1 /////////////////////////////////////////
2 //
3 //             OpenLieroX
4 //
5 // code under LGPL, based on JasonBs work,
6 // enhanced by Dark Charlie and Albert Zeyer
7 //
8 //
9 /////////////////////////////////////////
10 
11 
12 // Shoot list class
13 // Created 20/12/02
14 // Jason Boettcher
15 
16 
17 #include <assert.h>
18 
19 #include "LieroX.h"
20 #include "CShootList.h"
21 #include "CWorm.h"
22 #include "Protocol.h"
23 #include "MathLib.h"
24 #include "WeaponDesc.h"
25 
26 
27 ///////////////////
28 // Initialize the list
Initialize()29 bool CShootList::Initialize()
30 {
31 	m_nNumShootings = 0;
32 	m_fStartTime = AbsTime();
33 
34 	// TODO: use std::queue or std::list
35 	m_psShoot = new shoot_t[MAX_SHOOTINGS];
36 	if( m_psShoot == NULL )
37 		return false;
38 
39 	return true;
40 }
41 
42 
43 ///////////////////
44 // Shutdown the list
Shutdown()45 void CShootList::Shutdown()
46 {
47 	if( m_psShoot ) {
48 		delete[] m_psShoot;
49 		m_psShoot = NULL;
50 	}
51 
52 	m_nNumShootings = 0;
53 	m_fStartTime = AbsTime();
54 }
55 
56 
57 ///////////////////
58 // Clear the list
Clear()59 void CShootList::Clear()
60 {
61 	m_nNumShootings = 0;
62 	m_fStartTime = AbsTime();
63 }
64 
65 
66 ///////////////////
67 // Return a shot
getShot(int index)68 shoot_t *CShootList::getShot( int index )
69 {
70 	if( index >= 0 && index < m_nNumShootings )
71 		return &m_psShoot[index];
72 
73 	return NULL;
74 }
75 
76 
77 ///////////////////
78 // Add a shot to the list
79 // (done on server-side from GameServer::WormShoot)
addShoot(int weaponID,TimeDiff fTime,float fSpeed,int nAngle,CWorm * pcWorm,bool release)80 bool CShootList::addShoot( int weaponID, TimeDiff fTime, float fSpeed, int nAngle, CWorm *pcWorm, bool release )
81 {
82 	assert( pcWorm );
83 	assert( m_psShoot );
84 
85 	// Check if it isn't too full
86 	if( m_nNumShootings >= MAX_SHOOTINGS )
87 		return false;
88 
89 	// If this is the first shot in the list, set the start time
90 	if( m_fStartTime == AbsTime())
91 		m_fStartTime = tLX->currentTime;
92 
93 	shoot_t *psShot = &m_psShoot[ m_nNumShootings++ ];
94 
95 	// Fill in the info
96 	psShot->cPos = pcWorm->getPos();
97 	psShot->cWormVel = pcWorm->getVelocity();
98 	psShot->fTime = fTime;
99 	psShot->nAngle = nAngle;
100 	psShot->nRandom = pcWorm->getShotCount(); // uint32 to unit8 conversion
101 	psShot->nSpeed = (int)( fSpeed*100 );
102 	psShot->nWeapon = weaponID;
103 	psShot->nWormID = pcWorm->getID();
104 	psShot->release = release;
105 
106 	return true;
107 }
108 
109 
110 ///////////////////
111 // Write the shoot list to a bytestream
112 // Returns true if good (even if we didn't write anything)
113 // Returns false if the packet couldn't be written (overflow)
writePacket(CBytestream * bs,const Version & receiverVer)114 bool CShootList::writePacket( CBytestream *bs, const Version& receiverVer )
115 {
116 	CBytestream strm;
117 
118 	// If no shots are in the list, just leave
119 	if( m_nNumShootings == 0)
120 		return true;
121 
122 	// Single shot
123 	if( m_nNumShootings == 1 )
124 		writeSingle( &strm, receiverVer, 0 );
125 	else
126 		// Multiple shots
127 		writeMulti( &strm, receiverVer, 0 );
128 
129 
130 	// Otherwise, append the shootlist onto the bytestream
131 	// Don't append for now
132 	bs->Append( &strm );
133 	m_fLastWrite = tLX->currentTime;
134 
135 	return true;
136 }
137 
138 
139 ///////////////////
140 // A single shot packet
writeSingle(CBytestream * bs,const Version & receiverVer,int index)141 void CShootList::writeSingle( CBytestream *bs, const Version& receiverVer, int index )
142 {
143 	byte	flags = 0;
144 	shoot_t *psShot = &m_psShoot[index];
145 
146 	// Set the flags
147 	if( psShot->nAngle > 255 )
148 		flags |= SMF_LARGEANGLE;			// Large angle
149 	if( psShot->nSpeed > 255 || psShot->nSpeed < -255)
150 		flags |= SMF_LARGESPEED;			// Large speed
151 	if( psShot->nSpeed < 0 )
152 		flags |= SMF_NEGSPEED;				// Negative speed
153 
154 
155 	short x = (short)psShot->cPos.x;
156 	short y = (short)psShot->cPos.y;
157 	short vx = (short)psShot->cWormVel.x;
158 	short vy = (short)psShot->cWormVel.y;
159 
160 	// Write the packet
161 	bs->writeByte( S2C_SINGLESHOOT );
162 	bs->writeByte( flags );
163 	bs->writeByte( psShot->nWormID );
164 	bs->writeFloat( (float)psShot->fTime.seconds() );
165 	bs->writeByte( psShot->nWeapon );
166 	bs->write2Int12( x, y );
167 	bs->writeInt16( vx );
168 	bs->writeInt16( vy );
169 	bs->writeByte( psShot->nRandom );
170 
171 	if( flags & SMF_LARGEANGLE )
172 		bs->writeByte( psShot->nAngle-255 );
173 	else
174 		bs->writeByte( psShot->nAngle );
175 
176 	if( flags & SMF_LARGESPEED )
177 		bs->writeByte( psShot->nSpeed-255 );
178 	else if( flags & SMF_NEGSPEED ) {
179 		if(flags & SMF_LARGESPEED)
180 			bs->writeByte( (-psShot->nSpeed)-255 );
181 		else
182 			bs->writeByte( -psShot->nSpeed );
183 	}
184 	else
185 		bs->writeByte( psShot->nSpeed );
186 
187 	if(receiverVer >= OLXBetaVersion(0,58,1)) {
188 		bs->ResetBitPos();
189 		bs->writeBit(psShot->release);
190 		bs->SkipRestBits();
191 	}
192 }
193 
194 
195 ///////////////////
196 // A multiple shot packet
writeMulti(CBytestream * bs,const Version & receiverVer,int index)197 void CShootList::writeMulti( CBytestream *bs, const Version& receiverVer, int index )
198 {
199 	// If index is over the limit, exit
200 	if( index >= m_nNumShootings )
201 		return;
202 
203 	// If index is the last shot, send a single shot & exit
204 	if( index == m_nNumShootings-1 ) {
205 		writeSingle( bs, receiverVer, index );
206 		return;
207 	}
208 
209 
210 	int		num = 1;
211 	int		wmid = m_psShoot[index].nWormID;
212 	int		wpid = m_psShoot[index].nWeapon;
213 	int		i;
214 
215 	// Calculate how many shots we can/should send in a row
216 	// (based on worm id, weapon id, angle, time, number, speed & worm velocity)
217 	for(i=index+1; i<m_nNumShootings; i++) {
218 		if( m_psShoot[i].nWormID != wmid ||
219 			m_psShoot[i].nWeapon != wpid ||
220 			(m_psShoot[i].fTime - m_psShoot[i-1].fTime).milliseconds() > 255 ||
221 			abs(m_psShoot[i].nAngle - m_psShoot[i-1].nAngle) > 255 ||
222 			abs(m_psShoot[i].nSpeed - m_psShoot[i-1].nSpeed) > 255 ||
223 			abs((int)m_psShoot[i].cWormVel.x - (int)m_psShoot[i-1].cWormVel.x) > 255 ||
224 			abs((int)m_psShoot[i].cWormVel.y - (int)m_psShoot[i-1].cWormVel.y) > 255 ||
225 			num > 255) {
226 
227 			break;
228 		}
229 
230 		num++;
231 	}
232 
233 
234 	// If we can only send 1, send the 'single' packet
235 	if( num == 1 ) {
236 		writeSingle(bs, receiverVer, index);
237 
238 		// If we could only send one shot, but we still have more shots to send, send them
239 		if( m_nNumShootings > 1)
240 			writeMulti(bs, receiverVer, index+1);
241 		return;
242 	}
243 
244 
245 	// Write out the header
246 	byte	flags = 0;
247 	shoot_t *psShot = &m_psShoot[index];
248 
249 	// Set the flags
250 	if( psShot->nAngle > 255 )
251 		flags |= SMF_LARGEANGLE;			// Large angle
252 	if( psShot->nSpeed > 255 || psShot->nSpeed < -255)
253 		flags |= SMF_LARGESPEED;			// Large speed
254 	if( psShot->nSpeed < 0 )
255 		flags |= SMF_NEGSPEED;				// Negative speed
256 
257 
258 	short x = (short)psShot->cPos.x;
259 	short y = (short)psShot->cPos.y;
260 	short vx = (short)psShot->cWormVel.x;
261 	short vy = (short)psShot->cWormVel.y;
262 
263 	// Write the packet
264 	bs->writeByte( S2C_MULTISHOOT );
265 	bs->writeByte( flags );
266 	bs->writeByte( psShot->nWormID );
267 	bs->writeFloat( (float)psShot->fTime.seconds() );
268 	bs->writeByte( psShot->nWeapon );
269 	bs->writeByte( num );
270 	bs->write2Int12( x, y );
271 	bs->writeInt16( vx );
272 	bs->writeInt16( vy );
273 	bs->writeByte( psShot->nRandom );
274 
275 	if( flags & SMF_LARGEANGLE )
276 		bs->writeByte( psShot->nAngle-255 );
277 	else
278 		bs->writeByte( psShot->nAngle );
279 
280 	int speed = psShot->nSpeed;
281 
282 	if( flags & SMF_LARGESPEED )
283 		speed = psShot->nSpeed-255;
284 	if( flags & SMF_NEGSPEED ) {
285 		if(flags & SMF_LARGESPEED)
286 			speed = (-psShot->nSpeed)-255;
287 		else
288 			speed = -psShot->nSpeed;
289 	}
290 
291 	bs->writeByte( speed );
292 
293 	if(receiverVer >= OLXBetaVersion(0,58,1)) {
294 		bs->ResetBitPos();
295 		bs->writeBit(psShot->release);
296 		bs->SkipRestBits();
297 	}
298 
299 	// Send out the following shots
300 	for(i=1; i<num; i++)
301 		writeSmallShot( &m_psShoot[index+i-1], bs, receiverVer, index+i );
302 
303 	// Continue writing out multiple packets until all shots are written
304 	writeMulti( bs, receiverVer, index+num );
305 }
306 
307 
308 ///////////////////
309 // Write a small shot out
writeSmallShot(shoot_t * psFirst,CBytestream * bs,const Version & receiverVer,int index)310 void CShootList::writeSmallShot( shoot_t *psFirst, CBytestream *bs, const Version& receiverVer, int index )
311 {
312 	byte	flags = 0;
313 	byte	extraflags = 0;
314 
315 	assert( index < m_nNumShootings );
316 
317 	shoot_t	*psShot = &m_psShoot[index];
318 
319 
320 	int xoff = (int)( psShot->cPos.x - psFirst->cPos.x );
321 	int yoff = (int)( psShot->cPos.x - psFirst->cPos.x );
322 	xoff = abs(xoff);
323 	yoff = abs(yoff);
324 
325 	// Set the flags
326 	if( psShot->fTime != psFirst->fTime )
327 		flags |= SHF_TIMEOFF;
328 	if( (int)psShot->cPos.x != (int)psFirst->cPos.x )
329 		flags |= SHF_XPOSOFF;
330 	if( (int)psShot->cPos.y != (int)psFirst->cPos.y )
331 		flags |= SHF_YPOSOFF;
332 	if( psShot->nAngle != psFirst->nAngle )
333 		flags |= SHF_ANGLEOFF;
334 	if( psShot->nSpeed != psFirst->nSpeed )
335 		flags |= SHF_SPEEDOFF;
336 	if( (int)psShot->cPos.x < (int)psFirst->cPos.x ) {
337 		flags |= SHF_NG_XPOSOFF;
338 		flags &= ~SHF_XPOSOFF;
339 	}
340 	if( (int)psShot->cPos.y < (int)psFirst->cPos.y ) {
341 		flags |= SHF_NG_YPOSOFF;
342 		flags &= ~SHF_YPOSOFF;
343 	}
344 
345 	// Extra flags
346 	if( psShot->nAngle < psFirst->nAngle ) {
347 		extraflags |= SHF_NG_ANGLEOFF;
348 		flags &= ~SHF_ANGLEOFF;
349 	}
350 	if( psShot->nSpeed < psFirst->nSpeed ) {
351 		extraflags |= SHF_NG_SPEEDOFF;
352 		flags &= ~SHF_SPEEDOFF;
353 	}
354 	if( xoff >= 32 )
355 		extraflags |= SHF_LARGEXOFF;
356 	if( yoff >= 32 )
357 		extraflags |= SHF_LARGEYOFF;
358 
359 	if( (int)psShot->cWormVel.x != (int)psFirst->cWormVel.x )
360 		flags |= SHF_XWRMVEL;
361 	if( (int)psShot->cWormVel.y != (int)psFirst->cWormVel.y )
362 		flags |= SHF_YWRMVEL;
363 	if( (int)psShot->cWormVel.x < (int)psFirst->cWormVel.x ) {
364 		extraflags &= ~SHF_XWRMVEL;
365 		extraflags |= SHF_NG_XWRMVEL;
366 	}
367 	if( (int)psShot->cWormVel.y < (int)psFirst->cWormVel.y ) {
368 		extraflags &= ~SHF_YWRMVEL;
369 		extraflags |= SHF_NG_YWRMVEL;
370 	}
371 
372 
373 	if( extraflags )
374 		flags |= SHF_EXTRAFLAGS;
375 
376 
377 	// For now, do some asserts for data that can't be written in the space
378 	assert( abs( psShot->nAngle - psFirst->nAngle ) <= 255 );
379 	//assert( abs( psShot->nSpeed - psFirst->nSpeed ) <= 255 );
380 
381 
382 	// Write the data
383 	bs->writeByte( flags );
384 	if( flags & SHF_EXTRAFLAGS )
385 		bs->writeByte( extraflags );
386 	if( flags & SHF_TIMEOFF )
387 		bs->writeByte( (int)( (psShot->fTime - psFirst->fTime).milliseconds()) );
388 
389 	// X offset
390 	if( flags & SHF_XPOSOFF || flags & SHF_NG_XPOSOFF ) {
391 		if( extraflags & SHF_LARGEXOFF )
392 			bs->writeByte( xoff );
393 	}
394 	// Y offset
395 	if( flags & SHF_YPOSOFF || flags & SHF_NG_YPOSOFF ) {
396 		if( extraflags & SHF_LARGEYOFF )
397 			bs->writeByte( yoff );
398 	}
399 
400 	// X & Y Small offset
401 	if( (flags & SHF_XPOSOFF || flags & SHF_NG_XPOSOFF) && (flags & SHF_YPOSOFF || flags & SHF_NG_YPOSOFF) ) {
402 		if( !(extraflags & SHF_LARGEXOFF) && !(extraflags & SHF_LARGEYOFF) )
403 			bs->write2Int4( xoff, yoff );
404 	}
405 
406 	if( flags & SHF_ANGLEOFF )
407 		bs->writeByte( psShot->nAngle - psFirst->nAngle );
408 	if( flags & SHF_SPEEDOFF )
409 		bs->writeByte( psShot->nSpeed - psFirst->nSpeed );
410 	if( extraflags & SHF_NG_ANGLEOFF )
411 		bs->writeByte( psFirst->nAngle - psShot->nAngle );
412 	if( extraflags & SHF_NG_SPEEDOFF )
413 		bs->writeByte( psFirst->nSpeed - psShot->nSpeed );
414 
415 	// Worm velocity
416 	if( extraflags & SHF_XWRMVEL )
417 		bs->writeByte( (int)psShot->cWormVel.x - (int)psFirst->cWormVel.x );
418 	if( extraflags & SHF_YWRMVEL )
419 		bs->writeByte( (int)psShot->cWormVel.y - (int)psFirst->cWormVel.y );
420 	if( extraflags & SHF_NG_XWRMVEL )
421 		bs->writeByte( (int)psFirst->cWormVel.x - (int)psShot->cWormVel.x );
422 	if( extraflags & SHF_NG_YWRMVEL )
423 		bs->writeByte( (int)psFirst->cWormVel.y - (int)psShot->cWormVel.y );
424 
425 	if(receiverVer >= OLXBetaVersion(0,58,1)) {
426 		bs->ResetBitPos();
427 		bs->writeBit(psShot->release);
428 		bs->SkipRestBits();
429 	}
430 }
431 
432 
433 
434 ///////////////////
435 // Read a single shot packet
readSingle(CBytestream * bs,const Version & senderVer,int max_weapon_id)436 void CShootList::readSingle( CBytestream *bs, const Version& senderVer, int max_weapon_id )
437 {
438 	// Clear the list
439 	Clear();
440 
441 	shoot_t *psShot = &m_psShoot[0];
442 
443 
444 	// Read the packet
445 	byte flags = bs->readByte();
446 	psShot->nWormID = bs->readByte(); // Used for indexing
447 	psShot->fTime = MAX(bs->readFloat(), 0.0f);
448 	psShot->nWeapon = CLAMP((int)bs->readByte(), 0, max_weapon_id); // Used for indexing
449 	short x, y;
450 	bs->read2Int12( x, y );
451 	short vx = bs->readInt16();
452 	short vy = bs->readInt16();
453 	psShot->nRandom = bs->readByte();
454 
455 	psShot->nAngle = bs->readByte();
456 	int speed = bs->readByte();
457 	psShot->nSpeed = speed;
458 
459 	if( flags & SMF_LARGEANGLE )
460 		psShot->nAngle += 255;
461 
462 	if( flags & SMF_LARGESPEED )
463 		psShot->nSpeed = speed+255;
464 	if( flags & SMF_NEGSPEED ) {
465 		if( flags & SMF_LARGESPEED )
466 			psShot->nSpeed = -(speed+255);
467 		else
468 			psShot->nSpeed = -speed;
469 	}
470 
471 
472 	// Convert the pos
473 	psShot->cPos = CVec( (float)x, (float)y );
474 
475 	// Convert the velocity
476 	psShot->cWormVel = CVec( (float)vx, (float)vy );
477 
478 	if(senderVer >= OLXBetaVersion(0,58,1)) {
479 		bs->ResetBitPos();
480 		psShot->release = bs->readBit();
481 		bs->SkipRestBits();
482 	}
483 	else
484 		psShot->release = false;
485 
486 	m_nNumShootings++;
487 }
488 
489 
490 ///////////////////
491 // Read a multi shot packet
readMulti(CBytestream * bs,const Version & senderVer,int max_weapon_id)492 void CShootList::readMulti( CBytestream *bs, const Version& senderVer, int max_weapon_id )
493 {
494 	// Clear the list
495 	Clear();
496 
497 	// Read the header
498 	byte	flags = 0;
499 	short	x, y, vx, vy;
500 	int		i;
501 	int		num = 0;
502 	shoot_t *psShot = m_psShoot;
503 
504 	flags = bs->readByte();
505 	psShot->nWormID = bs->readByte(); // Used for indexing
506 	psShot->fTime = MAX(bs->readFloat(), 0.0f);
507 	psShot->nWeapon = CLAMP((int)bs->readByte(), 0, max_weapon_id);
508 	num = MIN(bs->readByte(), MAX_SHOOTINGS - 1);
509 	bs->read2Int12( x, y );
510 	vx = bs->readInt16();
511 	vy = bs->readInt16();
512 	psShot->nRandom = bs->readByte();
513 
514 	psShot->nAngle = bs->readByte();
515 	int speed = bs->readByte();
516 	psShot->nSpeed = speed;
517 
518 	if( flags & SMF_LARGEANGLE )
519 		psShot->nAngle += 255;
520 
521 	if( flags & SMF_LARGESPEED )
522 		psShot->nSpeed = speed+255;
523 	if( flags & SMF_NEGSPEED ) {
524 		if( flags & SMF_LARGESPEED )
525 			psShot->nSpeed = -(speed+255);
526 		else
527 			psShot->nSpeed = -speed;
528 	}
529 
530 	// Convert the pos
531 	psShot->cPos = CVec( (float)x, (float)y );
532 
533 	// Convert the velocity
534 	psShot->cWormVel = CVec( (float)vx, (float)vy );
535 
536 	if(senderVer >= OLXBetaVersion(0,58,1)) {
537 		bs->ResetBitPos();
538 		psShot->release = bs->readBit();
539 		bs->SkipRestBits();
540 	}
541 	else
542 		psShot->release = false;
543 
544 	m_nNumShootings++;
545 
546 	// Read the following shots
547 	for(i=1; i<num; i++)
548 		readSmallShot( &m_psShoot[i-1], bs, senderVer, i );
549 }
550 
551 
552 ///////////////////
553 // Read a small shot
readSmallShot(shoot_t * psFirst,CBytestream * bs,const Version & senderVer,int index)554 void CShootList::readSmallShot( shoot_t *psFirst, CBytestream *bs, const Version& senderVer, int index )
555 {
556 	byte	flags = 0;
557 	byte	extraflags = 0;
558 	int		x = 0;
559 	int		y = 0;
560 
561 	shoot_t	*psShot = &m_psShoot[index];
562 
563 	// Copy the base data, so we only apply the changes to the shot
564 	*psShot = *psFirst;
565 
566 	psShot->nRandom++;
567 
568 	flags = bs->readByte();
569 	if( flags & SHF_EXTRAFLAGS )
570 		extraflags = bs->readByte();
571 
572 	// AbsTime offset
573 	if( flags & SHF_TIMEOFF ) {
574 		float time = (float)bs->readByte();
575 		psShot->fTime += TimeDiff(time/1000.0f);
576 	}
577 
578 	// X Large offset
579 	if( flags & SHF_XPOSOFF || flags & SHF_NG_XPOSOFF ) {
580 		if( extraflags & SHF_LARGEXOFF )
581 			x = bs->readByte();
582 	}
583 
584 	// Y Large offset
585 	if( flags & SHF_YPOSOFF || flags & SHF_NG_YPOSOFF ) {
586 		if( extraflags & SHF_LARGEYOFF )
587 			y = bs->readByte();
588 	}
589 
590 	// X & Y Small offset
591 	if( (flags & SHF_XPOSOFF || flags & SHF_NG_XPOSOFF) && (flags & SHF_YPOSOFF || flags & SHF_NG_YPOSOFF) ) {
592 		if( !(extraflags & SHF_LARGEXOFF) && !(extraflags & SHF_LARGEYOFF) ) {
593 			short sx, sy;
594 			bs->read2Int4( sx, sy );
595 			x = sx; y = sy;
596 		}
597 	}
598 
599 	// Negate the position offsets
600 	if( flags & SHF_NG_XPOSOFF )
601 		x = -x;
602 	if( flags & SHF_NG_YPOSOFF )
603 		y = -y;
604 
605 
606 	if( flags & SHF_ANGLEOFF ) {
607 		int angle = bs->readByte();
608 		psShot->nAngle += angle;
609 	}
610 	if( flags & SHF_SPEEDOFF ) {
611 		int speed = bs->readByte();
612 		psShot->nSpeed += speed;
613 	}
614 
615 	if( extraflags & SHF_NG_ANGLEOFF ) {
616 		int angle = bs->readByte();
617 		psShot->nAngle -= angle;
618 	}
619 	if( extraflags & SHF_NG_SPEEDOFF ) {
620 		int speed = bs->readByte();
621 		psShot->nSpeed -= speed;
622 	}
623 
624 	// Worm velocity
625 	if( extraflags & SHF_XWRMVEL ) {
626 		int velx = bs->readByte();
627 		psShot->cWormVel.x=( psShot->cWormVel.x + (float)velx );
628 	}
629 	if( extraflags & SHF_YWRMVEL ) {
630 		int vely = bs->readByte();
631 		psShot->cWormVel.y=( psShot->cWormVel.y + (float)vely );
632 	}
633 	if( extraflags & SHF_NG_XWRMVEL ) {
634 		int velx = bs->readByte();
635 		psShot->cWormVel.x=( psShot->cWormVel.x - (float)velx );
636 	}
637 	if( extraflags & SHF_NG_YWRMVEL ) {
638 		int vely = bs->readByte();
639 		psShot->cWormVel.y=( psShot->cWormVel.y - (float)vely );
640 	}
641 
642 	if(senderVer >= OLXBetaVersion(0,58,1)) {
643 		bs->ResetBitPos();
644 		psShot->release = bs->readBit();
645 		bs->SkipRestBits();
646 	}
647 	else
648 		psShot->release = false;
649 
650 	m_nNumShootings++;
651 }
652 
653 
skipSingle(CBytestream * bs,const Version & senderVer)654 bool CShootList::skipSingle(CBytestream *bs, const Version& senderVer)  {
655 	if(senderVer >= OLXBetaVersion(0,58,1))
656 		return bs->Skip(18);
657 	else
658 		return bs->Skip(17);
659 }
skipMulti(CBytestream * bs,const Version & senderVer)660 bool CShootList::skipMulti(CBytestream *bs, const Version& senderVer)  {
661 	bs->Skip(7);
662 	byte num = bs->readByte();
663 	bs->Skip(10);
664 	if(senderVer >= OLXBetaVersion(0,58,1)) bs->Skip(1);
665 	for (byte i = 0; i < num - 1;i++) skipSmallShot(bs, senderVer);
666 	return bs->isPosAtEnd();
667 }
668 
669 ////////////////
670 // Skip the small shot packet
skipSmallShot(CBytestream * bs,const Version & senderVer)671 bool CShootList::skipSmallShot(CBytestream *bs, const Version& senderVer)
672 {
673 	// For comments see the above function
674 	byte flags = bs->readByte();
675 	byte extraflags = 0;
676 	if (flags & SHF_EXTRAFLAGS)
677 		extraflags = bs->readByte();
678 
679 	if (flags & SHF_TIMEOFF)
680 		bs->Skip(1);
681 
682 	if( flags & SHF_XPOSOFF || flags & SHF_NG_XPOSOFF )
683 		if( extraflags & SHF_LARGEXOFF )
684 			bs->Skip(1);
685 
686 	if( flags & SHF_YPOSOFF || flags & SHF_NG_YPOSOFF )
687 		if( extraflags & SHF_LARGEYOFF )
688 			bs->Skip(1);
689 
690 	if( (flags & SHF_XPOSOFF || flags & SHF_NG_XPOSOFF) && (flags & SHF_YPOSOFF || flags & SHF_NG_YPOSOFF) )
691 		if( !(extraflags & SHF_LARGEXOFF) && !(extraflags & SHF_LARGEYOFF) )
692 			bs->Skip(1);
693 
694 	if( flags & SHF_ANGLEOFF )
695 		bs->Skip(1);
696 
697 	if( flags & SHF_SPEEDOFF )
698 		bs->Skip(1);
699 
700 	if( extraflags & SHF_NG_ANGLEOFF )
701 		bs->Skip(1);
702 
703 	if( extraflags & SHF_NG_SPEEDOFF )
704 		bs->Skip(1);
705 
706 	if( extraflags & SHF_XWRMVEL )
707 		bs->Skip(1);
708 
709 	if( extraflags & SHF_YWRMVEL )
710 		bs->Skip(1);
711 
712 	if( extraflags & SHF_NG_XWRMVEL )
713 		bs->Skip(1);
714 
715 	if( extraflags & SHF_NG_YWRMVEL )
716 		bs->Skip(1);
717 
718 	if(senderVer >= OLXBetaVersion(0,58,1)) bs->Skip(1);
719 
720 	return bs->isPosAtEnd();
721 }
722