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 void EntityStateQW_ReadPlayerUpdate(void)
45 int slot = MSG_ReadByte(&cl_message);
46 int enumber = slot + 1;
53 entity_t *ent = cl.entities + enumber;
57 // slide the current state into the previous
58 ent->state_previous = ent->state_current;
61 s = &ent->state_current;
63 s->active = ACTIVE_NETWORK;
65 s->colormap = enumber;
66 playerflags = MSG_ReadShort(&cl_message);
67 MSG_ReadVector(&cl_message, s->origin, cls.protocol);
68 s->frame = MSG_ReadByte(&cl_message);
70 VectorClear(viewangles);
71 VectorClear(velocity);
73 if (playerflags & QW_PF_MSEC)
75 // time difference between last update this player sent to the server,
76 // and last input we sent to the server (this packet is in response to
77 // our input, so msec is how long ago the last update of this player
78 // entity occurred, compared to our input being received)
79 msec = MSG_ReadByte(&cl_message);
83 if (playerflags & QW_PF_COMMAND)
85 bits = MSG_ReadByte(&cl_message);
86 if (bits & QW_CM_ANGLE1)
87 viewangles[0] = MSG_ReadAngle16i(&cl_message); // cmd->angles[0]
88 if (bits & QW_CM_ANGLE2)
89 viewangles[1] = MSG_ReadAngle16i(&cl_message); // cmd->angles[1]
90 if (bits & QW_CM_ANGLE3)
91 viewangles[2] = MSG_ReadAngle16i(&cl_message); // cmd->angles[2]
92 if (bits & QW_CM_FORWARD)
93 MSG_ReadShort(&cl_message); // cmd->forwardmove
94 if (bits & QW_CM_SIDE)
95 MSG_ReadShort(&cl_message); // cmd->sidemove
97 MSG_ReadShort(&cl_message); // cmd->upmove
98 if (bits & QW_CM_BUTTONS)
99 (void) MSG_ReadByte(&cl_message); // cmd->buttons
100 if (bits & QW_CM_IMPULSE)
101 (void) MSG_ReadByte(&cl_message); // cmd->impulse
102 (void) MSG_ReadByte(&cl_message); // cmd->msec
104 if (playerflags & QW_PF_VELOCITY1)
105 velocity[0] = MSG_ReadShort(&cl_message);
106 if (playerflags & QW_PF_VELOCITY2)
107 velocity[1] = MSG_ReadShort(&cl_message);
108 if (playerflags & QW_PF_VELOCITY3)
109 velocity[2] = MSG_ReadShort(&cl_message);
110 if (playerflags & QW_PF_MODEL)
111 s->modelindex = MSG_ReadByte(&cl_message);
113 s->modelindex = cl.qw_modelindex_player;
114 if (playerflags & QW_PF_SKINNUM)
115 s->skin = MSG_ReadByte(&cl_message);
116 if (playerflags & QW_PF_EFFECTS)
117 QW_TranslateEffects(s, MSG_ReadByte(&cl_message));
118 if (playerflags & QW_PF_WEAPONFRAME)
119 weaponframe = MSG_ReadByte(&cl_message);
123 if (enumber == cl.playerentity)
125 // if this is an update on our player, update the angles
126 VectorCopy(cl.viewangles, viewangles);
129 // calculate the entity angles from the viewangles
130 s->angles[0] = viewangles[0] * -0.0333;
131 s->angles[1] = viewangles[1];
133 s->angles[2] = V_CalcRoll(s->angles, velocity)*4;
135 // if this is an update on our player, update interpolation state
136 if (enumber == cl.playerentity)
138 VectorCopy (cl.mpunchangle[0], cl.mpunchangle[1]);
139 VectorCopy (cl.mpunchvector[0], cl.mpunchvector[1]);
140 VectorCopy (cl.mvelocity[0], cl.mvelocity[1]);
141 cl.mviewzoom[1] = cl.mviewzoom[0];
144 cl.mpunchangle[0][0] = 0;
145 cl.mpunchangle[0][1] = 0;
146 cl.mpunchangle[0][2] = 0;
147 cl.mpunchvector[0][0] = 0;
148 cl.mpunchvector[0][1] = 0;
149 cl.mpunchvector[0][2] = 0;
150 cl.mvelocity[0][0] = 0;
151 cl.mvelocity[0][1] = 0;
152 cl.mvelocity[0][2] = 0;
155 VectorCopy(velocity, cl.mvelocity[0]);
156 cl.stats[STAT_WEAPONFRAME] = weaponframe;
157 if (playerflags & QW_PF_GIB)
158 cl.stats[STAT_VIEWHEIGHT] = 8;
159 else if (playerflags & QW_PF_DEAD)
160 cl.stats[STAT_VIEWHEIGHT] = -16;
162 cl.stats[STAT_VIEWHEIGHT] = 22;
165 // set the cl.entities_active flag
166 cl.entities_active[enumber] = (s->active == ACTIVE_NETWORK);
167 // set the update time
168 s->time = cl.mtime[0] - msec * 0.001; // qw has no clock
169 // check if we need to update the lerp stuff
170 if (s->active == ACTIVE_NETWORK)
171 CL_MoveLerpEntityStates(&cl.entities[enumber]);
174 static void EntityStateQW_ReadEntityUpdate(entity_state_t *s, int bits)
177 s->active = ACTIVE_NETWORK;
178 s->number = bits & 511;
180 if (bits & QW_U_MOREBITS)
181 bits |= MSG_ReadByte(&cl_message);
183 // store the QW_U_SOLID bit here?
185 if (bits & QW_U_MODEL)
186 s->modelindex = MSG_ReadByte(&cl_message);
187 if (bits & QW_U_FRAME)
188 s->frame = MSG_ReadByte(&cl_message);
189 if (bits & QW_U_COLORMAP)
190 s->colormap = MSG_ReadByte(&cl_message);
191 if (bits & QW_U_SKIN)
192 s->skin = MSG_ReadByte(&cl_message);
193 if (bits & QW_U_EFFECTS)
194 QW_TranslateEffects(s, qweffects = MSG_ReadByte(&cl_message));
195 if (bits & QW_U_ORIGIN1)
196 s->origin[0] = MSG_ReadCoord13i(&cl_message);
197 if (bits & QW_U_ANGLE1)
198 s->angles[0] = MSG_ReadAngle8i(&cl_message);
199 if (bits & QW_U_ORIGIN2)
200 s->origin[1] = MSG_ReadCoord13i(&cl_message);
201 if (bits & QW_U_ANGLE2)
202 s->angles[1] = MSG_ReadAngle8i(&cl_message);
203 if (bits & QW_U_ORIGIN3)
204 s->origin[2] = MSG_ReadCoord13i(&cl_message);
205 if (bits & QW_U_ANGLE3)
206 s->angles[2] = MSG_ReadAngle8i(&cl_message);
208 if (developer_networkentities.integer >= 2)
210 Con_Printf("ReadFields e%i", s->number);
211 if (bits & QW_U_MODEL)
212 Con_Printf(" U_MODEL %i", s->modelindex);
213 if (bits & QW_U_FRAME)
214 Con_Printf(" U_FRAME %i", s->frame);
215 if (bits & QW_U_COLORMAP)
216 Con_Printf(" U_COLORMAP %i", s->colormap);
217 if (bits & QW_U_SKIN)
218 Con_Printf(" U_SKIN %i", s->skin);
219 if (bits & QW_U_EFFECTS)
220 Con_Printf(" U_EFFECTS %i", qweffects);
221 if (bits & QW_U_ORIGIN1)
222 Con_Printf(" U_ORIGIN1 %f", s->origin[0]);
223 if (bits & QW_U_ANGLE1)
224 Con_Printf(" U_ANGLE1 %f", s->angles[0]);
225 if (bits & QW_U_ORIGIN2)
226 Con_Printf(" U_ORIGIN2 %f", s->origin[1]);
227 if (bits & QW_U_ANGLE2)
228 Con_Printf(" U_ANGLE2 %f", s->angles[1]);
229 if (bits & QW_U_ORIGIN3)
230 Con_Printf(" U_ORIGIN3 %f", s->origin[2]);
231 if (bits & QW_U_ANGLE3)
232 Con_Printf(" U_ANGLE3 %f", s->angles[2]);
233 if (bits & QW_U_SOLID)
234 Con_Printf(" U_SOLID");
239 entityframeqw_database_t *EntityFrameQW_AllocDatabase(mempool_t *pool)
241 entityframeqw_database_t *d;
242 d = (entityframeqw_database_t *)Mem_Alloc(pool, sizeof(*d));
246 void EntityFrameQW_FreeDatabase(entityframeqw_database_t *d)
251 void EntityFrameQW_CL_ReadFrame(qboolean delta)
253 qboolean invalid = false;
254 int number, oldsnapindex, newsnapindex, oldindex, newindex, oldnum, newnum;
256 entityframeqw_database_t *d;
257 entityframeqw_snapshot_t *oldsnap, *newsnap;
259 if (!cl.entitydatabaseqw)
260 cl.entitydatabaseqw = EntityFrameQW_AllocDatabase(cls.levelmempool);
261 d = cl.entitydatabaseqw;
263 // there is no cls.netcon in demos, so this reading code can't access
264 // cls.netcon-> at all... so cls.qw_incoming_sequence and
265 // cls.qw_outgoing_sequence are updated every time the corresponding
266 // cls.netcon->qw. variables are updated
267 // read the number of this frame to echo back in next input packet
268 cl.qw_validsequence = cls.qw_incoming_sequence;
269 newsnapindex = cl.qw_validsequence & QW_UPDATE_MASK;
270 newsnap = d->snapshot + newsnapindex;
271 memset(newsnap, 0, sizeof(*newsnap));
275 number = MSG_ReadByte(&cl_message);
276 oldsnapindex = cl.qw_deltasequence[newsnapindex];
277 if ((number & QW_UPDATE_MASK) != (oldsnapindex & QW_UPDATE_MASK))
278 Con_DPrintf("WARNING: from mismatch\n");
279 if (oldsnapindex != -1)
281 if (cls.qw_outgoing_sequence - oldsnapindex >= QW_UPDATE_BACKUP-1)
283 Con_DPrintf("delta update too old\n");
284 newsnap->invalid = invalid = true; // too old
287 oldsnap = d->snapshot + (oldsnapindex & QW_UPDATE_MASK);
293 // if we can't decode this frame properly, report that to the server
295 cl.qw_validsequence = 0;
297 // read entity numbers until we find a 0x0000
298 // (which would be an empty update on world entity, but is actually a terminator)
299 newsnap->num_entities = 0;
303 int word = (unsigned short)MSG_ReadShort(&cl_message);
304 if (cl_message.badread)
305 return; // just return, the main parser will print an error
306 newnum = word == 0 ? 512 : (word & 511);
307 oldnum = delta ? (oldindex >= oldsnap->num_entities ? 9999 : oldsnap->entities[oldindex].number) : 9999;
309 // copy unmodified oldsnap entities
310 while (newnum > oldnum) // delta only
312 if (developer_networkentities.integer >= 2)
313 Con_Printf("copy %i\n", oldnum);
314 // copy one of the old entities
315 if (newsnap->num_entities >= QW_MAX_PACKET_ENTITIES)
316 Host_Error("EntityFrameQW_CL_ReadFrame: newsnap->num_entities == MAX_PACKETENTITIES");
317 newsnap->entities[newsnap->num_entities] = oldsnap->entities[oldindex++];
318 newsnap->num_entities++;
319 oldnum = oldindex >= oldsnap->num_entities ? 9999 : oldsnap->entities[oldindex].number;
325 if (developer_networkentities.integer >= 2)
327 if (word & QW_U_REMOVE)
328 Con_Printf("remove %i\n", newnum);
329 else if (newnum == oldnum)
330 Con_Printf("delta %i\n", newnum);
332 Con_Printf("baseline %i\n", newnum);
335 if (word & QW_U_REMOVE)
337 if (newnum != oldnum && !delta && !invalid)
339 cl.qw_validsequence = 0;
340 Con_Printf(CON_WARN "WARNING: U_REMOVE %i on full update\n", newnum);
345 if (newsnap->num_entities >= QW_MAX_PACKET_ENTITIES)
346 Host_Error("EntityFrameQW_CL_ReadFrame: newsnap->num_entities == MAX_PACKETENTITIES");
347 newsnap->entities[newsnap->num_entities] = (newnum == oldnum) ? oldsnap->entities[oldindex] : cl.entities[newnum].state_baseline;
348 EntityStateQW_ReadEntityUpdate(newsnap->entities + newsnap->num_entities, word);
349 newsnap->num_entities++;
352 if (newnum == oldnum)
356 // expand cl.num_entities to include every entity we've seen this game
357 newnum = newsnap->num_entities ? newsnap->entities[newsnap->num_entities - 1].number : 1;
358 if (cl.num_entities <= newnum)
360 cl.num_entities = newnum + 1;
361 if (cl.max_entities < newnum + 1)
362 CL_ExpandEntities(newnum);
365 // now update the non-player entities from the snapshot states
366 number = cl.maxclients + 1;
367 for (newindex = 0;;newindex++)
369 newnum = newindex >= newsnap->num_entities ? cl.num_entities : newsnap->entities[newindex].number;
370 // kill any missing entities
371 for (;number < newnum;number++)
373 if (cl.entities_active[number])
375 cl.entities_active[number] = false;
376 cl.entities[number].state_current.active = ACTIVE_NOT;
379 if (number >= cl.num_entities)
382 ent = &cl.entities[number];
383 ent->state_previous = ent->state_current;
384 ent->state_current = newsnap->entities[newindex];
385 ent->state_current.time = cl.mtime[0];
386 CL_MoveLerpEntityStates(ent);
387 // the entity lives again...
388 cl.entities_active[number] = true;