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