1 /***************************************************************************
2 * TEKSTAT.C - sprite status and interactiob code for Tekwar *
3 * *
4 * *
5 ***************************************************************************/
6
7 #include "build.h"
8 #include "names.h"
9 #include "pragmas.h"
10 #include "cache1d.h"
11 #include "mmulti.h"
12
13 #include "tekwar.h"
14
15
16 //#define NEWSTAT_DEBUG
17 //#define NETDEBUG
18 FILE *dbgfp2;
19
20 #define MAXFRAMES 8
21
22 #define SPR_LOTAG_SPAWNCHASE 2000
23 #define SPR_LOTAG_PLAYBACK 2001
24 #define SPR_LOTAG_PUSHABLE 2002
25 #define SPR_LOTAG_MORPH 2003
26 #define SPR_LOTAG_PICKUP 2004
27 #define SPR_LOTAG_FLAMMABLE 2005
28 #define SPR_LOTAG_PICKUP_FLAMMABLE 2006
29 #define SPR_LOTAG_PUSHABLE_FLAMMABLE 2007
30
31 #define SECT_LOTAG_TRIGGERSPRITE 5020
32 #define SECT_LOTAG_SHOWMESSAGE 5030
33 #define SECT_LOTAG_NOSTANDING 5040
34 #define SECT_LOTAG_OFFLIMITS_CIVILLIAN 5050
35 #define SECT_LOTAG_OFFLIMITS_ALL 5055
36 #define SECT_LOTAG_CLIMB 5060
37 #define SECT_LOTAG_SUNKEN 5065
38
39 #define DONTBOTHERDISTANCE 20480
40 #define HEARGUNSHOTDIST 10240
41
42 #define INANIMATE 0
43 #define PLAYER 8
44 #define INACTIVE 100
45 #define STANDING 201
46 #define AMBUSH 202
47 #define GUARD 203
48 #define STALK 204
49 #define FLEE 205
50 #define CHASE 206
51 #define PATROL 207
52 #define CRAWL 208
53 #define STROLL 209
54 #define VIRUS 250
55 #define PLRVIRUS 255
56 #define ATTACK 300
57 #define DEATH 301
58 #define PAIN 302
59 #define TWITCH 303
60 #define MORPH 304
61 #define SQUAT 305
62 #define UNSQUAT 306
63 #define JUMP 307
64 #define LEAP 308
65 #define DODGE 309
66 #define UNDODGE 310
67 #define HIDE 311
68 #define UNHIDE 312
69 #define DELAYEDATTACK 313
70 #define MIRRORMAN1 320
71 #define MIRRORMAN2 321
72 #define FLOATING 322
73 #define PROJHIT 400
74 #define PROJECTILE 401
75 #define TOSS 402
76 #define PINBALL 403
77 #define KINDLING 405
78 #define DROPSIES 406
79 #define RUNTHRU 407
80 #define BLOODFLOW 408
81 #define FLY 500
82 #define RODENT 502
83 #define TIMEBOMB 602
84 #define STACKED 610
85 #define FALL 611
86 #define GENEXPLODE1 800
87 #define GENEXPLODE2 801
88 #define VANISH 999
89 #define KAPUT MAXSTATUS
90
91 #define FORCEPROJECTILESTAT 710
92 #define DARTPROJECTILESTAT 712
93 #define BOMBPROJECTILESTAT 714
94 #define BOMBPROJECTILESTAT2 716
95 #define MOVEBODYPARTSSTAT 900
96
97 #define ENEMYCRITICALCONDITION 25
98
99 #define FX_NULL 0x0000
100 #define FX_HASREDCARD 0x0001
101 #define FX_HASBLUECARD 0x0002
102 #define FX_ANDROID 0x0004
103 #define FX_HOLOGRAM 0x0008
104
105 #define FX_NXTSTTVANISH 0x0010
106 #define FX_NXTSTTPAIN 0x0020
107 #define FX_NXTSTTDEATH 0x0040
108
109 #define NO_PIC 0
110
111 #define MINATTACKDIST 8192L
112 #define CHASEATTDIST 8192L
113 #define GUARDATTDIST 6144L
114 #define STALKATTDIST 8192L
115 #define SCARECIVILLIANDISTANCE 102400
116
117 #define RMOD2(s) ( ((krand_intercept(s))>0x00008000) )
118 #define RMOD3(s) ( ((krand_intercept(s))>0x00008000)+(((krand_intercept(s))>>1)&1L) )
119 #define RMOD4(s) ( (((krand_intercept(s))>>3)&0x0000000F)&3L )
120 #define RMOD10(s) ( (krand_intercept(s))&9L )
121 #define RMOD16(s) ( (krand_intercept(s))&15L )
122
123 int pickupclock;
124 uspritetype pickup;
125 struct picattribtype picinfo;
126 struct picattribtype *picinfoptr=&picinfo;
127
128 #define MAXBOBS 32
129 int bobbing[MAXBOBS] = {
130 0, 2, 4, 6, 8, 10, 12, 14,
131 16, 14, 12, 10, 8, 6, 4, 2,
132 0, -2, -4, -6, -8,-10,-12,-14,
133 -16,-14,-12,-10, -8, -6, -4, -2
134 };
135
136 // angles, 0 east start, 22.5deg(==128scaled) resolution
137 short leftof[17] = { 1920, 0, 128, 256,
138 384, 512, 640, 768,
139 896, 1024, 1152, 1280,
140 1408, 1536, 1664, 1792, 1920 };
141
142 short rightof[17] = { 128, 256, 384, 512,
143 640, 768, 896, 1024,
144 1152, 1280, 1408, 1536,
145 1664, 1792, 1920, 0, 128 };
146
147 #ifdef __GNUC__
148 # if __GNUC__ == 4 && __GNUC_MINOR__ >= 7
149 # define TPACK __attribute__ ((packed, gcc_struct))
150 # else
151 # define TPACK __attribute__ ((packed))
152 # endif
153 #else
154 #define TPACK
155 #endif
156
157 #ifdef _MSC_VER
158 #pragma pack(1)
159 #endif
160
161 #ifdef __WATCOMC__
162 #pragma pack(push,1);
163 #endif
164
165 struct TPACK XTsavetype {
166 short XTnum;
167 struct spriteextension sprXT;
168 };
169 struct XTsavetype XTsave;
170 struct TPACK XTtrailertype {
171 int numXTs;
172 int start;
173 char mapname[13];
174 char ID[13];
175 };
176 struct XTtrailertype XTtrailer;
177 #define TRAILERID "**MAP_EXTS**"
178
179 #ifdef _MSC_VER
180 #pragma pack()
181 #endif
182
183 #ifdef __WATCOMC__
184 #pragma pack(pop)
185 #endif
186
187 #undef TPACK
188
189 struct sectflashtype {
190 short sectnum;
191 int step;
192 unsigned char ovis;
193 };
194 struct sectflashtype sectflash;
195
196 int vadd;
197 char ensfirsttime=1;
198 int stackedcheck;
199
200 #define STATLISTDEBUG
201 #ifdef STATLISTDEBUG
202 short *headspritesectptr[MAXSECTORS+1],*headspritestatptr[MAXSTATUS+1];
203 short *prevspritesectptr[MAXSPRITES], *prevspritestatptr[MAXSPRITES];
204 short *nextspritesectptr[MAXSPRITES], *nextspritestatptr[MAXSPRITES];
205 #endif
206
207 #define PLRSPRDEBUG
208 #define VERIFYSTATS
209
210 char vbad;
211
212
213
214 short
jsinsertsprite(short sect,short stat)215 jsinsertsprite(short sect, short stat)
216 {
217 short j;
218
219 j=insertsprite(sect,stat);
220 if( j != -1 ) {
221 sprite[j].x=0L;
222 sprite[j].y=0L;
223 sprite[j].z=0L;
224 sprite[j].cstat=0;
225 sprite[j].shade=0;
226 sprite[j].pal=0;
227 sprite[j].clipdist=32;
228 sprite[j].xrepeat=0;
229 sprite[j].yrepeat=0;
230 sprite[j].xoffset=0;
231 sprite[j].yoffset=0;
232 sprite[j].picnum=0;
233 sprite[j].ang=0;
234 sprite[j].xvel=0;
235 sprite[j].yvel=0;
236 sprite[j].zvel=0;
237 sprite[j].owner=-1;
238 sprite[j].lotag=0;
239 sprite[j].hitag=0;
240 sprite[j].extra=-1;
241 }
242 return(j);
243 }
244
245 short
jsdeletesprite(short spritenum)246 jsdeletesprite(short spritenum)
247 {
248 int ext;
249
250 ext=sprptr[spritenum]->extra;
251
252 if( validext(ext) ) {
253 memset(sprXTptr[ext], 0, sizeof(struct spriteextension));
254 sprXTptr[ext]->lock=0x00;
255 }
256
257 deletesprite(spritenum);
258 sprite[spritenum].extra=-1;
259
260 return(0);
261 }
262
263 int
isaplayersprite(int sprnum)264 isaplayersprite(int sprnum)
265 {
266 int j;
267
268 for( j=connecthead ; j >= 0 ; j=connectpoint2[j] ) {
269 if( playersprite[j] == sprnum ) {
270 return(1);
271 }
272 }
273 if( sprptr[sprnum]->statnum == 8 ) {
274 crash("isplrspr: non plr has statnm 8");
275 }
276 return(0);
277 }
278
279 int
validext(int ext)280 validext(int ext)
281 {
282 if( (ext >= 0) && (ext < MAXSPRITES) ) {
283 return(1);
284 }
285 return(0);
286 }
287
288 void
clearXTpics(short spriteno)289 clearXTpics(short spriteno)
290 {
291 short extno=sprptr[spriteno]->extra;
292
293 #ifdef PLRSPRDEBUG
294 if( isaplayersprite(spriteno) ) {
295 crash("messing w plrsprite at 2");
296 }
297 #endif
298
299 if( extno != -1 ) {
300 sprXTptr[extno]->basepic=sprptr[spriteno]->picnum;
301 sprXTptr[extno]->standpic=NO_PIC;
302 sprXTptr[extno]->walkpic=NO_PIC;
303 sprXTptr[extno]->runpic=NO_PIC;
304 sprXTptr[extno]->attackpic=NO_PIC;
305 sprXTptr[extno]->deathpic=NO_PIC;
306 sprXTptr[extno]->painpic=NO_PIC;
307 sprXTptr[extno]->squatpic=NO_PIC;
308 sprXTptr[extno]->morphpic=NO_PIC;
309 sprXTptr[extno]->specialpic=NO_PIC;
310 }
311 }
312
313 int
mapXT(int sn)314 mapXT(int sn)
315 {
316 short i;
317
318 #ifdef PLRSPRDEBUG
319 if( isaplayersprite(sn) ) {
320 crash("messing w plrsprite at 0");
321 }
322 #endif
323
324 for ( i=0; i<MAXSPRITES; i++ ) {
325 if( sprXTptr[i]->lock == 0x00 ) {
326 sprptr[sn]->extra=i;
327 memset(sprXTptr[i], 0, sizeof(struct spriteextension));
328 sprXTptr[i]->lock=0xFF;
329 return(i);
330 }
331 }
332
333 sprptr[sn]->extra=-1;
334 return(-1); // no free spot found
335 }
336
337 void
noextcrash(int i,int loc)338 noextcrash(int i, int loc)
339 {
340 crash("sprite at %d,%d no extension from %d", sprite[i].x,sprite[i].y, loc);
341 }
342
343 #ifdef VERIFYSTATS
344 void
verifystatus(int i,int stat)345 verifystatus(int i, int stat)
346 {
347 if( i == -1 ) {
348 return;
349 }
350 if( sprptr[i]->statnum != stat ) {
351 if( nextspritestat[i] != -1 ) {
352 crash("verifystatus fail for %d", stat);
353 }
354 vbad++;
355 }
356 }
357 #endif
358
359 int
initsprites()360 initsprites()
361 {
362 int i;
363
364 #ifdef NETDEBUG
365 dbgfp2=fopen("debug.sts","wt");
366 #endif
367
368 for( i=0; i< MAXSPRITES; i++ ) {
369 memset(&sprite[i], 0, sizeof(spritetype));
370 sprite[i].sectnum=MAXSECTORS;
371 sprite[i].statnum=MAXSTATUS;
372 sprite[i].extra=-1;
373 }
374
375 // initialize blast sector flashes
376 sectflash.sectnum=0;
377 sectflash.ovis=0;
378 sectflash.step=0;
379
380 #ifdef STATLISTDEBUG
381 for( i=0; i < (MAXSECTORS+1); i++ ) {
382 headspritesectptr[i]=&headspritesect[i];
383 }
384 for( i=0; i < (MAXSTATUS+1); i++ ) {
385 headspritestatptr[i]=&headspritestat[i];
386 }
387 for( i=0; i < MAXSPRITES; i ++ ) {
388 prevspritesectptr[i]=&prevspritesect[i];
389 prevspritestatptr[i]=&prevspritestat[i];
390 nextspritesectptr[i]=&nextspritesect[i];
391 nextspritestatptr[i]=&nextspritestat[i];
392 }
393 #endif
394
395 return(1);
396 }
397
398 int
initspriteXTs()399 initspriteXTs()
400 {
401 int fh,i,nr,ext;
402
403 memset(&pickup, 0, sizeof(pickup));
404 pickup.extra=-1;
405
406 for (i=0; i<MAXSPRITES; i++) {
407 memset(&spriteXT[i], 0, sizeof(struct spriteextension));
408 }
409
410 fh=kopen4load(boardfilename, 0);
411 if( fh == -1 ) {
412 return 0;
413 }
414
415 // read in XTtrailer
416 klseek(fh, -((int)sizeof(struct XTtrailertype)), SEEK_END);
417 memset(&XTtrailer, 0, sizeof(struct XTtrailertype));
418 kread(fh, &XTtrailer, sizeof(struct XTtrailertype));
419
420 // if no previous extension info then continue
421 if( strcmp(XTtrailer.ID, TRAILERID) != 0 ) {
422 goto noext;
423 }
424
425 // load and intialize spriteXT array members
426 klseek(fh, XTtrailer.start, SEEK_SET);
427 for( i=0; i<XTtrailer.numXTs; i++ ) {
428 nr=kread(fh, &XTsave, sizeof(struct XTsavetype));
429 if( nr != sizeof(struct XTsavetype) )
430 break;
431 spriteXT[XTsave.XTnum]=XTsave.sprXT; // struct assign
432 }
433
434 noext:
435
436 kclose(fh);
437
438 switch( difficulty ) {
439 case 0:
440 case 1:
441 vadd=-1;
442 break;
443 case 2:
444 vadd=0;
445 break;
446 case 3:
447 vadd=3;
448 break;
449 }
450
451 // adjust speed for difficulty
452 for( i=0; i<MAXSPRITES; i++ ) {
453 if( sprite[i].extra != -1 ) {
454 #ifdef NOSHOWSPRITES
455 show2dsprite[i>>3] &= ~(1<<(i&7));
456 #endif
457 switch( spriteXT[sprite[i].extra].basestat ) {
458 case GUARD:
459 case CHASE:
460 case STALK:
461 sprite[i].xvel+=vadd;
462 if( sprite[i].xvel < 0 )
463 sprite[i].xvel=0;
464 sprite[i].yvel+=vadd;
465 if( sprite[i].yvel < 0 )
466 sprite[i].yvel=0;
467 sprite[i].zvel+=vadd;
468 if( sprite[i].zvel < 0 )
469 sprite[i].zvel=0;
470 break;
471 }
472 }
473 }
474
475 // only CHASE in multiplayer
476 if( option[4] != 0 ) {
477 for( i=0; i<MAXSPRITES; i++ ) {
478 if( (ext=sprite[i].extra) != -1 ) {
479 if( sprite[i].statnum != CHASE ) {
480 jsdeletesprite(i);
481 }
482 else if( spriteXT[ext].basestat != CHASE ) {
483 jsdeletesprite(i);
484 }
485 }
486 }
487 }
488
489 if( noenemiesflag != 0 ) {
490 for( i=0; i<MAXSPRITES; i++ ) {
491 if( sprptr[i]->extra != -1 ) {
492 jsdeletesprite(i);
493 }
494 }
495 }
496
497 if( noguardflag != 0 ) {
498 for( i=0; i<MAXSPRITES; i++ ) {
499 if( sprptr[i]->statnum == GUARD ) {
500 jsdeletesprite(i);
501 }
502 else {
503 if( sprptr[i]->extra != -1 ) {
504 if( sprXTptr[sprptr[i]->extra]->basestat == GUARD ) {
505 jsdeletesprite(i);
506 }
507 }
508 }
509 }
510 }
511
512 if( nostalkflag != 0 ) {
513 for( i=0; i<MAXSPRITES; i++ ) {
514 if( sprptr[i]->statnum == STALK ) {
515 jsdeletesprite(i);
516 }
517 else {
518 if( sprptr[i]->extra != -1 ) {
519 if( sprXTptr[sprptr[i]->extra]->basestat == STALK ) {
520 jsdeletesprite(i);
521 }
522 }
523 }
524 }
525 }
526
527 if( nochaseflag != 0 ) {
528 for( i=0; i<MAXSPRITES; i++ ) {
529 if( sprptr[i]->statnum == CHASE ) {
530 jsdeletesprite(i);
531 }
532 else {
533 if( sprptr[i]->extra != -1 ) {
534 if( sprXTptr[sprptr[i]->extra]->basestat == CHASE ) {
535 jsdeletesprite(i);
536 }
537 }
538 }
539 }
540 }
541
542 if( nostrollflag != 0 ) {
543 for( i=0; i<MAXSPRITES; i++ ) {
544 if( sprptr[i]->statnum == STROLL ) {
545 jsdeletesprite(i);
546 }
547 else {
548 if( sprptr[i]->extra != -1 ) {
549 if( sprXTptr[sprptr[i]->extra]->basestat == STROLL ) {
550 jsdeletesprite(i);
551 }
552 }
553 }
554 }
555 }
556
557 return(1);
558 }
559
560 int
isvisible(short i,short target)561 isvisible(short i, short target)
562 {
563 if( !validplayer(target) ) {
564 crash("isvisible: bad targetnum");
565 }
566
567 if( sintable[(sprptr[i]->ang+2560)&2047]*(posx[target]-sprptr[i]->x) + sintable[(sprptr[i]->ang+2048)&2047]*(posy[target]-sprptr[i]->y) >= 0) {
568 if( cansee(posx[target],posy[target],(posz[target])>>1,cursectnum[target],
569 sprptr[i]->x,sprptr[i]->y,sprptr[i]->z-(tilesiz[sprptr[i]->picnum].y<<7),sprptr[i]->sectnum) == 1) {
570 return(1);
571 }
572 }
573
574 return(0);
575 }
576
getpicinfo(short picnum)577 void getpicinfo(short picnum)
578 {
579 #if 0 // TODO
580 int amask = picanm[picnum];
581
582 picinfoptr->numframes = amask & 0x0000003F;
583 picinfoptr->animtype = (amask & 0x000000C0) >> 6;
584 #endif
585 picinfoptr->xcenteroffset = picanm[picnum].xofs; //(amask & 0x0000FF00) >> 8;
586 picinfoptr->ycenteroffset = picanm[picnum].yofs; //(amask & 0x00FF0000) >> 16;
587 picinfoptr->animspeed = picanm[picnum].sf; //(amask & 0x0F000000) >> 24;
588 }
589
wallangle(int wn)590 short wallangle(int wn)
591 {
592 int w1x, w1y, w2x, w2y;
593 short wang;
594
595 w1x = wallptr[wn]->x; w1y = wallptr[wn]->y;
596 wn = wallptr[wn]->point2;
597 w2x = wallptr[wn]->x; w2y = wallptr[wn]->y;
598 wang = getangle(w2x - w1x, w2y - w1y);
599
600 return wang;
601 }
602
603 short
arbitraryangle(void)604 arbitraryangle(void)
605 {
606 switch( RMOD4("STAT642 ") ) {
607 case 0:
608 case 1:
609 return(leftof[RMOD16("STAT645 ")]);
610 break;
611 default:
612 return(rightof[RMOD16("STAT648 ")]);
613 break;
614 }
615 }
616
617 short
wallnormal(int wn)618 wallnormal(int wn)
619 {
620 int w1x,w1y, w2x,w2y;
621 short wnorm;
622
623 w1x=wallptr[wn]->x; w1y=wallptr[wn]->y;
624 wn=wallptr[wn]->point2;
625 w2x=wallptr[wn]->x; w2y=wallptr[wn]->y;
626 wnorm=getangle(w2x-w1x, w2y-w1y);
627 wnorm=(wnorm+512L)&2047;
628
629 return(wnorm);
630 }
631
632 short
walldeflect(int wn,short angin)633 walldeflect(int wn, short angin)
634 {
635 short wnorm,refract,delta,angout;
636
637 wnorm=wallnormal(wn);
638
639 refract=(angin+1024)&2047;
640
641 delta=wnorm-refract;
642
643 angout = wnorm+delta;
644
645 if ( angout < 0 )
646 angout+=2048;
647
648 return(angout);
649 }
650
651 short
spritedeflect(int sn,short angin)652 spritedeflect(int sn, short angin)
653 {
654 short angout;
655
656 switch ( sprptr[sn]->statnum ) {
657 case INANIMATE:
658 case INACTIVE:
659 case AMBUSH:
660 angout=(angin+1024)&2047;
661 switch( (int)RMOD2("STAT697 ") ) {
662 case 0:
663 angout=leftof[angout];
664 break;
665 case 1:
666 default:
667 angout=rightof[angout];
668 break;
669 }
670 break;
671 default:
672 angout=sprptr[sn]->ang;
673 break;
674 }
675
676 return(angout);
677 }
678
679 void
tweakdeathdist(short i)680 tweakdeathdist(short i)
681 {
682 int dax,day;
683
684 #ifdef PLRSPRDEBUG
685 if( isaplayersprite(i) ) {
686 crash("messing w plrsprite at 1");
687 }
688 #endif
689
690 sprptr[i]->clipdist<<=1;
691 dax=( ((sintable[(sprptr[i]->ang+512)&2047])*sprptr[i]->xvel) <<3 );
692 day=( ((sintable[sprptr[i]->ang])*sprptr[i]->yvel) <<3 );
693 movesprite(( short)i,dax,day,0L,1024,1024,CLIFFCLIP);
694
695 if( sprptr[i]->extra == -1 ) {
696 sprptr[i]->lotag=SPR_LOTAG_PICKUP;
697 }
698 }
699
700 void
splash(int i)701 splash(int i)
702 {
703 int j;
704
705 #ifdef PLRSPRDEBUG
706 if( isaplayersprite(i) ) {
707 crash("messing w plrsprite at 3");
708 }
709 #endif
710
711 if( option[4] != 0 ) {
712 return;
713 }
714
715 j=jsinsertsprite(sprptr[i]->sectnum, RUNTHRU);
716 if( j != -1 ) {
717 fillsprite(j,sprptr[i]->x,sprptr[i]->y,sprptr[i]->z,
718 2,-13,0,32,64,64,0,0,BLUESPLASH,sprptr[i]->ang,
719 0,0,0,i+4096,sprptr[i]->sectnum,
720 RUNTHRU,0,0,-1);
721 getpicinfo(BLUESPLASH);
722 sprptr[j]->lotag=picinfoptr->numframes;
723 if( sprptr[j]->lotag > MAXFRAMES ) {
724 sprptr[j]->lotag=MAXFRAMES;
725 }
726 if( sprptr[j]->lotag < 0 ) {
727 sprptr[j]->lotag=0;
728 }
729 sprptr[j]->hitag=0;
730 playsound(S_SPLASH,sprptr[i]->x,sprptr[i]->y,0,ST_NOUPDATE);
731 }
732 }
733
734 int
pickupsprite(short sn)735 pickupsprite(short sn)
736 {
737 #ifdef PLRSPRDEBUG
738 if( isaplayersprite(sn) ) {
739 crash("messing w plrsprite at 4");
740 }
741 #endif
742
743 // can only carry one at a time of these items
744 if( (pickup.picnum != 0) || (option[4] != 0) ) {
745 return(0);
746 }
747
748 pickup.picnum=sprptr[sn]->picnum;
749 pickup.cstat=sprptr[sn]->cstat;
750 pickup.shade=sprptr[sn]->shade;
751 pickup.pal=sprptr[sn]->pal;
752 pickup.clipdist=sprptr[sn]->clipdist;
753 pickup.xrepeat=sprptr[sn]->xrepeat;
754 pickup.yrepeat=sprptr[sn]->yrepeat;
755 pickup.xoffset=sprptr[sn]->xoffset;
756 pickup.yoffset=sprptr[sn]->yoffset;
757 // cant set lotag/hitag as TOSS needs to use them
758 pickup.extra=sprptr[sn]->extra;
759
760 jsdeletesprite(sn);
761
762 pickupclock=lockclock;
763 return(1);
764 }
765
766 void
toss(short snum)767 toss(short snum)
768 {
769 int j;
770
771 if( !validplayer(snum) ) {
772 crash("toss: bad plrnum");
773 }
774 if( pickup.picnum == 0 ) {
775 return;
776 }
777 j=jsinsertsprite(cursectnum[snum], TOSS);
778 if( j != -1 ) {
779 if( drawweap[snum] == 0 ) {
780 sprptr[j]->x=posx[snum]+(sintable[(ang[snum]+2560+256)&2047]>>6);
781 sprptr[j]->y=posy[snum]+(sintable[(ang[snum]+2048+256)&2047]>>6);
782 }
783 else {
784 sprptr[j]->x=posx[snum]-(sintable[(ang[snum]+2560+256)&2047]>>6);
785 sprptr[j]->y=posy[snum]-(sintable[(ang[snum]+2048+256)&2047]>>6);
786 }
787 sprptr[j]->z=posz[snum]+(4<<8);
788 sprptr[j]->cstat=pickup.cstat;
789 sprptr[j]->shade=pickup.shade;
790 sprptr[j]->pal=pickup.pal;
791 sprptr[j]->clipdist=pickup.clipdist;
792 sprptr[j]->xrepeat=pickup.xrepeat;
793 sprptr[j]->yrepeat=pickup.yrepeat;
794 sprptr[j]->xoffset=pickup.xoffset;
795 sprptr[j]->yoffset=pickup.yoffset;
796 sprptr[j]->ang=ang[snum];
797 switch( pickup.picnum ) {
798 case RATPIC:
799 sprptr[j]->picnum=RATTHROWPIC;
800 break;
801 case TUBEBOMB+1:
802 sprptr[j]->picnum=TUBEBOMB;
803 break;
804 case DARTBOMB+1:
805 sprptr[j]->picnum=DARTBOMB;
806 break;
807 default:
808 sprptr[j]->picnum=pickup.picnum;
809 break;
810 }
811 sprptr[j]->xvel=sintable[(ang[snum]+2560)&2047]>>6;
812 sprptr[j]->yvel=sintable[(ang[snum]+2048)&2047]>>6;
813 sprptr[j]->zvel=(80-horiz[snum])<<6;
814 sprptr[j]->owner=snum+4096;
815 sprptr[j]->sectnum=cursectnum[snum];
816 // TOSS will be usin hi/lo tag
817 sprptr[j]->lotag=0;
818 sprptr[j]->hitag=0;
819 sprptr[j]->extra=pickup.extra;
820 }
821 memset(&pickup, 0, sizeof(pickup));
822 pickup.extra=-1;
823 }
824
825 void
triggersprite(short sn)826 triggersprite(short sn)
827 {
828 int datag;
829 short j;
830 short newext;
831
832 if( option[4] != 0 ) {
833 return;
834 }
835
836 #ifdef PLRSPRDEBUG
837 if( isaplayersprite(sn) ) {
838 crash("messing w plrsprite at 5");
839 }
840 #endif
841
842 if( sprptr[sn]->extra == -1 ) {
843 return;
844 }
845
846 datag = sprptr[sn]->lotag;
847
848 switch( datag ) {
849
850 case SPR_LOTAG_MORPH:
851 break;
852 case SPR_LOTAG_SPAWNCHASE:
853 j = jsinsertsprite(sprptr[sn]->sectnum, sprXTptr[ sprptr[sn]->extra ]->basestat);
854 if ( j == -1 ) {
855 break;
856 }
857 newext=mapXT(j);
858 if( !validext(newext) ) {
859 jsdeletesprite(j);
860 break;
861 }
862 sprptr[j]->x = sprptr[sn]->x+( sintable[(sprptr[sn]->ang+512)&2047]>>6 );
863 sprptr[j]->y = sprptr[sn]->y+( sintable[sprptr[sn]->ang&2047]>>6 );
864 sprptr[j]->z = sprptr[sn]->z;
865 sprptr[j]->cstat = 0x101;
866 sprptr[j]->picnum = sprXTptr[ sprptr[sn]->extra ]->basepic;
867 sprptr[j]->shade = sprptr[sn]->shade;
868 sprptr[j]->sectnum = sprptr[sn]->sectnum;
869 sprptr[j]->xrepeat = sprptr[sn]->xrepeat;
870 sprptr[j]->yrepeat = sprptr[sn]->yrepeat;
871 sprptr[j]->ang = sprptr[sn]->ang;
872 sprptr[j]->xvel = sprptr[sn]->xvel;
873 sprptr[j]->yvel = sprptr[sn]->yvel;
874 sprptr[j]->zvel = sprptr[sn]->zvel;
875 sprptr[j]->owner = -1;
876 sprptr[j]->lotag = 0;
877 sprptr[j]->hitag = 0;
878 sprXTptr[ sprptr[j]->extra ]->basestat = sprXTptr[ sprptr[sn]->extra ]->basestat;
879 sprXTptr[ sprptr[j]->extra ]->basepic = sprXTptr[ sprptr[sn]->extra ]->basepic;
880 sprXTptr[ sprptr[j]->extra ]->walkpic = sprXTptr[ sprptr[sn]->extra ]->walkpic;
881 sprXTptr[ sprptr[j]->extra ]->standpic = sprXTptr[ sprptr[sn]->extra ]->standpic;
882 sprXTptr[ sprptr[j]->extra ]->runpic = sprXTptr[ sprptr[sn]->extra ]->runpic;
883 sprXTptr[ sprptr[j]->extra ]->attackpic = sprXTptr[ sprptr[sn]->extra ]->attackpic;
884 sprXTptr[ sprptr[j]->extra ]->deathpic = sprXTptr[ sprptr[sn]->extra ]->deathpic;
885 sprXTptr[ sprptr[j]->extra ]->morphpic = sprXTptr[ sprptr[sn]->extra ]->morphpic;
886 sprXTptr[ sprptr[j]->extra ]->specialpic = sprXTptr[ sprptr[sn]->extra ]->specialpic;
887 // delete trigger tag from old sprites
888 sprptr[sn]->lotag=0;
889 sprptr[sn]->hitag=0;
890 clearXTpics(sn);
891 break;
892 default:
893 newstatus(sn, sprXTptr[ sprptr[sn]->extra ]->basestat);
894 break;
895 }
896 }
897
898 void
sectortriggersprites(short snum)899 sectortriggersprites(short snum)
900 {
901 short i,nexti,ext;
902 char triggered=0;
903
904 if( option[4] != 0 ) {
905 return;
906 }
907
908 if( !validplayer(snum) ) {
909 crash("sectrtrgrsprts: bad plrnum");
910 }
911
912 if( sectptr[cursectnum[snum]]->lotag == SECT_LOTAG_SHOWMESSAGE ) {
913 switch( sectptr[cursectnum[snum]]->hitag ) {
914 case 0:
915 showmessage("AREA IS OFF-LIMITS");
916 break;
917 }
918 return;
919 }
920 if( sectptr[cursectnum[snum]]->lotag != SECT_LOTAG_TRIGGERSPRITE ) {
921 return;
922 }
923
924 i=headspritestat[INANIMATE];
925 while (i != -1) {
926 nexti=nextspritestat[i];
927 if (sprptr[i]->hitag == sectptr[cursectnum[snum]]->hitag) {
928 triggersprite(i);
929 triggered=1;
930 }
931 i=nexti;
932 }
933
934 i=headspritestat[AMBUSH];
935 while (i != -1) {
936 nexti=nextspritestat[i];
937 if( sprptr[i]->hitag == sectptr[cursectnum[snum]]->hitag ) {
938 ext=sprptr[i]->extra;
939 if( !validext(ext) ) {
940 noextcrash(i, 300);
941 }
942 sprXTptr[i]->aimask|=AI_JUSTSHOTAT;
943 ambushyell(i, ext);
944 triggered=1;
945 }
946 i=nexti;
947 }
948
949 i=headspritestat[GUARD];
950 while (i != -1) {
951 nexti=nextspritestat[i];
952 if( sprptr[i]->hitag == sectptr[cursectnum[snum]]->hitag ) {
953 if( (ext=sprptr[i]->extra) != -1 ) {
954 sprXTptr[ext]->aimask&=~AI_GAVEWARNING;
955 givewarning(i, ext);
956 sprXTptr[ext]->aimask|=AI_ENCROACHMENT;
957 triggered=1;
958 }
959 }
960 i=nexti;
961 }
962
963 i=headspritestat[STANDING]; // check GUARDS who are standing
964 while (i != -1) {
965 nexti=nextspritestat[i];
966 ext=sprptr[i]->extra;
967 if( (!validext(ext)) || (sprXTptr[ext]->basestat == GUARD) ) {
968 if( sprptr[i]->hitag == sectptr[cursectnum[snum]]->hitag )
969 sprXTptr[ext]->aimask&=~AI_GAVEWARNING;
970 givewarning(i, ext);
971 sprXTptr[ext]->aimask|=AI_ENCROACHMENT;
972 triggered=1;
973 }
974 i=nexti;
975 }
976
977 if( triggered ) {
978 sectptr[cursectnum[snum]]->hitag=0;
979 }
980 }
981
982 void
bloodonwall(int wn,int x,int y,int z,short sect,short daang,int hitx,int hity,int hitz)983 bloodonwall(int wn, int x,int y,int z, short sect, short daang, int hitx, int hity, int hitz)
984 {
985 int j;
986
987 if( wallptr[wn]->lotag != 0 ) {
988 return;
989 }
990
991 switch( wallptr[wn]->picnum ) {
992 case 15:
993 case 71:
994 case 72:
995 case 87:
996 case 93:
997 case 92:
998 case 95:
999 case 97:
1000 case 98:
1001 case 99:
1002 case 124:
1003 case 126:
1004 case 147:
1005 case 152:
1006 case 214:
1007 case 215:
1008 case 235:
1009 case 236:
1010 case 636:
1011 case 855:
1012 case 1457:
1013 return;
1014 default:
1015 break;
1016 }
1017
1018 if( wallptr[wn]->lotag == 0 )
1019 {
1020 wallptr[wn]->lotag=1;
1021
1022 neartag(x, y, z, sect, daang, &neartagsector,&neartagwall,&neartagsprite,&neartaghitdist,512L,1, nullptr);
1023
1024 if( neartagwall != -1 ) {
1025 j=jsinsertsprite(sect, BLOODFLOW);
1026 if( j != -1 ) {
1027 sprptr[j]->picnum=WALLBLOOD;
1028 sprptr[j]->x=hitx;
1029 sprptr[j]->y=hity;
1030 sprptr[j]->z=hitz+2048;
1031 if( sprptr[j]->z > sectptr[sect]->floorz )
1032 sprptr[j]->z=sectptr[sect]->floorz-2048;
1033 sprptr[j]->xrepeat=16;
1034 sprptr[j]->yrepeat=16;
1035 sprptr[j]->xvel=0;
1036 sprptr[j]->yvel=0;
1037 sprptr[j]->zvel=0;
1038 sprptr[j]->cstat=0x0090;
1039 sprptr[j]->ang=wallnormal(wn);
1040 sprptr[j]->shade=0;
1041 sprptr[j]->extra=-1;
1042 sprptr[j]->lotag=0;
1043 sprptr[j]->hitag=0;
1044 }
1045 }
1046 wallptr[wn]->lotag=0;
1047 }
1048 }
1049
1050 int
spewblood(int sprnum,int hitz,short UNUSED (daang))1051 spewblood(int sprnum, int hitz, short UNUSED(daang))
1052 {
1053 int j,ext=sprptr[sprnum]->extra;
1054
1055 if( option[4] != 0 ) {
1056 return(0);
1057 }
1058 if( !validext(ext) ) {
1059 return(0);
1060 }
1061 if( isanandroid(sprnum) || isahologram(sprnum) ) {
1062 return(0);
1063 }
1064
1065 switch( sprXTptr[ext]->basepic ) {
1066 case RUBWALKPIC:
1067 case FRGWALKPIC:
1068 case COP1WALKPIC:
1069 case ANTWALKPIC:
1070 case SARAHWALKPIC:
1071 case MAWALKPIC:
1072 case DIWALKPIC:
1073 case ERWALKPIC:
1074 case SAMWALKPIC:
1075 j=jsinsertsprite(sprptr[sprnum]->sectnum, RUNTHRU);
1076 if( j != -1 ) {
1077 fillsprite(j,sprptr[sprnum]->x,sprptr[sprnum]->y,sprptr[sprnum]->z-(tilesiz[sprptr[sprnum]->picnum].y<<6),128,
1078 0,0,12,16,16,0,0, BLOODSPLAT,sprptr[sprnum]->ang,
1079 sintable[(sprptr[sprnum]->ang+2560)&2047]>>6,sintable[(sprptr[sprnum]->ang+2048)&2047]>>6,
1080 30L,sprnum+4096,sprptr[sprnum]->sectnum, RUNTHRU,0,0,0);
1081 sprptr[j]->z=hitz;
1082 getpicinfo(BLOODSPLAT);
1083 sprptr[j]->lotag=picinfoptr->numframes;
1084 if( sprptr[j]->lotag > MAXFRAMES ) {
1085 sprptr[j]->lotag=MAXFRAMES;
1086 }
1087 if( sprptr[j]->lotag < 0 ) {
1088 sprptr[j]->lotag=0;
1089 }
1090 sprptr[j]->hitag=0;
1091 return(1);
1092 }
1093 break;
1094 default:
1095 break;
1096 }
1097
1098 return(0);
1099 }
1100
1101 int
playervirus(short pnum,int pic)1102 playervirus(short pnum, int pic)
1103 {
1104 int j,nextj;
1105
1106 if( !validplayer(pnum) ) {
1107 crash("plrvrus: bad plrnum");
1108 }
1109
1110 j=headspritestat[PLRVIRUS];
1111 while( j >= 0 ) {
1112 nextj = nextspritestat[j];
1113 // already hosting ?
1114 if( sprptr[j]->owner == pnum ) {
1115 return(0);
1116 }
1117 j = nextj;
1118 }
1119
1120 j=jsinsertsprite(cursectnum[pnum], PLRVIRUS);
1121 if( j == -1 ) {
1122 return(0);
1123 }
1124
1125 sprptr[j]->extra=-1;
1126 sprptr[j]->x=posx[pnum];
1127 sprptr[j]->y=posy[pnum];
1128 sprptr[j]->z=posz[pnum];
1129 sprptr[j]->xrepeat=18;
1130 sprptr[j]->yrepeat=40;
1131 sprptr[j]->cstat=0x0000;
1132 sprptr[j]->shade=-28;
1133 sprptr[j]->picnum=pic;
1134 sprptr[j]->lotag=(krand_intercept("STAT1172")&512)+128;
1135 sprptr[j]->hitag=0;
1136 sprptr[j]->owner=pnum; // host
1137
1138 playsound(S_FIRELOOP,sprptr[j]->x,sprptr[j]->y,0,ST_UPDATE);
1139
1140 return(1);
1141 }
1142
1143 int
attachvirus(short i,int pic)1144 attachvirus(short i, int pic)
1145 {
1146 int j,ext,nextj;
1147
1148 if( option[4] != 0 ) {
1149 return(0);
1150 }
1151 if( (sprptr[i]->statnum == VIRUS) || (sprptr[i]->statnum == PINBALL) ) {
1152 return(0);
1153 }
1154 if( isanandroid(i) || isahologram(i) ) {
1155 return(0);
1156 }
1157
1158 j=headspritestat[VIRUS];
1159 while( j >= 0 ) {
1160 nextj = nextspritestat[j];
1161 // already hosting ?
1162 if( sprptr[j]->owner == i ) {
1163 return(0);
1164 }
1165 j = nextj;
1166 }
1167
1168 j=jsinsertsprite(sprptr[i]->sectnum, VIRUS);
1169 if( j == -1 ) {
1170 return(0);
1171 }
1172
1173 sprptr[j]->extra=-1;
1174 sprptr[j]->x=sprptr[i]->x;
1175 sprptr[j]->y=sprptr[i]->y;
1176 sprptr[j]->z=sprptr[i]->z;
1177 sprptr[j]->xrepeat=20;
1178 sprptr[j]->yrepeat=20;
1179 sprptr[j]->cstat=0x0000;
1180 sprptr[j]->shade=-28;
1181 sprptr[j]->picnum=pic;
1182 sprptr[j]->lotag=(krand_intercept("STAT1216")&512)+128;
1183 sprptr[j]->hitag=0;
1184 sprptr[j]->owner=i; // host
1185
1186 if( pic == FIREPIC ) {
1187 sprptr[j]->xrepeat=sprptr[i]->xrepeat;
1188 sprptr[j]->yrepeat=sprptr[i]->yrepeat+8;
1189 ext=sprptr[i]->extra;
1190 playsound(S_FIRELOOP,sprptr[j]->x,sprptr[j]->y,0,ST_UPDATE);
1191 if( validext(ext) ) {
1192 newstatus(i, PINBALL);
1193 if( sprptr[i]->statnum == PINBALL ) {
1194 sprptr[i]->xvel+=4;
1195 sprptr[i]->yvel+=4;
1196 }
1197 }
1198 }
1199 else {
1200 playsound(S_FORCEFIELDHUMLOOP, sprptr[i]->x,sprptr[i]->y,0,ST_UNIQUE);
1201 }
1202
1203 return(1);
1204 }
1205
1206 void
deathdropitem(short sprnum)1207 deathdropitem(short sprnum)
1208 {
1209 short j,ext;
1210 int pic;
1211
1212 #ifdef PLRSPRDEBUG
1213 if( isaplayersprite(sprnum) ) {
1214 crash("messing w plrsprite at 7");
1215 }
1216 #endif
1217
1218 if( option[4] != 0 ) {
1219 return;
1220 }
1221
1222 ext=sprptr[sprnum]->extra;
1223 if( !validext(ext) ) {
1224 return;
1225 }
1226
1227 if( sprXTptr[ext]->fxmask&FX_HASREDCARD ) {
1228 pic=RED_KEYCARD;
1229 sprXTptr[ext]->fxmask&=(~FX_HASREDCARD);
1230 }
1231 else if( sprXTptr[ext]->fxmask&FX_HASBLUECARD ) {
1232 pic=BLUE_KEYCARD;
1233 sprXTptr[ext]->fxmask&=(~FX_HASBLUECARD);
1234 }
1235 else if( sprXTptr[ext]->fxmask&FX_ANDROID ) {
1236 showmessage("WAS AN ANDROID");
1237 return;
1238 }
1239 else {
1240 switch( sprXTptr[ext]->weapon ) {
1241 case 4:
1242 case 5:
1243 pic=KLIPPIC;
1244 break;
1245 default:
1246 return;
1247 }
1248 }
1249
1250 j=jsinsertsprite(sprptr[sprnum]->sectnum, DROPSIES);
1251 if( j != -1 ) {
1252 fillsprite(j,sprptr[sprnum]->x,sprptr[sprnum]->y,sprptr[sprnum]->z-(tilesiz[sprptr[sprnum]->picnum].y<<6),128,
1253 0,0,12,16,16,0,0,pic,sprptr[sprnum]->ang,
1254 sintable[(sprptr[sprnum]->ang+2560)&2047]>>6,sintable[(sprptr[sprnum]->ang+2048)&2047]>>6,
1255 30L,sprnum+4096,sprptr[sprnum]->sectnum,DROPSIES,0,0,0);
1256 }
1257 else {
1258 return;
1259 }
1260
1261 // tweak the size of the pic
1262 switch( sprptr[j]->picnum ) {
1263 case KLIPPIC:
1264 sprptr[j]->xrepeat-=2;
1265 sprptr[j]->yrepeat-=2;
1266 break;
1267 case RED_KEYCARD:
1268 case BLUE_KEYCARD:
1269 sprptr[j]->xrepeat>>=1;
1270 sprptr[j]->yrepeat>>=1;
1271 break;
1272 default:
1273 break;
1274 }
1275 }
1276
1277 void
deathsounds(int pic,int x,int y)1278 deathsounds(int pic, int x,int y)
1279 {
1280 switch( pic ) {
1281 case ANTDEATHPIC: //anton boss
1282 case DIDEATHPIC: //dimarco boss
1283 case 2165: //miles boss
1284 case 2978: //sonny hokuri boss
1285 case 2850: //carlyle boss
1286 case 2662: //janus boss
1287 case 2550: //marty dollar boss
1288 case RUBDEATHPIC:
1289 case FRGDEATHPIC:
1290 case JAKEDEATHPIC:
1291 case COP1DEATHPIC:
1292 case ERDEATHPIC:
1293 case 2415: //rebreather
1294 case 2295: //black cop
1295 case 2455: //trenchcoat
1296 case 2792: //blacksmith
1297 case 2712: //orange guy
1298 case 3041: //swat guy
1299 case 2910: //saline suit
1300 playsound(S_MANDIE1+RMOD4("STAT1378")+RMOD3("STAT1378")+RMOD3("STAT1378"),x,y,0,ST_NOUPDATE);
1301 break;
1302 case SARAHDEATHPIC:
1303 case SAMDEATHPIC:
1304 case MADEATHPIC:
1305 case 2340: //nika
1306 case 2607: //halter top
1307 case 2227: //cowgirl
1308 playsound(S_GIRLDIE1+RMOD4("STAT1389")+RMOD3("STAT1389"),x,y,0,ST_NOUPDATE);
1309 break;
1310 case GLASSDEATHPIC:
1311 playsound(S_GLASSBREAK1+RMOD2("STAT1392"),x,y,0,ST_NOUPDATE);
1312 break;
1313 case 570: // autogun
1314 playsound(S_AUTOGUNEXPLODE,x,y,0,ST_NOUPDATE);
1315 break;
1316 case 609: //bathroom glass
1317 playsound(S_SMALLGLASS1+RMOD2("STAT1398"),0,0,0,ST_IMMEDIATE);
1318 break;
1319 case 3060:
1320 case 3064:
1321 case 3068:
1322 case 3072:
1323 case 3076:
1324 case 3080:
1325 case 3084:
1326 playsound(S_HOLOGRAMDIE,x,y,0,ST_NOUPDATE);
1327 break;
1328 case 3973: //matrix character death
1329 if( krand_intercept("STAT1364") < 32767 ) {
1330 playsound(S_MATRIX_DIE1,x,y,0,ST_NOUPDATE);
1331 }
1332 else {
1333 playsound(S_MATRIX_DIE2,x,y,0,ST_NOUPDATE);
1334 }
1335 break;
1336
1337 }
1338 }
1339
1340 void
hideplea(short sn,short ext)1341 hideplea(short sn, short ext)
1342 {
1343 #ifdef PLRSPRDEBUG
1344 if( isaplayersprite(sn) ) {
1345 crash("messing w plrsprite at 8");
1346 }
1347 #endif
1348
1349 if( (sprXTptr[ext]->aimask&AI_DIDHIDEPLEA) && (krand_intercept("STAT1383")&1) )
1350 return;
1351
1352 switch( sprXTptr[ext]->basepic ) {
1353 case ERWALKPIC:
1354 playsound(S_MALE_DONTHURT+(krand_intercept("STAT1390")&5),sprptr[sn]->x,sprptr[sn]->y,0,ST_UNIQUE);
1355 if(krand_intercept("STAT1391")&1) {
1356 sprXTptr[ext]->aimask|=AI_DIDHIDEPLEA;
1357 }
1358 break;
1359 case SARAHWALKPIC:
1360 case SAMWALKPIC:
1361 playsound(S_DIANE_DONTSHOOTP+(krand_intercept("STAT1397")&5),sprptr[sn]->x,sprptr[sn]->y,0,ST_UNIQUE);
1362 if(krand_intercept("STAT1398")&1) {
1363 sprXTptr[ext]->aimask|=AI_DIDHIDEPLEA;
1364 }
1365 break;
1366 }
1367 }
1368
1369 void
fleescream(short sn,short ext)1370 fleescream(short sn, short ext)
1371 {
1372 #ifdef PLRSPRDEBUG
1373 if( isaplayersprite(sn) ) {
1374 crash("messing w plrsprite at 9");
1375 }
1376 #endif
1377
1378 if( !validext(ext) ) {
1379 return;
1380 }
1381
1382 if( (sprXTptr[ext]->aimask&AI_DIDFLEESCREAM) && (krand_intercept("STAT1417")&1) )
1383 return;
1384
1385 switch( sprXTptr[ext]->basepic ) {
1386 case ERWALKPIC:
1387 playsound(S_MALE_OHMYGOD+(krand_intercept("STAT1424")&5),sprptr[sn]->x,sprptr[sn]->y,0,ST_UNIQUE);
1388 if(krand_intercept("STAT1425")&1) {
1389 sprXTptr[ext]->aimask|=AI_DIDFLEESCREAM;
1390 }
1391 break;
1392 case SARAHWALKPIC:
1393 case SAMWALKPIC:
1394 switch( RMOD4("STAT1478") ) {
1395 case 0:
1396 case 2:
1397 playsound(S_FEM_RUNHEGOTGUN+(krand_intercept("STAT1434")&11),sprptr[sn]->x,sprptr[sn]->y,0,ST_UNIQUE);
1398 break;
1399 default:
1400 playsound(S_SCREAM1+RMOD3("STAT1484"),sprptr[sn]->x,sprptr[sn]->y,0,ST_UNIQUE);
1401 break;
1402 }
1403 if(krand_intercept("STAT1440")&1) {
1404 sprXTptr[ext]->aimask|=AI_DIDFLEESCREAM;
1405 }
1406 break;
1407 }
1408 }
1409
1410 void
rubitinsound(int UNUSED (p),int sn)1411 rubitinsound(int UNUSED(p), int sn)
1412 {
1413 int ext=sprptr[sn]->extra;
1414
1415 #ifdef PLRSPRDEBUG
1416 if( isaplayersprite(sn) ) {
1417 crash("messing w plrsprite at 10");
1418 }
1419 #endif
1420
1421 if( !validext(ext) ) {
1422 return;
1423 }
1424
1425 if( sprXTptr[ext]->aimask&AI_DIDHIDEPLEA )
1426 return;
1427
1428 switch( sprXTptr[ext]->basepic ) {
1429 case MAWALKPIC:
1430 playsound(S_MAR_THINKYOUTAKE+RMOD3("STAT1513"),sprptr[sn]->x,sprptr[sn]->y,0,ST_UPDATE);
1431 case DIWALKPIC:
1432 playsound(S_DIM_LAUGHTER+RMOD3("STAT1515"),sprptr[sn]->x,sprptr[sn]->y,0,ST_UPDATE);
1433 break;
1434 case ANTWALKPIC:
1435 playsound(S_MALE_YOULOSER+RMOD3("STAT1518"),sprptr[sn]->x,sprptr[sn]->y,0,ST_UPDATE);
1436 break;
1437 }
1438 }
1439
1440 void
newstatus(short sn,int seq)1441 newstatus(short sn, int seq)
1442 {
1443 short newpic;
1444 short ext;
1445 int zoffs;
1446
1447 #ifdef PLRSPRDEBUG
1448 if( isaplayersprite(sn) ) {
1449 crash("messing w plrsprite at 11");
1450 }
1451 #else
1452 if( isaplayersprite(sn) ) {
1453 return;
1454 }
1455 #endif
1456
1457 ext=sprptr[sn]->extra;
1458 if( !validext(ext) ) {
1459 noextcrash(sn, 0);
1460 }
1461
1462 switch( seq ) {
1463 case INANIMATE:
1464 changespritestat(sn, INANIMATE);
1465 #ifdef NEWSTAT_DEBUG
1466 showmessage("INANIMATE");
1467 #endif
1468 break;
1469 case INACTIVE:
1470 changespritestat(sn, INACTIVE);
1471 #ifdef NEWSTAT_DEBUG
1472 showmessage("INACTIVE");
1473 #endif
1474 break;
1475 case FLOATING:
1476 if( sectptr[sprptr[sn]->sectnum]->lotag == 4 ) {
1477 if( (sprptr[sn]->cstat&128) == 0 ) {
1478 zoffs = -((tilesiz[sprptr[sn]->picnum].y*sprptr[sn]->yrepeat)<<1);
1479 }
1480 else {
1481 zoffs = 0;
1482 }
1483 sprptr[sn]->z=sectptr[sprptr[sn]->sectnum]->floorz-zoffs;
1484 sprptr[sn]->lotag=0;
1485 sprptr[sn]->hitag=0;
1486 sprptr[sn]->xvel=1;
1487 sprptr[sn]->yvel=1;
1488 changespritestat(sn, FLOATING);
1489 }
1490 else {
1491 sprptr[sn]->z=sectptr[sprptr[sn]->sectnum]->floorz;
1492 changespritestat(sn, INACTIVE);
1493 }
1494 break;
1495 case GUARD:
1496 newpic=sprXTptr[ext]->walkpic;
1497 if( newpic != NO_PIC ) {
1498 changespritestat(sn, GUARD);
1499 sprptr[sn]->lotag=0;
1500 sprptr[sn]->picnum=newpic;
1501 sprXTptr[ext]->basestat=GUARD;
1502 #ifdef NEWSTAT_DEBUG
1503 showmessage("GUARD");
1504 #endif
1505 }
1506 break;
1507 case PATROL:
1508 newpic=sprXTptr[ext]->walkpic;
1509 if( newpic != NO_PIC ) {
1510 changespritestat(sn, PATROL);
1511 sprptr[sn]->lotag=0;
1512 sprptr[sn]->picnum=newpic;
1513 sprXTptr[ext]->basestat=PATROL;
1514 #ifdef NEWSTAT_DEBUG
1515 showmessage("PATROL");
1516 #endif
1517 }
1518 break;
1519 case PINBALL:
1520 newpic=sprXTptr[ext]->walkpic;
1521 if( newpic != NO_PIC ) {
1522 changespritestat(sn, PINBALL);
1523 sprptr[sn]->picnum=newpic;
1524 sprXTptr[ext]->basestat=PINBALL;
1525 #ifdef NEWSTAT_DEBUG
1526 showmessage("PINBALL");
1527 #endif
1528 }
1529 break;
1530 case STROLL:
1531 newpic=sprXTptr[ext]->walkpic;
1532 if( newpic != NO_PIC ) {
1533 changespritestat(sn, STROLL);
1534 sprptr[sn]->lotag=0;
1535 sprptr[sn]->picnum=newpic;
1536 sprXTptr[ext]->basestat=STROLL;
1537 #ifdef NEWSTAT_DEBUG
1538 showmessage("STROLL");
1539 #endif
1540 }
1541 break;
1542 case CHASE:
1543 newpic=sprXTptr[ext]->runpic;
1544 if( newpic != NO_PIC ) {
1545 changespritestat(sn, CHASE);
1546 sprptr[sn]->lotag=0;
1547 sprptr[sn]->picnum=newpic;
1548 sprXTptr[ext]->basestat=CHASE;
1549 #ifdef NEWSTAT_DEBUG
1550 showmessage("CHASE");
1551 #endif
1552 }
1553 break;
1554 case FLEE:
1555 newpic=sprXTptr[ext]->runpic;
1556 if( newpic != NO_PIC ) {
1557 changespritestat(sn, FLEE);
1558 sprptr[sn]->lotag=0;
1559 sprptr[sn]->picnum=newpic;
1560 #ifdef NEWSTAT_DEBUG
1561 showmessage("FLEE");
1562 #endif
1563 }
1564 break;
1565 case ATTACK:
1566 // standard 5 angles, 2 frames/angle
1567 newpic=sprXTptr[ext]->attackpic;
1568 if( newpic != NO_PIC ) {
1569 changespritestat(sn,ATTACK);
1570 sprptr[sn]->picnum=newpic;
1571 switch( sprXTptr[ext]->weapon ) {
1572 case 1:
1573 case 2:
1574 case 3:
1575 case 4:
1576 case 5:
1577 sprptr[sn]->lotag=32;
1578 sprptr[sn]->hitag=32;
1579 break;
1580 default:
1581 sprptr[sn]->lotag=64;
1582 sprptr[sn]->hitag=64;
1583 break;
1584 }
1585 #ifdef NEWSTAT_DEBUG
1586 showmessage("ATTACK");
1587 #endif
1588 }
1589 break;
1590 case DELAYEDATTACK:
1591 // standard 5 angles, 2 frames/angle
1592 sprptr[sn]->lotag=95;
1593 changespritestat(sn, DELAYEDATTACK);
1594 #ifdef NEWSTAT_DEBUG
1595 showmessage("DELAYED ATTACK");
1596 #endif
1597 break;
1598 case STALK:
1599 newpic=sprXTptr[ext]->runpic;
1600 if( newpic != NO_PIC ) {
1601 changespritestat(sn, STALK);
1602 sprptr[sn]->lotag=0;
1603 sprptr[sn]->picnum=newpic;
1604 sprXTptr[ext]->basestat=STALK;
1605 #ifdef NEWSTAT_DEBUG
1606 showmessage("STALK");
1607 #endif
1608 }
1609 break;
1610 case SQUAT:
1611 newpic=sprXTptr[ext]->squatpic;
1612 if ( newpic != NO_PIC ) {
1613 changespritestat(sn, SQUAT);
1614 // standard 3 frames
1615 // stay squat for 4 TICSPERFRAME
1616 sprptr[sn]->lotag=47;
1617 sprptr[sn]->hitag=64;
1618 #ifdef NEWSTAT_DEBUG
1619 showmessage("SQUAT");
1620 #endif
1621 }
1622 break;
1623 case UNSQUAT:
1624 newpic=sprXTptr[ext]->squatpic;
1625 if ( newpic != NO_PIC ) {
1626 changespritestat(sn, UNSQUAT);
1627 sprptr[sn]->lotag=47;
1628 sprptr[sn]->hitag=0;
1629 #ifdef NEWSTAT_DEBUG
1630 showmessage("UNSQUAT");
1631 #endif
1632 }
1633 break;
1634 case DODGE:
1635 newpic=sprXTptr[ext]->squatpic;
1636 if ( newpic != NO_PIC ) {
1637 changespritestat(sn, SQUAT);
1638 // standard 2 frames
1639 sprptr[sn]->lotag=31;
1640 sprptr[sn]->hitag=0;
1641 #ifdef NEWSTAT_DEBUG
1642 showmessage("DODGE");
1643 #endif
1644 }
1645 break;
1646 case UNDODGE:
1647 newpic=sprXTptr[ext]->squatpic;
1648 if ( newpic != NO_PIC ) {
1649 changespritestat(sn, UNSQUAT);
1650 sprptr[sn]->lotag=31;
1651 sprptr[sn]->hitag=0;
1652 #ifdef NEWSTAT_DEBUG
1653 showmessage("UNDODGE");
1654 #endif
1655 }
1656 break;
1657 case HIDE:
1658 newpic=sprXTptr[ext]->squatpic;
1659 if ( newpic != NO_PIC ) {
1660 changespritestat(sn, HIDE);
1661 // standard 2 frames
1662 sprptr[sn]->lotag=31;
1663 sprptr[sn]->hitag=256;
1664 #ifdef NEWSTAT_DEBUG
1665 showmessage("HIDE");
1666 #endif
1667 }
1668 break;
1669 case UNHIDE:
1670 newpic=sprXTptr[ext]->squatpic;
1671 if ( newpic != NO_PIC ) {
1672 changespritestat(sn, UNHIDE);
1673 sprptr[sn]->lotag=31;
1674 sprptr[sn]->hitag=0;
1675 #ifdef NEWSTAT_DEBUG
1676 showmessage("UNHIDE");
1677 #endif
1678 }
1679 break;
1680 case PAIN:
1681 newpic=sprXTptr[ext]->painpic;
1682 if ( newpic != 0 ) {
1683 changespritestat(sn,PAIN);
1684 sprptr[sn]->picnum=newpic;
1685 sprptr[sn]->lotag=16;
1686 #ifdef NEWSTAT_DEBUG
1687 showmessage("PAIN");
1688 #endif
1689 }
1690 break;
1691 case STANDING:
1692 newpic=sprXTptr[ext]->standpic;
1693 if( newpic != 0 ) {
1694 sprptr[sn]->picnum=newpic;
1695 if( sprptr[sn]->lotag <= 0 ) {
1696 sprptr[sn]->lotag=((krand_intercept("STAT1732"))&1024);
1697 }
1698 changespritestat(sn, STANDING);
1699 #ifdef NEWSTAT_DEBUG
1700 showmessage("STANDING");
1701 #endif
1702 }
1703 break;
1704 case FLY:
1705 newpic=sprXTptr[ext]->runpic;
1706 if( newpic != NO_PIC ) {
1707 changespritestat(sn, FLY);
1708 sprptr[sn]->lotag=0;
1709 sprptr[sn]->picnum=newpic;
1710 sprXTptr[ext]->basestat=FLY;
1711 #ifdef NEWSTAT_DEBUG
1712 showmessage("FLY");
1713 #endif
1714 }
1715 break;
1716 case RODENT:
1717 newpic=sprXTptr[ext]->runpic;
1718 if( newpic != NO_PIC ) {
1719 changespritestat(sn, RODENT);
1720 sprptr[sn]->lotag=0;
1721 sprptr[sn]->picnum=newpic;
1722 sprXTptr[ext]->basestat=RODENT;
1723 #ifdef NEWSTAT_DEBUG
1724 showmessage("RODENT");
1725 #endif
1726 }
1727 break;
1728 case MORPH:
1729 if ( sprXTptr[ext]->morphpic != 0 ) {
1730 changespritestat(sn,MORPH);
1731 sprptr[sn]->lotag=95;
1732 #ifdef NEWSTAT_DEBUG
1733 showmessage("MORPH");
1734 #endif
1735 }
1736 break;
1737 case DEATH:
1738 newpic=sprXTptr[ext]->deathpic;
1739 sprptr[sn]->cstat&=~257;
1740 if( newpic != 0 ) {
1741 changespritestat(sn,DEATH);
1742 deathdropitem(sn);
1743 getpicinfo(newpic);
1744 sprptr[sn]->lotag=((picinfoptr->numframes)<<4)-1;
1745 sprptr[sn]->hitag=sprptr[sn]->lotag;
1746 deathsounds(newpic,sprptr[sn]->x,sprptr[sn]->y);
1747 sprptr[sn]->picnum=newpic;
1748 }
1749 else {
1750 changespritestat(sn, INACTIVE);
1751 }
1752 #ifdef NEWSTAT_DEBUG
1753 showmessage("DEATH");
1754 #endif
1755 break;
1756 }
1757
1758 }
1759
1760 int
damagesprite(int hitsprite,int points)1761 damagesprite(int hitsprite, int points)
1762 {
1763 short ext;
1764
1765 #ifdef PLRSPRDEBUG
1766 if( isaplayersprite(hitsprite) ) {
1767 crash("messing w plrsprite at 12");
1768 }
1769 #else
1770 if( isaplayersprite(hitsprite) ) {
1771 return(0);
1772 }
1773 #endif
1774
1775 ext=sprptr[hitsprite]->extra;
1776
1777 switch( sprptr[hitsprite]->statnum ) {
1778 case INANIMATE:
1779 if( validext(ext) ) {
1780 newstatus(hitsprite, DEATH);
1781 }
1782 return(0);
1783 case GENEXPLODE1:
1784 changespritestat(hitsprite,INACTIVE);
1785 genexplosion1(hitsprite);
1786 //changespritestat(hitsprite,VANISH);
1787 jsdeletesprite(hitsprite);
1788 return(0);
1789 case GENEXPLODE2:
1790 changespritestat(hitsprite,INACTIVE);
1791 genexplosion2(hitsprite);
1792 //changespritestat(hitsprite,VANISH);
1793 jsdeletesprite(hitsprite);
1794 return(0);
1795 case INACTIVE:
1796 case FLOATING:
1797 return(0);
1798 case PROJHIT:
1799 case PROJECTILE:
1800 case TOSS:
1801 case PAIN:
1802 case RUNTHRU:
1803 case TWITCH:
1804 case DEATH:
1805 return(0);
1806 default:
1807 break;
1808 }
1809
1810 if( difficulty == 0 ) {
1811 points<<=1;
1812 }
1813
1814 if( validext(ext) ) {
1815 if( (labs(points)) > sprXTptr[ext]->hitpoints ) {
1816 sprXTptr[ext]->hitpoints=0;
1817 }
1818 else {
1819 sprXTptr[ext]->hitpoints-=points;
1820 }
1821 sprXTptr[ext]->aimask|=AI_JUSTSHOTAT;
1822 sprXTptr[ext]->aimask|=AI_TIMETODODGE;
1823 sprXTptr[ext]->aimask|=AI_WASATTACKED;
1824 if( sprXTptr[ext]->hitpoints < ENEMYCRITICALCONDITION )
1825 sprXTptr[ext]->aimask|=AI_CRITICAL;
1826 if( sprXTptr[ext]->hitpoints <= 0 ) {
1827 sprXTptr[ext]->hitpoints=0;
1828 //newstatus(hitsprite,DEATH);
1829 sprXTptr[ext]->fxmask|=FX_NXTSTTDEATH;
1830 return(1);
1831 }
1832 else {
1833 //newstatus(hitsprite,PAIN);
1834 sprXTptr[ext]->fxmask|=FX_NXTSTTPAIN;
1835 }
1836 }
1837
1838 return(0);
1839 }
1840
1841 void
attackifclose(short i,int snum,int dist)1842 attackifclose(short i, int snum, int dist)
1843 {
1844 int mindist;
1845 short ext;
1846
1847 #ifdef PLRSPRDEBUG
1848 if( isaplayersprite(i) ) {
1849 crash("messing w plrsprite at 13");
1850 }
1851 #endif
1852
1853 if( !validplayer(snum) ) {
1854 crash("atakifclse: bad plrnum");
1855 }
1856 if( health[snum] <= 0 ) {
1857 return;
1858 }
1859 ext=sprptr[i]->extra;
1860 if( !validext(ext) ) {
1861 return;
1862 }
1863
1864 switch( sprptr[i]->statnum ) {
1865 case CHASE:
1866 mindist=CHASEATTDIST;
1867 break;
1868 case PATROL:
1869 case GUARD:
1870 mindist=GUARDATTDIST;
1871 break;
1872 case STALK:
1873 mindist=STALKATTDIST;
1874 break;
1875 default:
1876 mindist=MINATTACKDIST;
1877 break;
1878 }
1879
1880 switch( sprptr[i]->picnum ) {
1881 case RATPIC:
1882 mindist=1024L;
1883 break;
1884 case BATPIC:
1885 if( RMOD4("STAT1968") != 0 ) {
1886 return;
1887 }
1888 mindist=1024;
1889 if( dist <= 1024 ) {
1890 sprptr[i]->z=posz[snum]-4096;
1891 }
1892
1893 break;
1894 default:
1895 break;
1896 }
1897
1898 if ( (dist < mindist) ) {
1899 switch( sprptr[i]->statnum ) {
1900 default:
1901 sprptr[i]->ang=
1902 getangle(posx[snum]-sprptr[i]->x,posy[snum]-sprptr[i]->y);
1903 newstatus(i, ATTACK);
1904 break;
1905 }
1906 }
1907
1908 return;
1909 }
1910
1911 void
enemygunshot(int sn)1912 enemygunshot(int sn)
1913 {
1914 int j,nextj,ext;
1915 int dist;
1916
1917 #ifdef PLRSPRDEBUG
1918 if( isaplayersprite(sn) ) {
1919 crash("messing w plrsprite at 14");
1920 }
1921 #endif
1922
1923 j=headspritestat[STROLL];
1924 while( j != -1 ) {
1925 nextj = nextspritestat[j];
1926
1927 ext=sprptr[j]->extra;
1928 if( !validext(ext) ) {
1929 noextcrash(sn,100);
1930 }
1931 dist = labs(sprptr[sn]->x-sprptr[j]->x)+labs(sprptr[sn]->y-sprptr[j]->y);
1932 if( dist < HEARGUNSHOTDIST ) {
1933 sprXTptr[ext]->aimask|=AI_JUSTSHOTAT;
1934 }
1935
1936 j = nextj;
1937 }
1938
1939 j=headspritestat[STANDING];
1940 while( j != -1 ) {
1941 nextj = nextspritestat[j];
1942
1943 ext=sprptr[j]->extra;
1944 if( !validext(ext) ) {
1945 noextcrash(sn,101);
1946 }
1947
1948 // guards not woken by enemies gun shot
1949 if( sprXTptr[ext]->basestat != GUARD ) {
1950 dist = labs(sprptr[sn]->x-sprptr[j]->x)+labs(sprptr[sn]->y-sprptr[j]->y);
1951 if( dist < HEARGUNSHOTDIST ) {
1952 sprXTptr[ext]->aimask|=AI_JUSTSHOTAT;
1953 }
1954 }
1955
1956 j = nextj;
1957 }
1958
1959 #ifdef WAKEUPGUARDSBYENEMYGUNSHOT
1960 j=headspritestat[GUARD];
1961 while( j != -1 ) {
1962 nextj = nextspritestat[j];
1963
1964 if( j == sn ) {
1965 j=nextj;
1966 continue;
1967 }
1968
1969 ext=sprptr[j]->extra;
1970 if( !validext(ext) ) {
1971 noextcrash(sn,102);
1972 }
1973 dist = labs(sprptr[sn]->x-sprptr[j]->x)+labs(sprptr[sn]->y-sprptr[j]->y);
1974 if( dist < HEARGUNSHOTDIST ) {
1975 sprXTptr[ext]->aimask|=AI_JUSTSHOTAT;
1976 }
1977
1978 j = nextj;
1979 }
1980 #endif
1981 }
1982
1983 void
playergunshot(int snum)1984 playergunshot(int snum)
1985 {
1986 int j,nextj,ext;
1987 int dist;
1988
1989 if( !validplayer(snum) ) {
1990 crash("plgunsht: bad plrnum");
1991 }
1992
1993 j=headspritestat[STROLL];
1994 while( j != -1 ) {
1995 nextj = nextspritestat[j];
1996
1997 ext=sprptr[j]->extra;
1998 if( !validext(ext) ) {
1999 noextcrash(j,103);
2000 }
2001 dist = labs(sprptr[j]->x-posx[snum])+labs(sprptr[j]->y-posy[snum]);
2002 if( dist < HEARGUNSHOTDIST ) {
2003 sprXTptr[ext]->aimask|=AI_JUSTSHOTAT;
2004 }
2005
2006 j = nextj;
2007 }
2008
2009 j=headspritestat[STANDING];
2010 while( j != -1 ) {
2011 nextj = nextspritestat[j];
2012
2013 ext=sprptr[j]->extra;
2014 if( !validext(ext) ) {
2015 noextcrash(j,105);
2016 }
2017 dist = labs(sprptr[j]->x-posx[snum])+labs(sprptr[j]->y-posy[snum]);
2018 if( dist < HEARGUNSHOTDIST ) {
2019 sprXTptr[ext]->aimask|=AI_JUSTSHOTAT;
2020 }
2021
2022 j = nextj;
2023 }
2024
2025 j=headspritestat[GUARD];
2026 while( j != -1 ) {
2027 nextj = nextspritestat[j];
2028
2029 ext=sprptr[j]->extra;
2030 if( !validext(ext) ) {
2031 noextcrash(j,106);
2032 }
2033 dist = labs(sprptr[j]->x-posx[snum])+labs(sprptr[j]->y-posy[snum]);
2034 if( dist < HEARGUNSHOTDIST ) {
2035 sprXTptr[ext]->aimask|=AI_JUSTSHOTAT;
2036 }
2037
2038 j = nextj;
2039 }
2040 }
2041
2042 void
enemywoundplayer(short plrhit,short sprnum,char guntype)2043 enemywoundplayer(short plrhit, short sprnum, char guntype)
2044 {
2045 int damage=0;
2046
2047 #ifdef PLRSPRDEBUG
2048 if( isaplayersprite(sprnum) ) {
2049 crash("messing w plrsprite at 15");
2050 }
2051 #endif
2052
2053 if( !validplayer(plrhit) ) {
2054 return;
2055 }
2056
2057 switch( guntype ) {
2058 case 0:
2059 damage=64;
2060 break;
2061 case 1:
2062 case 2:
2063 case 3:
2064 case 4:
2065 case 5:
2066 damage=128;
2067 break;
2068 case 6:
2069 default:
2070 damage=256;
2071 break;
2072 }
2073 switch( difficulty ) {
2074 case 0:
2075 case 1:
2076 damage>>=4;
2077 break;
2078 case 2:
2079 damage>>=3;
2080 break;
2081 case 3:
2082 damage>>=2;
2083 break;
2084 }
2085
2086 changehealth(plrhit,-damage);
2087 }
2088
2089 void
enemyshootgun(short sprnum,int x,int y,int z,short daang,int dahoriz,short dasectnum,char guntype)2090 enemyshootgun(short sprnum,int x,int y,int z,short daang,int dahoriz,
2091 short dasectnum,char guntype)
2092 {
2093 hitdata_t hitinfo;
2094 short daang2;
2095 int j,daz2,discrim;
2096 int ext,target,pnum;
2097
2098 #ifdef PLRSPRDEBUG
2099 if( isaplayersprite(sprnum) ) {
2100 crash("messing w plrsprite at 16");
2101 }
2102 #endif
2103
2104 ext=sprptr[sprnum]->extra;
2105 if( !validext(ext) ) {
2106 crash("enemyshootgun: bad ext");
2107 }
2108 target=sprXTptr[sprnum]->target;
2109 if( !validplayer(target) ) {
2110 return;
2111 }
2112
2113 // enemy gun fire sounds
2114 switch (guntype) {
2115 case 0:
2116 switch( sprXTptr[ext]->attackpic ) {
2117 case RATATTACKPIC:
2118 break;
2119 case 3910:
2120 playsound(S_WH_8,x,y,0,ST_NOUPDATE);
2121 break;
2122 default:
2123 playsound(S_MATRIX_ATTACK2,x,y,0,ST_NOUPDATE);
2124 break;
2125 }
2126 break;
2127 case 1:
2128 case 2:
2129 case 3:
2130 case 4:
2131 switch( sprXTptr[ext]->attackpic ) {
2132 case 3773:
2133 case 3800:
2134 case 3805:
2135 case 3810:
2136 case 3818:
2137 playsound(S_MATRIX_ATTACK,x,y,0,ST_NOUPDATE);
2138 break;
2139 case 3850:
2140 case 3860:
2141 case 3890:
2142 case 3909:
2143 case 3952:
2144 case 4001:
2145 playsound(S_MATRIX_ATTACK2,x,y,0,ST_NOUPDATE);
2146 break;
2147 case COPATTACKPIC:
2148 playsound(S_ENEMYGUN1,x,y,0,ST_NOUPDATE);
2149 break;
2150 case ANTATTACKPIC:
2151 playsound(S_ENEMYGUN2,x,y,0,ST_NOUPDATE);
2152 break;
2153 case MAATTACKPIC:
2154 playsound(S_ENEMYGUN3,x,y,0,ST_NOUPDATE);
2155 break;
2156 case SAMATTACKPIC:
2157 playsound(S_ENEMYGUN4,x,y,0,ST_NOUPDATE);
2158 break;
2159 default:
2160 playsound(S_ENEMYGUN1,x,y,0,ST_NOUPDATE);
2161 break;
2162 }
2163 break;
2164 case 5:
2165 case 6:
2166 case 7:
2167 case 8:
2168 switch( sprXTptr[ext]->attackpic ) {
2169 case 3773:
2170 case 3800:
2171 case 3805:
2172 case 3810:
2173 case 3818:
2174 playsound(S_MATRIX_ATTACK,x,y,0,ST_NOUPDATE);
2175 break;
2176 case 3850:
2177 case 3860:
2178 case 3890:
2179 case 3909:
2180 case 3952:
2181 case 4001:
2182 playsound(S_MATRIX_ATTACK2,x,y,0,ST_NOUPDATE);
2183 break;
2184 default:
2185 playsound(S_AUTOGUN,x,y,0,ST_NOUPDATE);
2186 }
2187 break;
2188 default:
2189 break;
2190 }
2191
2192 // gun shot code
2193 switch (guntype) {
2194 case 0:
2195 if( (labs(x-posx[target])+labs(y-posy[target])) < 1024 ) {
2196 if( labs(z-posz[target]) < 12288 ) {
2197 playerpainsound(target);
2198 if( ((sprXTptr[ext]->fxmask)&FX_HOLOGRAM) != 0 ) {
2199 playsound(S_MATRIX_ATTACK,x,y,0,ST_NOUPDATE);
2200 enemywoundplayer(target,sprnum,0);
2201 }
2202 if( ((sprXTptr[ext]->fxmask)&FX_ANDROID) != 0 ) {
2203 androidexplosion(sprnum);
2204 enemywoundplayer(target,sprnum,6);
2205 //changespritestat(sprnum, VANISH);
2206 jsdeletesprite(sprnum);
2207 }
2208 else {
2209 enemywoundplayer(target,sprnum,0);
2210 }
2211 }
2212 }
2213 return;
2214 case GUN3FLAG:
2215 case GUN4FLAG:
2216 case GUN5FLAG:
2217 daang2=daang;
2218 daz2=((100-dahoriz)<<11);
2219 z=posz[target]; // instead of calculating a dot product angle
2220 vec3_t pos;
2221 pos.x = x; pos.y = y; pos.z = z;
2222
2223 hitscan(&pos,dasectnum,sintable[(daang2+2560)&2047], sintable[(daang2+2048)&2047],daz2, &hitinfo, CLIPMASK1);
2224 if( hitinfo.sprite > 0 ) {
2225 if( playerhit(hitinfo.sprite, &pnum) ) {
2226 playerpainsound(pnum);
2227 enemywoundplayer(pnum,sprnum,3);
2228 }
2229 else {
2230 damagesprite(hitinfo.sprite,tekgundamage(guntype,x,y,z, hitinfo.sprite));
2231 }
2232 }
2233 else {
2234 j=jsinsertsprite(hitinfo.sect, 3);
2235 if( j != -1 ) {
2236 fillsprite(j,hitinfo.pos.x,hitinfo.pos.y,hitinfo.pos.z+(8<<8),2,-4,0,32,16,16,0,0,
2237 EXPLOSION,daang,0,0,0,sprnum+MAXSPRITES,hitsect,3,63,0,0);
2238 }
2239 }
2240 break;
2241 case GUN6FLAG:
2242 j = jsinsertsprite(sprptr[sprnum]->sectnum, PROJECTILE);
2243 if ( j == -1 ) {
2244 break;
2245 }
2246 sprptr[j]->x=sprptr[sprnum]->x;
2247 sprptr[j]->y=sprptr[sprnum]->y;
2248 switch( sprXTptr[ext]->basestat ) {
2249 case FLY:
2250 sprptr[j]->z=sprptr[sprnum]->z;
2251 break;
2252 default:
2253 sprptr[j]->z=sectptr[sprptr[sprnum]->sectnum]->floorz-8192;
2254 break;
2255 }
2256 sprptr[j]->cstat=0x01;
2257 sprptr[j]->picnum=PULSARPIC;
2258 sprptr[j]->shade=-32;
2259 sprptr[j]->xrepeat=32;
2260 sprptr[j]->yrepeat=32;
2261 sprptr[j]->ang=sprptr[sprnum]->ang;
2262 sprptr[j]->xvel=(sintable[(sprptr[j]->ang+2560)&2047]>>4);
2263 sprptr[j]->yvel=(sintable[(sprptr[j]->ang+2048)&2047]>>4);
2264 discrim=ksqrt((posx[target]-sprptr[j]->x)*(posx[target]-sprptr[j]->x) +
2265 (posy[target]-sprptr[j]->y)*(posy[target]-sprptr[j]->y));
2266 if ( discrim == 0 ) {
2267 discrim=1;
2268 }
2269 sprptr[j]->zvel=((posz[target]+(8<<8)-sprptr[j]->z)<<9)/discrim;
2270 sprptr[j]->owner=sprnum;
2271 sprptr[j]->clipdist=16L;
2272 sprptr[j]->lotag=0;
2273 sprptr[j]->hitag=0;
2274 break;
2275 default:
2276 break;
2277 }
2278
2279 if( guntype != 0 ) {
2280 enemygunshot(sprnum);
2281 }
2282 }
2283
2284 int
isahologram(int i)2285 isahologram(int i)
2286 {
2287 int ext=sprptr[i]->extra;
2288
2289 #ifdef PLRSPRDEBUG
2290 if( isaplayersprite(i) ) {
2291 crash("messing w plrsprite at 21");
2292 }
2293 #endif
2294
2295 if( validext(ext) ) {
2296 if( ((sprXTptr[ext]->fxmask)&FX_HOLOGRAM) != 0 ) {
2297 return(1);
2298 }
2299 }
2300
2301 return(0);
2302 }
2303
2304 int
isanandroid(int i)2305 isanandroid(int i)
2306 {
2307 int ext=sprptr[i]->extra;
2308
2309 #ifdef PLRSPRDEBUG
2310 if( isaplayersprite(i) ) {
2311 crash("messing w plrsprite at 22");
2312 }
2313 #endif
2314
2315 if( validext(ext) ) {
2316 if( ((sprXTptr[ext]->fxmask)&FX_ANDROID) != 0 ) {
2317 return(1);
2318 }
2319 }
2320
2321 return(0);
2322 }
2323
2324 void
enemynewsector(int i)2325 enemynewsector(int i)
2326 {
2327 int ext=sprptr[i]->extra;
2328
2329 if( option[4] != 0 ) {
2330 return;
2331 }
2332
2333 #ifdef PLRSPRDEBUG
2334 if( isaplayersprite(i) ) {
2335 crash("messing w plrsprite at 23");
2336 }
2337 #endif
2338
2339 if( ensfirsttime == 1 ) {
2340 ensfirsttime=0;
2341 return;
2342 }
2343
2344 switch( sectptr[sprptr[i]->sectnum]->lotag ) {
2345 case 4:
2346 playsound(S_SPLASH,sprptr[i]->x,sprptr[i]->y,0,ST_UPDATE);
2347 break;
2348 default:
2349 break;
2350 }
2351 switch( sectptr[sprptr[i]->sectnum]->hitag ) {
2352 case 1010:
2353 case 1011:
2354 case 1012:
2355 case 1013:
2356 case 1014:
2357 case 1015:
2358 case 1016:
2359 case 1017:
2360 case 1018:
2361 case 1019:
2362 if( isahologram(i) ) {
2363 jsdeletesprite(i);
2364 return;
2365 }
2366 if( tekexplodebody(i) ) {
2367 missionaccomplished(i);
2368 }
2369 playsound(S_BUSHIT, sprptr[i]->x,sprptr[i]->y, 0, ST_UPDATE);
2370 if( validext(ext) ) {
2371 switch( sprXTptr[ext]->basepic ) {
2372 case ERWALKPIC:
2373 playsound(S_MANDIE1+RMOD4("STAT2615")+RMOD3("STAT2615"),sprptr[i]->x,sprptr[i]->y,0,ST_UPDATE);
2374 break;
2375 case SARAHWALKPIC:
2376 playsound(S_GIRLDIE1+RMOD4("STAT2618")+RMOD3("STAT2618"),sprptr[i]->x,sprptr[i]->y,0,ST_UPDATE);
2377 break;
2378 case SAMWALKPIC:
2379 playsound(S_MANDIE1+RMOD4("STAT2621")+RMOD3("STAT2621"),sprptr[i]->x,sprptr[i]->y,0,ST_UPDATE);
2380 break;
2381 }
2382 }
2383 jsdeletesprite(i);
2384 break;
2385 default:
2386 operatesector(sprptr[i]->sectnum); // JEFF TEST
2387 break;
2388 }
2389 }
2390
2391 void
ambushyell(short sn,short ext)2392 ambushyell(short sn, short ext)
2393 {
2394 #ifdef PLRSPRDEBUG
2395 if( isaplayersprite(sn) ) {
2396 crash("messing w plrsprite at 24");
2397 }
2398 #endif
2399
2400 if( !validext(ext) ) {
2401 return;
2402 }
2403 if( sprXTptr[ext]->aimask&AI_DIDAMBUSHYELL )
2404 return;
2405
2406 switch( sprXTptr[ext]->basepic ) {
2407 case ANTWALKPIC:
2408 case RUBWALKPIC:
2409 playsound(S_MALE_COMEONYOU+(krand_intercept("STAT2603")&6),sprptr[sn]->x,sprptr[sn]->y,0,ST_IMMEDIATE);
2410 sprXTptr[ext]->aimask|=AI_DIDAMBUSHYELL;
2411 break;
2412 case DIWALKPIC:
2413 playsound(S_DIM_WANTSOMETHIS+(krand_intercept("STAT2607")&2),sprptr[sn]->x,sprptr[sn]->y,0,ST_IMMEDIATE);
2414 sprXTptr[ext]->aimask|=AI_DIDAMBUSHYELL;
2415 break;
2416 }
2417 }
2418
2419 void
givewarning(short i,short ext)2420 givewarning(short i, short ext)
2421 {
2422 int dist = 0L;
2423
2424 #ifdef PLRSPRDEBUG
2425 if( isaplayersprite(i) ) {
2426 crash("messing w plrsprite at 25");
2427 }
2428 #endif
2429
2430 if( option[4] != 0 ) {
2431 return;
2432 }
2433 if( !validext(ext) ) {
2434 return;
2435 }
2436 if( sprXTptr[ext]->aimask&AI_GAVEWARNING )
2437 return;
2438
2439 dist=labs(posx[screenpeek]-sprptr[i]->x)+labs(posy[screenpeek]-sprptr[i]->y);
2440 if( dist > 5000 ) {
2441 return;
2442 }
2443
2444 switch( sprXTptr[ext]->basepic ) {
2445 case COP1WALKPIC:
2446 playsound(S_GRD_WHATDOINGHERE+(krand_intercept("STAT2636")&4),sprptr[i]->x,sprptr[i]->y,0,ST_UNIQUE);
2447 sprXTptr[ext]->aimask|=AI_GAVEWARNING;
2448 break;
2449 }
2450 }
2451
2452 void
statuslistcode()2453 statuslistcode()
2454 {
2455 vec3_t pos;
2456 short p, target, hitobject, daang, osectnum, movestat, hitsprite,ext;
2457 int i, nexti, dax, day, daz, dist, mindist;
2458 int prevx,prevy,prevz;
2459 short prevsect=0;
2460 int seecan;
2461 int targx,targy,targz;
2462 short targang,targsect,host,tempshort;
2463 int pnum;
2464 int px,py,pz,deltapy,zoffs;
2465 spritetype *spr;
2466
2467 dosectorflash();
2468
2469 #ifdef DEBUGBREAKHERE
2470 if( keystatus[37] != 0 ) {
2471 keystatus[37]=0;
2472 i=1;
2473 }
2474 #endif
2475
2476 if( (lockclock-stackedcheck) > 30 ) {
2477 stackedcheck=lockclock;
2478 i = headspritestat[STACKED];
2479 while (i >= 0)
2480 {
2481 nexti = nextspritestat[i];
2482
2483 if( sprptr[i]->z != sectptr[sprptr[i]->sectnum]->floorz ) {
2484 spr=sprptr[i];
2485 tempshort=spr->cstat;
2486 spr->cstat&=~1;
2487
2488 vec3_t pos;
2489 pos.x = spr->x; pos.y = spr->y; pos.z = spr->z - 1;
2490
2491 getzrange(&pos,spr->sectnum, &globhiz,&globhihit,&globloz,&globlohit, ((int)spr->clipdist)<<2,CLIPMASK1);
2492 spr->cstat=tempshort;
2493 if( spr->z != globloz ) {
2494 spr->hitag=0;
2495 changespritestat(i, FALL);
2496 }
2497 }
2498 #ifdef VERIFYSTATS
2499 verifystatus(nexti,STACKED);
2500 #endif
2501 i = nexti;
2502 }
2503 }
2504
2505 i = headspritestat[VANISH];
2506 while (i >= 0)
2507 {
2508 nexti = nextspritestat[i];
2509
2510 jsdeletesprite(i);
2511
2512 i = nexti;
2513 }
2514
2515 i = headspritestat[FALL];
2516 while (i >= 0)
2517 {
2518 nexti = nextspritestat[i];
2519
2520 spr=sprptr[i];
2521
2522 spr->z+=(TICSPERFRAME<<11);
2523
2524 tempshort=spr->cstat;
2525 spr->cstat&=~1;
2526
2527 vec3_t pos;
2528 pos.x = spr->x; pos.y = spr->y; pos.z = spr->z - 1;
2529
2530 getzrange(&pos,spr->sectnum, &globhiz,&globhihit,&globloz,&globlohit, ((int)spr->clipdist)<<2,CLIPMASK1);
2531 spr->cstat=tempshort;
2532 if( spr->z >= globloz ) {
2533 spr->z=globloz;
2534 if( globloz < sectptr[spr->sectnum]->floorz ) {
2535 changespritestat(i, STACKED);
2536 }
2537 else {
2538 changespritestat(i, INANIMATE);
2539 }
2540 }
2541
2542 #ifdef VERIFYSTATS
2543 verifystatus(nexti,FALL);
2544 #endif
2545 i = nexti;
2546 }
2547
2548 i = headspritestat[3]; //Go through smoke sprites
2549 while (i >= 0)
2550 {
2551 nexti = nextspritestat[i];
2552
2553 sprite[i].z -= (TICSPERFRAME<<3);
2554 sprite[i].lotag -= TICSPERFRAME;
2555 if (sprite[i].lotag < 0)
2556 jsdeletesprite(i);
2557
2558 #ifdef VERIFYSTATS
2559 verifystatus(nexti,3);
2560 #endif
2561 i = nexti;
2562 }
2563
2564 i = headspritestat[5]; //Go through explosion sprites
2565 while (i >= 0)
2566 {
2567 nexti = nextspritestat[i];
2568
2569 sprite[i].lotag -= TICSPERFRAME;
2570 if (sprite[i].lotag < 0)
2571 jsdeletesprite(i);
2572
2573 #ifdef VERIFYSTATS
2574 verifystatus(nexti,5);
2575 #endif
2576 i = nexti;
2577 }
2578
2579 i=headspritestat[RUNTHRU];
2580 while (i >= 0)
2581 {
2582 nexti = nextspritestat[i];
2583
2584 sprptr[i]->hitag++;
2585
2586 if( sprptr[i]->hitag >= TICSPERFRAME ) {
2587 sprptr[i]->picnum++;
2588 sprptr[i]->hitag=0;
2589 sprptr[i]->lotag--;
2590 }
2591 if( sprptr[i]->lotag <= 0 ) {
2592 jsdeletesprite(i);
2593 }
2594
2595 #ifdef VERIFYSTATS
2596 verifystatus(nexti,RUNTHRU);
2597 #endif
2598 i = nexti;
2599 }
2600
2601 i=headspritestat[FLOATING];
2602 while (i >= 0)
2603 {
2604 nexti = nextspritestat[i];
2605
2606 prevx=sprptr[i]->x;
2607 prevy=sprptr[i]->y;
2608 prevz=sprptr[i]->z;
2609 prevsect=sprptr[i]->sectnum;
2610
2611 // bob on surface
2612 sprptr[i]->hitag++;
2613 if( sprptr[i]->hitag >= (TICSPERFRAME) ) {
2614 sprptr[i]->lotag++;
2615 if( sprptr[i]->lotag >= MAXBOBS ) {
2616 sprptr[i]->lotag=0;
2617 }
2618 sprptr[i]->z+=(bobbing[sprptr[i]->lotag]<<4);
2619 sprptr[i]->hitag=0;
2620 }
2621 dax=( ((sintable[(sprptr[i]->ang+512)&2047])*sprptr[i]->xvel) <<3 );
2622 day=( ((sintable[sprptr[i]->ang])*sprptr[i]->yvel) <<3 );
2623 movestat=floatmovesprite(i,dax,day,0L,1024L,1024L,NORMALCLIP);
2624 if( (movestat&0xC000) == 32768 ) {
2625 pos.x = prevx; pos.y = prevy; pos.z = prevz;
2626 setsprite(i, &pos);
2627 sprptr[i]->ang=walldeflect(movestat&0x0FFF,sprptr[i]->ang);
2628 }
2629 else if( (movestat&0xC000) == 49152 ) {
2630 pos.x = prevx; pos.y = prevy; pos.z = prevz;
2631 setsprite(i, &pos);
2632 sprptr[i]->ang=spritedeflect(movestat&0x0FFF,sprptr[i]->ang);
2633 }
2634 else if( prevsect != sprptr[i]->sectnum ) {
2635 pos.x = prevx; pos.y = prevy; pos.z = prevz;
2636 setsprite(i, &pos);
2637 sprptr[i]->ang=arbitraryangle();
2638 }
2639
2640 #ifdef VERIFYSTATS
2641 verifystatus(nexti,FLOATING);
2642 #endif
2643 i = nexti;
2644 }
2645
2646 i=headspritestat[PINBALL];
2647 while (i >= 0)
2648 {
2649 nexti = nextspritestat[i];
2650
2651 ext=sprptr[i]->extra;
2652 if( !validext(ext) ) {
2653 noextcrash(i,19);
2654 }
2655 sprXTptr[ext]->target=0;
2656
2657 prevx=sprptr[i]->x;
2658 prevy=sprptr[i]->y;
2659 prevz=sprptr[i]->z;
2660 prevsect=sprptr[i]->sectnum;
2661
2662 dax=( ((sintable[(sprptr[i]->ang+512)&2047])*sprptr[i]->xvel) <<3 );
2663 day=( ((sintable[sprptr[i]->ang])*sprptr[i]->yvel) <<3 );
2664 movestat=flymovesprite(i,dax,day,0L,1024L,1024L,NORMALCLIP);
2665
2666 if( (movestat&0xC000) == 32768 ) {
2667 pos.x = prevx; pos.y = prevy; pos.z = prevz;
2668 setsprite(i, &pos);
2669 sprptr[i]->ang=walldeflect(movestat&0x0FFF,sprptr[i]->ang);
2670 movestat=flymovesprite(i,dax,day,0L,1024L,1024L,NORMALCLIP);
2671 }
2672 else if( (movestat&0xC000) == 49152 ) {
2673 hitsprite=(movestat&0x0FFF);
2674 pos.x = prevx; pos.y = prevy; pos.z = prevz;
2675 setsprite(i, &pos);
2676 if( playerhit(hitsprite, &pnum) ) {
2677 sprXTptr[ext]->target=pnum;
2678 newstatus(i, ATTACK);
2679 }
2680 else {
2681 sprptr[i]->ang=spritedeflect(hitsprite,sprptr[i]->ang);
2682 movestat=flymovesprite(i,dax,day,0L,1024L,1024L,NORMALCLIP);
2683 }
2684 }
2685 if( movestat != 0 ) {
2686 sprptr[i]->ang=arbitraryangle();
2687 }
2688
2689 #ifdef VERIFYSTATS
2690 verifystatus(nexti,PINBALL);
2691 #endif
2692 i = nexti;
2693 }
2694
2695 i=headspritestat[TIMEBOMB];
2696 while (i >= 0)
2697 {
2698 nexti = nextspritestat[i];
2699
2700 sprptr[i]->hitag--;
2701 if( sprptr[i]->hitag <= 0 ) {
2702 if( sectptr[sprptr[i]->sectnum]->lotag == 4 ) {
2703 splash(i);
2704 }
2705 changespritestat(i,INACTIVE);
2706 genexplosion2(i);
2707 jsdeletesprite(i);
2708 }
2709
2710 #ifdef VERIFYSTATS
2711 verifystatus(nexti,TIMEBOMB);
2712 #endif
2713 i = nexti;
2714 }
2715
2716 i=headspritestat[BLOODFLOW];
2717 while (i >= 0)
2718 {
2719 nexti = nextspritestat[i];
2720
2721 sprptr[i]->hitag++;
2722
2723 if( sprptr[i]->hitag >= (TICSPERFRAME*6) ) {
2724 sprptr[i]->picnum++;
2725 sprptr[i]->hitag=0;
2726 sprptr[i]->lotag++;
2727 }
2728 if( sprptr[i]->lotag == 5 ) {
2729 changespritestat(i, INANIMATE);
2730 }
2731
2732 #ifdef VERIFYSTATS
2733 verifystatus(nexti,BLOODFLOW);
2734 #endif
2735 i = nexti;
2736 }
2737
2738 i = headspritestat[DROPSIES];
2739 while (i != -1)
2740 {
2741 nexti = nextspritestat[i];
2742
2743 dax = ((((int)sprite[i].xvel)*TICSPERFRAME)<<7);
2744 day = ((((int)sprite[i].yvel)*TICSPERFRAME)<<7);
2745 daz = 0;
2746
2747 osectnum = sprite[i].sectnum;
2748 hitobject = movesprite((short)i,dax,day,daz,4L<<8,4L<<8,1);
2749
2750 sprite[i].z += sprite[i].zvel;
2751 sprite[i].zvel += (TICSPERFRAME<<2);
2752 if (sprite[i].z < globhiz+(tilesiz[KLIPPIC].y<<6)) {
2753 sprite[i].z = globhiz+(tilesiz[KLIPPIC].y<<6);
2754 sprite[i].zvel = -(sprite[i].zvel>>1);
2755 }
2756 if (sprite[i].z > globloz-(tilesiz[KLIPPIC].y<<6)) {
2757 sprite[i].z = globloz-(tilesiz[KLIPPIC].y<<6);
2758 sprite[i].zvel = -(sprite[i].zvel>>1);
2759 }
2760
2761 dax = sprite[i].xvel; day = sprite[i].yvel;
2762 dist = dax*dax+day*day;
2763 if (dist < 46000) {
2764 if( sectptr[sprptr[i]->sectnum]->lotag == 4 ) {
2765 if( (sprptr[i]->cstat&128) == 0 ) {
2766 zoffs = -((tilesiz[sprptr[i]->picnum].y*sprptr[i]->yrepeat)<<1);
2767 }
2768 else {
2769 zoffs = 0;
2770 }
2771 sprptr[i]->z=sectptr[sprptr[i]->sectnum]->floorz-zoffs;
2772 changespritestat(i, FLOATING);
2773 sprptr[i]->lotag=0;
2774 sprptr[i]->hitag=0;
2775 sprptr[i]->xvel=1;
2776 sprptr[i]->yvel=1;
2777 }
2778 else {
2779 changespritestat(i, INANIMATE);
2780 }
2781 sprite[i].z=sectptr[sprite[i].sectnum]->floorz;
2782 switch( sprptr[i]->picnum ) {
2783 case KLIPPIC:
2784 sprptr[i]->z-=2048;
2785 break;
2786 default:
2787 break;
2788 }
2789 goto dropsiescontinue;
2790 }
2791 if (mulscale(krand_intercept("STAT2934"),dist,30) == 0) {
2792 sprite[i].xvel -= ksgn(sprite[i].xvel);
2793 sprite[i].yvel -= ksgn(sprite[i].yvel);
2794 sprite[i].zvel -= ksgn(sprite[i].zvel);
2795 }
2796
2797 dropsiescontinue:
2798 #ifdef VERIFYSTATS
2799 verifystatus(nexti,DROPSIES);
2800 #endif
2801 i = nexti;
2802 }
2803
2804 i = headspritestat[7]; //Go through bomb spriral-explosion sprites
2805 while (i >= 0)
2806 {
2807 nexti = nextspritestat[i];
2808
2809 sprite[i].x += ((sprite[i].xvel*TICSPERFRAME)>>4);
2810 sprite[i].y += ((sprite[i].yvel*TICSPERFRAME)>>4);
2811 sprite[i].z += ((sprite[i].zvel*TICSPERFRAME)>>4);
2812
2813 sprite[i].zvel += (TICSPERFRAME<<7);
2814 if (sprite[i].z < sector[sprite[i].sectnum].ceilingz+(4<<8))
2815 {
2816 sprite[i].z = sector[sprite[i].sectnum].ceilingz+(4<<8);
2817 sprite[i].zvel = -(sprite[i].zvel>>1);
2818 }
2819 if (sprite[i].z > sector[sprite[i].sectnum].floorz-(4<<8))
2820 {
2821 sprite[i].z = sector[sprite[i].sectnum].floorz-(4<<8);
2822 sprite[i].zvel = -(sprite[i].zvel>>1);
2823 }
2824
2825 sprite[i].xrepeat = (sprite[i].lotag>>2);
2826 sprite[i].yrepeat = (sprite[i].lotag>>2);
2827
2828 sprite[i].lotag -= TICSPERFRAME;
2829 if (sprite[i].lotag < 0)
2830 jsdeletesprite(i);
2831
2832 #ifdef VERIFYSTATS
2833 verifystatus(nexti,7);
2834 #endif
2835 i = nexti;
2836 }
2837
2838 i = headspritestat[TOSS];
2839 while (i != -1)
2840 {
2841 nexti = nextspritestat[i];
2842
2843 dax = ((((int)sprite[i].xvel)*TICSPERFRAME)<<11);
2844 day = ((((int)sprite[i].yvel)*TICSPERFRAME)<<11);
2845 daz = 0;
2846 movestat=kenmovesprite((short)i,dax,day,daz,4L<<8,4L<<8,1);
2847 switch( movestat&0xC000 ) {
2848 // break stuff, but dont hurt enemies unless direct hit on head
2849 case 49152:
2850 hitsprite=(movestat&0x0FFF);
2851 ext=sprptr[hitsprite]->extra;
2852 if( validext(ext) && (sprXTptr[ext]->deathpic != 0) ) {
2853 switch( sprptr[hitsprite]->statnum ) {
2854 case INANIMATE:
2855 damagesprite(hitsprite, 20);
2856 break;
2857 }
2858 }
2859 break;
2860 }
2861
2862 sprite[i].z += sprite[i].zvel;
2863 sprite[i].zvel += (TICSPERFRAME<<5);
2864 if( sprite[i].z < globhiz+(tilesiz[BOMB].y<<6) ) {
2865 sprite[i].z = globhiz+(tilesiz[BOMB].y<<6);
2866 sprite[i].zvel = -(sprite[i].zvel>>1);
2867 }
2868 if( sprite[i].z > globloz-(tilesiz[BOMB].y<<4) ) {
2869 switch( globlohit&0xC000 ) {
2870 case 49152:
2871 // direct hit on head
2872 hitsprite=globlohit&0x0FFF;
2873 if( playerhit(hitsprite, &pnum) ) {
2874 changehealth(pnum, -40);
2875 }
2876 else if( sprptr[hitsprite]->extra != -1 ) {
2877 playsound(S_BUSHIT,sprptr[hitsprite]->x,sprptr[hitsprite]->y,0,ST_NOUPDATE);
2878 damagesprite(hitsprite, 10);
2879 }
2880 break;
2881 case 16384:
2882 if( (sectptr[globlohit&0x0FFF]->lotag == 4) && (sprptr[i]->picnum != RATTHROWPIC) ) {
2883 if( (sprptr[i]->cstat&128) == 0 ) {
2884 zoffs = -((tilesiz[sprptr[i]->picnum].y*sprptr[i]->yrepeat)<<1);
2885 }
2886 else {
2887 zoffs = 0;
2888 }
2889 sprptr[i]->z=sectptr[sprptr[i]->sectnum]->floorz-zoffs;
2890 splash(( int)i);
2891 switch( sprptr[i]->picnum ) {
2892 case TUBEBOMB:
2893 sprptr[i]->picnum=TUBEBOMB+1;
2894 sprptr[i]->hitag=(krand_intercept("STAT3031")&255);
2895 changespritestat(i, TIMEBOMB);
2896 break;
2897 case DARTBOMB:
2898 sprptr[i]->hitag=(krand_intercept("STAT3035")&255);
2899 sprptr[i]->picnum=DARTBOMB+1;
2900 changespritestat(i, TIMEBOMB);
2901 break;
2902 default:
2903 sprptr[i]->lotag=0;
2904 sprptr[i]->hitag=0;
2905 sprptr[i]->xvel=1;
2906 sprptr[i]->yvel=1;
2907 changespritestat(i, FLOATING);
2908 break;
2909 }
2910 goto tosscontinue;
2911 }
2912 break;
2913 }
2914 sprite[i].z = globloz-(tilesiz[BOMB].y<<4);
2915 sprite[i].zvel = -(sprite[i].zvel>>1);
2916 sprptr[i]->hitag++;
2917 }
2918 dax = sprite[i].xvel; day = sprite[i].yvel;
2919 dist = dax*dax+day*day;
2920 if( mulscale(krand_intercept("STAT3057"),dist,30) == 0 ) {
2921 sprite[i].xvel -= ksgn(sprite[i].xvel);
2922 sprite[i].yvel -= ksgn(sprite[i].yvel);
2923 sprite[i].zvel -= ksgn(sprite[i].zvel);
2924 }
2925 if( sprptr[i]->hitag >= 3 ) {
2926 switch( sprptr[i]->picnum ) {
2927 case RATTHROWPIC:
2928 ext=sprptr[i]->extra;
2929 if( !validext(ext) ) {
2930 jsdeletesprite(i);
2931 break;
2932 }
2933 sprptr[i]->z=sectptr[sprptr[i]->sectnum]->floorz;
2934 sprptr[i]->ang=arbitraryangle();
2935 sprptr[i]->picnum=RATPIC;
2936 sprXTptr[ext]->basestat=RODENT;
2937 newstatus(i, RODENT);
2938 sprptr[i]->xvel=4;
2939 sprptr[i]->yvel=4;
2940 sprptr[i]->zvel=0;
2941 sprptr[i]->lotag=2004;
2942 sprptr[i]->hitag=0;
2943 break;
2944 case TUBEBOMB:
2945 sprptr[i]->picnum=TUBEBOMB+1;
2946 sprptr[i]->hitag=(krand_intercept("STAT3083")&255);
2947 changespritestat(i, TIMEBOMB);
2948 break;
2949 case DARTBOMB:
2950 sprptr[i]->picnum=DARTBOMB+1;
2951 sprptr[i]->hitag=(krand_intercept("STAT3088")&255);
2952 changespritestat(i, TIMEBOMB);
2953 break;
2954 default:
2955 sprptr[i]->xvel=0;
2956 sprptr[i]->yvel=0;
2957 sprptr[i]->zvel=0;
2958 sprptr[i]->lotag=2004;
2959 if( globloz != sectptr[sprptr[i]->sectnum]->floorz ) {
2960 sprptr[i]->z=globloz;
2961 changespritestat(i, STACKED);
2962 }
2963 else {
2964 changespritestat(i, INANIMATE);
2965 }
2966 break;
2967 }
2968 }
2969
2970 tosscontinue:
2971 #ifdef VERIFYSTATS
2972 verifystatus(nexti,TOSS);
2973 #endif
2974 i = nexti;
2975 }
2976
2977 if( (activemenu != 0) && (option[4] ==0) ) {
2978 goto menuison;
2979 }
2980
2981 i = headspritestat[AMBUSH];
2982 while (i >= 0)
2983 {
2984 nexti = nextspritestat[i];
2985
2986 ext=sprptr[i]->extra;
2987 if( !validext(ext) ) {
2988 noextcrash(i,1);
2989 }
2990
2991 mindist = 0x7fffffff; target = connecthead;
2992 for(p=connecthead;p>=0;p=connectpoint2[p])
2993 {
2994 dist = labs(sprite[i].x-posx[p])+labs(sprite[i].y-posy[p]);
2995 if (dist < mindist) mindist = dist, target = p;
2996 }
2997 if( mindist > DONTBOTHERDISTANCE ) {
2998 goto ambushcontinue;
2999 }
3000
3001 dist=mindist;
3002 sprXTptr[ext]->target=target;
3003
3004 if( (sprXTptr[i]->aimask&AI_JUSTSHOTAT) || isvisible(i, target) ) {
3005 if( sprXTptr[ext]->morphpic != 0 ) {
3006 newstatus(i, MORPH);
3007 }
3008 else {
3009 ambushyell(i, sprptr[i]->extra);
3010 newstatus(i, sprXTptr[ext]->basestat);
3011 }
3012 }
3013
3014 ambushcontinue:
3015 sprXTptr[ext]->aimask&=~AI_JUSTSHOTAT;
3016 sprXTptr[ext]->aimask&=~AI_WASDRAWN;
3017 #ifdef VERIFYSTATS
3018 verifystatus(nexti,AMBUSH);
3019 #endif
3020 i = nexti;
3021 }
3022
3023 i = headspritestat[STALK];
3024 while (i >= 0)
3025 {
3026 nexti = nextspritestat[i];
3027
3028 ext=sprptr[i]->extra;
3029 if( !validext(ext) ) {
3030 noextcrash(i,2);
3031 }
3032
3033 mindist = 0x7fffffff; target = connecthead;
3034 for(p=connecthead;p>=0;p=connectpoint2[p])
3035 {
3036 dist = labs(sprite[i].x-posx[p])+labs(sprite[i].y-posy[p]);
3037 if (dist < mindist) mindist = dist, target = p;
3038 }
3039 if( mindist > DONTBOTHERDISTANCE ) {
3040 goto stalkcontinue;
3041 }
3042 dist=mindist;
3043 sprXTptr[ext]->target=target;
3044
3045 targx=posx[target];
3046 targy=posy[target];
3047 targz=posz[target];
3048 targang=ang[target];
3049 targsect=cursectnum[target];
3050
3051 prevx=sprptr[i]->x;
3052 prevy=sprptr[i]->y;
3053 prevz=sprptr[i]->z;
3054 prevsect=sprptr[i]->sectnum;
3055
3056 daang=(getangle(targx-sprptr[i]->x,targy-sprptr[i]->y)&2047);
3057
3058 // USES SPRITESORTLIST - NOT MULTIPLAYER COMPATIBLE !
3059
3060 if( ((sprXTptr[ext]->aimask)&AI_WASDRAWN) != 0 ) {
3061 if( ((sprptr[i]->ang+2048-daang)&2047) < 1024 ) {
3062 sprptr[i]->ang=((sprptr[i]->ang+2048-(TICSPERFRAME<<1))&2047);
3063 }
3064 else {
3065 sprptr[i]->ang=((sprptr[i]->ang+(TICSPERFRAME<<1))&2047);
3066 }
3067 if( RMOD16("STAT3291") == 0 )
3068 attackifclose(i, target, dist);
3069 if( sprptr[i]->statnum != ATTACK ) {
3070 daang=((daang+1024)&2047);
3071 dax=( ((sintable[(sprptr[i]->ang+512)&2047])*sprptr[i]->xvel) <<3 );
3072 day=( ((sintable[sprptr[i]->ang])*sprptr[i]->yvel) <<3 );
3073 movestat=movesprite(( short)i,dax,day,0L,1024L,1024L,CLIFFCLIP);
3074 switch( movestat&0xC000 ) {
3075 case 32768: // blocked by a wall
3076 sprptr[i]->ang=walldeflect(movestat&0x0FFF,sprptr[i]->ang);
3077 break;
3078 case 49152: // blocked by a sprite
3079 sprptr[i]->ang=spritedeflect(movestat&0x0FFF,sprptr[i]->ang);
3080 break;
3081 case 16384:
3082 sprptr[i]->ang=arbitraryangle();
3083 break;
3084 }
3085 if( movestat != 0 ) {
3086 dax=( ((sintable[(sprptr[i]->ang+512)&2047])*sprptr[i]->xvel) <<3 );
3087 day=( ((sintable[sprptr[i]->ang])*sprptr[i]->yvel) <<3 );
3088 movestat=movesprite(( short)i,dax,day,0L,1024L,1024L,CLIFFCLIP);
3089 if( movestat != 0 )
3090 sprptr[i]->ang=arbitraryangle();
3091 }
3092 }
3093 }
3094 else {
3095 if( ((sprptr[i]->ang+2048-daang)&2047) < 1024 ) {
3096 sprptr[i]->ang=((sprptr[i]->ang+2048-(TICSPERFRAME<<1))&2047);
3097 }
3098 else {
3099 sprptr[i]->ang=((sprptr[i]->ang+(TICSPERFRAME<<1))&2047);
3100 }
3101 dax=( ((sintable[(sprptr[i]->ang+512)&2047])*sprptr[i]->xvel) <<4 );
3102 day=( ((sintable[sprptr[i]->ang])*sprptr[i]->yvel) <<4 );
3103 movestat=movesprite(( short)i,dax,day,0L,1024L,1024L,CLIFFCLIP);
3104 switch( movestat&0xC000 ) {
3105 case 32768: // blocked by a wall
3106 newstatus(i, SQUAT);
3107 sprptr[i]->ang=walldeflect(movestat&0x0FFF,sprptr[i]->ang);
3108 break;
3109 case 49152: // blocked by a sprite
3110 newstatus(i, SQUAT);
3111 sprptr[i]->ang=spritedeflect(movestat&0x0FFF,sprptr[i]->ang);
3112 break;
3113 case 16384:
3114 sprptr[i]->ang=arbitraryangle();
3115 break;
3116 }
3117 if( movestat != 0 ) {
3118 dax=( ((sintable[(sprptr[i]->ang+512)&2047])*sprptr[i]->xvel) <<3 );
3119 day=( ((sintable[sprptr[i]->ang])*sprptr[i]->yvel) <<3 );
3120 movestat=movesprite(( short)i,dax,day,0L,1024L,1024L,CLIFFCLIP);
3121 if( movestat != 0 )
3122 sprptr[i]->ang=arbitraryangle();
3123 }
3124 }
3125
3126 if( sprptr[i]->sectnum != prevsect ) {
3127 if( sectptr[sprptr[i]->sectnum]->lotag == SECT_LOTAG_OFFLIMITS_ALL ) {
3128 pos.x = prevx; pos.y = prevy; pos.z = prevz;
3129 setsprite(i,&pos);
3130 sprptr[i]->ang=arbitraryangle();
3131 }
3132 else {
3133 enemynewsector(i);
3134 }
3135 }
3136
3137 stalkcontinue:
3138 sprXTptr[ext]->aimask&=~AI_JUSTSHOTAT;
3139 sprXTptr[ext]->aimask&=~AI_WASDRAWN;
3140 #ifdef VERIFYSTATS
3141 verifystatus(nexti,STALK);
3142 #endif
3143 i = nexti;
3144 }
3145
3146 i = headspritestat[CHASE];
3147 while (i >= 0)
3148 {
3149 nexti = nextspritestat[i];
3150
3151 ext=sprptr[i]->extra;
3152 if( !validext(ext) ) {
3153 noextcrash(i,3);
3154 }
3155
3156 mindist = 0x7fffffff; target = connecthead;
3157 for(p=connecthead;p>=0;p=connectpoint2[p])
3158 {
3159 dist = labs(sprite[i].x-posx[p])+labs(sprite[i].y-posy[p]);
3160 if (dist < mindist) mindist = dist, target = p;
3161 }
3162 if( mindist > DONTBOTHERDISTANCE ) {
3163 goto chasecontinue;
3164 }
3165 dist=mindist;
3166 sprXTptr[ext]->target=target;
3167
3168 targx=posx[target];
3169 targy=posy[target];
3170 targz=posz[target];
3171 targang=ang[target];
3172 targsect=cursectnum[target];
3173
3174 prevx=sprptr[i]->x;
3175 prevy=sprptr[i]->y;
3176 prevz=sprptr[i]->z;
3177 prevsect=sprptr[i]->sectnum;
3178
3179 daang=(getangle(targx-sprptr[i]->x,targy-sprptr[i]->y)&2047);
3180
3181 if( (option[4] == 0) && (sprXTptr[ext]->aimask)&AI_CRITICAL ) {
3182 if( ((sprXTptr[ext]->fxmask)&(FX_ANDROID|FX_HOLOGRAM)) == 0 ) {
3183 sprptr[i]->ang=((daang+1024)&2047);
3184 newstatus(i, FLEE);
3185 if( sprptr[i]->statnum == FLEE )
3186 goto chasecontinue;
3187 }
3188 }
3189
3190 // can player see target if they squat ?
3191 seecan=0;
3192 if( cansee(targx,targy,targz,targsect,
3193 sprptr[i]->x,sprptr[i]->y,sprptr[i]->z-(tilesiz[sprptr[i]->picnum].y<<6),sprptr[i]->sectnum) == 1) {
3194 seecan=1;
3195 }
3196
3197 if( seecan == 1 ) {
3198 if( ((sprptr[i]->ang+2048-daang)&2047) < 1024 ) {
3199 sprptr[i]->ang=((sprptr[i]->ang+2048-(TICSPERFRAME<<1))&2047);
3200 }
3201 else {
3202 sprptr[i]->ang=((sprptr[i]->ang+(TICSPERFRAME<<1))&2047);
3203 }
3204 if( RMOD4("STAT3427") == 0 ) {
3205 attackifclose(i, target, dist);
3206 }
3207 if( sprptr[i]->statnum != ATTACK ) {
3208 dax=( ((sintable[(sprptr[i]->ang+512)&2047])*sprptr[i]->xvel) <<3 );
3209 day=( ((sintable[sprptr[i]->ang])*sprptr[i]->yvel) <<3 );
3210 movestat=movesprite(( short)i,dax,day,0L,1024,1024,CLIFFCLIP);
3211 switch( movestat&0xC000 ) {
3212 case 32768: // blocked by a wall
3213 sprptr[i]->ang=walldeflect(movestat&0x0FFF,sprptr[i]->ang);
3214 break;
3215 case 49152: // blocked by a sprite
3216 sprptr[i]->ang=spritedeflect(movestat&0x0FFF,sprptr[i]->ang);
3217 break;
3218 case 16384:
3219 sprptr[i]->ang=arbitraryangle();
3220 break;
3221 }
3222 if( movestat != 0 ) {
3223 dax=( ((sintable[(sprptr[i]->ang+512)&2047])*sprptr[i]->xvel) <<3 );
3224 day=( ((sintable[sprptr[i]->ang])*sprptr[i]->yvel) <<3 );
3225 movestat=movesprite(( short)i,dax,day,0L,1024,1024,CLIFFCLIP);
3226 if( movestat != 0 )
3227 sprptr[i]->ang=arbitraryangle();
3228 }
3229 }
3230 }
3231 else {
3232 if( ((sprptr[i]->ang+2048-daang)&2047) < 1024 ) {
3233 sprptr[i]->ang=((sprptr[i]->ang+2048-(TICSPERFRAME<<1))&2047);
3234 }
3235 else {
3236 sprptr[i]->ang=((sprptr[i]->ang+(TICSPERFRAME<<1))&2047);
3237 }
3238 dax=( ((sintable[(sprptr[i]->ang+512)&2047])*sprptr[i]->xvel) <<3 );
3239 day=( ((sintable[sprptr[i]->ang])*sprptr[i]->yvel) <<3 );
3240 movestat=movesprite(( short)i,dax,day,0L,1024,1024,CLIFFCLIP);
3241 switch( movestat&0xC000 ) {
3242 case 32768: // blocked by a wall
3243 newstatus(i, SQUAT);
3244 sprptr[i]->ang=walldeflect(movestat&0x0FFF,sprptr[i]->ang);
3245 break;
3246 case 49152: // blocked by a sprite
3247 newstatus(i, SQUAT);
3248 sprptr[i]->ang=spritedeflect(movestat&0x0FFF,sprptr[i]->ang);
3249 break;
3250 case 16384:
3251 sprptr[i]->ang=arbitraryangle();
3252 break;
3253 }
3254 if( movestat != 0 ) {
3255 dax=( ((sintable[(sprptr[i]->ang+512)&2047])*sprptr[i]->xvel) <<3 );
3256 day=( ((sintable[sprptr[i]->ang])*sprptr[i]->yvel) <<3 );
3257 movestat=movesprite(( short)i,dax,day,0L,1024,1024,CLIFFCLIP);
3258 if( movestat != 0 )
3259 sprptr[i]->ang=arbitraryangle();
3260 }
3261 }
3262 if( sprptr[i]->sectnum != prevsect ) {
3263 if( sectptr[sprptr[i]->sectnum]->lotag == SECT_LOTAG_OFFLIMITS_ALL ) {
3264 pos.x = prevx; pos.y = prevy; pos.z = prevz;
3265 setsprite(i,&pos);
3266 sprptr[i]->ang=arbitraryangle();
3267 }
3268 else {
3269 enemynewsector(i);
3270 }
3271 }
3272
3273 chasecontinue:
3274 sprXTptr[ext]->aimask&=~AI_JUSTSHOTAT;
3275 sprXTptr[ext]->aimask&=~AI_WASDRAWN;
3276 #ifdef VERIFYSTATS
3277 verifystatus(nexti,CHASE);
3278 #endif
3279 i = nexti;
3280 }
3281
3282 i=headspritestat[GUARD];
3283 while (i >= 0)
3284 {
3285 nexti=nextspritestat[i];
3286
3287 ext=sprptr[i]->extra;
3288 if( !validext(ext) ) {
3289 noextcrash(i,4);
3290 }
3291
3292 mindist = 0x7fffffff; target = connecthead;
3293 for(p=connecthead;p>=0;p=connectpoint2[p])
3294 {
3295 dist = labs(sprite[i].x-posx[p])+labs(sprite[i].y-posy[p]);
3296 if (dist < mindist) mindist = dist, target = p;
3297 }
3298 if( mindist > DONTBOTHERDISTANCE ) {
3299 goto guardcontinue;
3300 }
3301 dist=mindist;
3302 sprXTptr[ext]->target=target;
3303
3304 targx=posx[target];
3305 targy=posy[target];
3306 targz=posz[target];
3307 targang=ang[target];
3308 targsect=cursectnum[target];
3309
3310 prevx=sprptr[i]->x;
3311 prevy=sprptr[i]->y;
3312 prevz=sprptr[i]->z;
3313 prevsect=sprptr[i]->sectnum;
3314
3315 if( ((sprXTptr[ext]->aimask)&AI_JUSTSHOTAT) ) {
3316 if( cansee(targx,targy,targz,targsect, sprptr[i]->x,sprptr[i]->y,
3317 sprptr[i]->z-(tilesiz[sprptr[i]->picnum].y<<7),sprptr[i]->sectnum) == 1 ) {
3318 sprptr[i]->ang=getangle(targx-sprptr[i]->x,targy-sprptr[i]->y);
3319 sprXTptr[ext]->aimask|=AI_WASATTACKED; // guard needs to take action
3320 }
3321 goto guardcontinue;
3322 }
3323
3324 if( (drawweap[target]) && isvisible(i, target) && !((sprXTptr[ext]->aimask)&(AI_WASATTACKED|AI_ENCROACHMENT)) ) {
3325 givewarning(i, ext);
3326 sprptr[i]->ang=getangle(targx-sprptr[i]->x,targy-sprptr[i]->y);
3327 sprptr[i]->picnum=sprXTptr[ext]->attackpic+1;
3328 if( dist < 1024 )
3329 newstatus(i, ATTACK);
3330 goto guardcontinue;
3331 }
3332 else {
3333 sprptr[i]->picnum=sprXTptr[ext]->basepic;
3334 }
3335
3336 switch( (sprXTptr[ext]->aimask)&(AI_WASATTACKED|AI_ENCROACHMENT) ) {
3337 case 0:
3338 sprXTptr[ext]->aimask&=~AI_GAVEWARNING;
3339 if( RMOD16("STAT3561") == 0 ) {
3340 sprptr[i]->ang=getangle(targx-sprptr[i]->x,targy-sprptr[i]->y);
3341 newstatus(i, STANDING);
3342 }
3343 else {
3344 dax=( ((sintable[(sprptr[i]->ang+512)&2047])*sprptr[i]->xvel) <<3 );
3345 day=( ((sintable[sprptr[i]->ang])*sprptr[i]->yvel) <<3 );
3346 movestat=movesprite(( short)i,dax,day,0L,1024,1024,CLIFFCLIP);
3347 if( movestat != 0 ) {
3348 sprptr[i]->ang=arbitraryangle();
3349 }
3350 }
3351 break;
3352 default:
3353 if( (RMOD4("STAT3575") == 0) && (cansee(targx,targy,targz,targsect, sprptr[i]->x,sprptr[i]->y,
3354 sprptr[i]->z-(tilesiz[sprptr[i]->picnum].y<<7),sprptr[i]->sectnum) == 1) ) {
3355 sprptr[i]->ang=getangle(targx-sprptr[i]->x,targy-sprptr[i]->y);
3356 newstatus(i, ATTACK);
3357 }
3358 else {
3359 dax=( ((sintable[(sprptr[i]->ang+512)&2047])*(sprptr[i]->xvel+2)) <<3 );
3360 day=( ((sintable[sprptr[i]->ang])*(sprptr[i]->yvel+2)) <<3 );
3361 movestat=movesprite(( short)i,dax,day,0L,1024,1024,CLIFFCLIP);
3362 if( movestat != 0 ) {
3363 sprptr[i]->ang=arbitraryangle();
3364 }
3365 }
3366 break;
3367 }
3368
3369 if( (prevsect != sprptr[i]->sectnum) ) {
3370 pos.x = prevx; pos.y = prevy; pos.z = prevz;
3371 setsprite(i,&pos);
3372 sprptr[i]->ang=arbitraryangle();
3373 }
3374
3375 guardcontinue:
3376 sprXTptr[ext]->aimask&=~AI_JUSTSHOTAT;
3377 sprXTptr[ext]->aimask&=~AI_WASDRAWN;
3378 #ifdef VERIFYSTATS
3379 verifystatus(nexti,GUARD);
3380 #endif
3381 i = nexti;
3382 }
3383
3384 i = headspritestat[FLEE];
3385 while (i >= 0)
3386 {
3387 nexti = nextspritestat[i];
3388
3389 ext=sprptr[i]->extra;
3390 if( !validext(ext) ) {
3391 noextcrash(i,5);
3392 }
3393
3394 mindist = 0x7fffffff; target = connecthead;
3395 for(p=connecthead;p>=0;p=connectpoint2[p])
3396 {
3397 dist = labs(sprite[i].x-posx[p])+labs(sprite[i].y-posy[p]);
3398 if (dist < mindist) mindist = dist, target = p;
3399 }
3400 if( (drawweap[target] == 0) || (mindist > DONTBOTHERDISTANCE) ) {
3401 newstatus(i, sprXTptr[ext]->basestat);
3402 goto fleecontinue;
3403 }
3404
3405 dist=mindist;
3406 sprXTptr[ext]->target=target;
3407
3408 targx=posx[target];
3409 targy=posy[target];
3410 targz=posz[target];
3411 targang=ang[target];
3412 targsect=cursectnum[target];
3413
3414 prevx=sprptr[i]->x;
3415 prevy=sprptr[i]->y;
3416 prevz=sprptr[i]->z;
3417 prevsect=sprptr[i]->sectnum;
3418
3419 #define FLEESPEED 5
3420 dax=( ((sintable[(sprptr[i]->ang+512)&2047])*FLEESPEED) <<3 );
3421 day=( ((sintable[sprptr[i]->ang])*FLEESPEED) <<3 );
3422 movestat=movesprite(( short)i,dax,day,0L,1024,1024,CLIFFCLIP);
3423
3424 if( movestat != 0 ) {
3425 switch( movestat&0xC000 ) {
3426 case 32768: // blocked by a wall
3427 sprptr[i]->ang=walldeflect(movestat&0x0FFF,sprptr[i]->ang);
3428 break;
3429 case 49152: // blocked by a sprite
3430 sprptr[i]->ang=spritedeflect(movestat&0x0FFF,sprptr[i]->ang);
3431 break;
3432 case 16384:
3433 sprptr[i]->ang=arbitraryangle();
3434 break;
3435 }
3436 if( cansee(targx,targy,targz,targsect,sprptr[i]->x,sprptr[i]->y,sprptr[i]->z-(tilesiz[sprptr[i]->picnum].y<<7),sprptr[i]->sectnum) == 1 ) {
3437 attackifclose(i, target, dist);
3438 if( sprptr[i]->statnum != ATTACK ) {
3439 daang=getangle(targx-sprptr[i]->x,targy-sprptr[i]->y);
3440 sprptr[i]->ang=((daang+1024)&2047);
3441 movestat=movesprite(( short)i,dax,day,0L,1024,1024,CLIFFCLIP);
3442 if( (movestat != 0) && RMOD2("STAT3663") )
3443 newstatus(i, HIDE);
3444 }
3445 }
3446 else {
3447 if( RMOD3("STAT3668") == 0 )
3448 newstatus(i, HIDE);
3449 }
3450 }
3451
3452 if( sprptr[i]->sectnum != prevsect ) {
3453 if( sectptr[sprptr[i]->sectnum]->lotag == SECT_LOTAG_OFFLIMITS_ALL ) {
3454 pos.x = prevx; pos.y = prevy; pos.z = prevz;
3455 setsprite(i,&pos);
3456 sprptr[i]->ang=arbitraryangle();
3457 }
3458 else {
3459 enemynewsector(i);
3460 }
3461 }
3462
3463 fleecontinue:
3464 sprXTptr[ext]->aimask&=~AI_JUSTSHOTAT;
3465 sprXTptr[ext]->aimask&=~AI_WASDRAWN;
3466 #ifdef VERIFYSTATS
3467 verifystatus(nexti,FLEE);
3468 #endif
3469 i = nexti;
3470 }
3471
3472 i=headspritestat[STROLL];
3473 while( i >= 0 )
3474 {
3475 nexti=nextspritestat[i];
3476
3477 ext=sprptr[i]->extra;
3478 if( !validext(ext) ) {
3479 noextcrash(i,6);
3480 }
3481
3482 mindist = 0x7fffffff; target = connecthead;
3483 for(p=connecthead;p>=0;p=connectpoint2[p])
3484 {
3485 dist = labs(sprite[i].x-posx[p])+labs(sprite[i].y-posy[p]);
3486 if (dist < mindist) mindist = dist, target = p;
3487 }
3488 if( mindist > DONTBOTHERDISTANCE ) {
3489 goto strollcontinue;
3490 }
3491 dist=mindist;
3492 sprXTptr[ext]->target=target;
3493
3494 targx=posx[target];
3495 targy=posy[target];
3496 targz=posz[target];
3497 targang=ang[target];
3498 targsect=cursectnum[target];
3499
3500 prevx=sprptr[i]->x;
3501 prevy=sprptr[i]->y;
3502 prevz=sprptr[i]->z;
3503 prevsect=sprptr[i]->sectnum;
3504
3505 if( ((sprXTptr[ext]->aimask)&AI_JUSTSHOTAT) != 0 ) {
3506 attackifclose(i, target, dist);
3507 if( sprptr[i]->statnum != ATTACK ) {
3508 daang=(getangle(posx[target]-sprptr[i]->x,posy[target]-sprptr[i]->y)&2047);
3509 sprptr[i]->ang=((daang+1024)&2047);
3510 fleescream(i, ext);
3511 newstatus(i, FLEE);
3512 }
3513 goto strollcontinue;
3514 }
3515
3516 if( (drawweap[target]) && isvisible(i, target) ) {
3517 daang=(getangle(posx[target]-sprptr[i]->x,posy[target]-sprptr[i]->y)&2047);
3518 sprptr[i]->ang=((daang+1024)&2047);
3519 #define HIDEDISTANCE 4096
3520 if( dist < HIDEDISTANCE ) {
3521 newstatus(i, HIDE);
3522 }
3523 if( sprptr[i]->statnum == HIDE ) {
3524 hideplea(i, ext);
3525 }
3526 else {
3527 fleescream(i, ext);
3528 newstatus(i, FLEE);
3529 }
3530 goto strollcontinue;
3531 }
3532
3533 dax=( ((sintable[(sprptr[i]->ang+512)&2047])*sprptr[i]->xvel) <<3 );
3534 day=( ((sintable[sprptr[i]->ang])*sprptr[i]->yvel) <<3 );
3535 movestat=movesprite(( short)i,dax,day,0L,1024,1024,CLIFFCLIP);
3536 if( movestat != 0 ) {
3537 if( (RMOD10("STAT3757") == 0) && (sectptr[sprptr[i]->sectnum]->lotag != SECT_LOTAG_NOSTANDING) ) {
3538 sprptr[i]->ang=((sprptr[i]->ang+1024)&2047);
3539 newstatus(i, STANDING);
3540 }
3541 else {
3542 switch( movestat&0xC000 ) {
3543 case 32768: // blocked by a wall
3544 sprptr[i]->ang=walldeflect(movestat&0x0FFF,sprptr[i]->ang);
3545 break;
3546 case 49152: // blocked by a sprite
3547 sprptr[i]->ang=spritedeflect(movestat&0x0FFF,sprptr[i]->ang);
3548 break;
3549 case 16384:
3550 sprptr[i]->ang=arbitraryangle();
3551 break;
3552 }
3553 }
3554 }
3555
3556 if( sprptr[i]->sectnum != prevsect ) {
3557 if( (sectptr[sprptr[i]->sectnum]->lotag == SECT_LOTAG_OFFLIMITS_CIVILLIAN) ||
3558 (sectptr[sprptr[i]->sectnum]->lotag == SECT_LOTAG_OFFLIMITS_ALL) ) {
3559 pos.x = prevx; pos.y = prevy; pos.z = prevz;
3560 setsprite(i,&pos);
3561 sprptr[i]->ang=arbitraryangle();
3562 }
3563 else {
3564 enemynewsector(i);
3565 }
3566 }
3567
3568 strollcontinue:
3569 sprXTptr[ext]->aimask&=~AI_JUSTSHOTAT;
3570 sprXTptr[ext]->aimask&=~AI_WASDRAWN;
3571 #ifdef VERIFYSTATS
3572 verifystatus(nexti,STROLL);
3573 #endif
3574 i = nexti;
3575 }
3576
3577 i = headspritestat[FLY];
3578 while( i >= 0 )
3579 {
3580 nexti = nextspritestat[i];
3581
3582 ext=sprptr[i]->extra;
3583 if( !validext(ext) ) {
3584 noextcrash(i,7);
3585 }
3586
3587 mindist = 0x7fffffff; target = connecthead;
3588 for(p=connecthead;p>=0;p=connectpoint2[p])
3589 {
3590 dist = labs(sprite[i].x-posx[p])+labs(sprite[i].y-posy[p]);
3591 if (dist < mindist) mindist = dist, target = p;
3592 }
3593 if( mindist > DONTBOTHERDISTANCE ) {
3594 goto flycontinue;
3595 }
3596 dist=mindist;
3597 sprXTptr[ext]->target=target;
3598
3599 if( sprXTptr[ext]->basepic != AUTOGUN ) {
3600 dax=( ((sintable[(sprptr[i]->ang+512)&2047])*((sprptr[i]->xvel)<<1)) <<3 );
3601 day=( ((sintable[sprptr[i]->ang])*((sprptr[i]->yvel)<<1)) <<3 );
3602 daz=0L;
3603 movestat = flymovesprite(i,dax,day,daz,1024,1024,NORMALCLIP);
3604 if( movestat != 0 ) {
3605 sprptr[i]->ang=arbitraryangle();
3606 }
3607 }
3608 if( cansee(posx[target],posy[target],posz[target],cursectnum[target],
3609 sprptr[i]->x,sprptr[i]->y,sprptr[i]->z-(tilesiz[sprptr[i]->picnum].y<<7),sprptr[i]->sectnum) ) {
3610 if( sprXTptr[ext]->weapon == 0 ) {
3611 if( dist < 5120 ) {
3612 sprptr[i]->ang=getangle(posx[target]-sprptr[i]->x,posy[target]-sprptr[i]->y);
3613 }
3614 if( dist < 1024 ) {
3615 sprptr[i]->ang=getangle(posx[target]-sprptr[i]->x,posy[target]-sprptr[i]->y);
3616 if( RMOD4("STAT3835") == 0 ) {
3617 newstatus(i, ATTACK);
3618 }
3619 }
3620 }
3621 else {
3622 attackifclose(i, target, dist);
3623 }
3624 }
3625
3626 flycontinue:
3627 sprXTptr[ext]->aimask&=~AI_JUSTSHOTAT;
3628 sprXTptr[ext]->aimask&=~AI_WASDRAWN;
3629 #ifdef VERIFYSTATS
3630 verifystatus(nexti,FLY);
3631 #endif
3632 i = nexti;
3633 }
3634
3635 i = headspritestat[RODENT];
3636 while (i >= 0)
3637 {
3638 nexti = nextspritestat[i];
3639
3640 ext=sprptr[i]->extra;
3641 if( !validext(ext) ) {
3642 noextcrash(i,3);
3643 }
3644
3645 mindist = 0x7fffffff; target = connecthead;
3646 for(p=connecthead;p>=0;p=connectpoint2[p])
3647 {
3648 dist = labs(sprite[i].x-posx[p])+labs(sprite[i].y-posy[p]);
3649 if (dist < mindist) mindist = dist, target = p;
3650 }
3651 if( mindist > DONTBOTHERDISTANCE ) {
3652 goto rodentcontinue;
3653 }
3654 dist=mindist;
3655 sprXTptr[ext]->target=target;
3656
3657 targx=posx[target];
3658 targy=posy[target];
3659 targz=posz[target];
3660 targang=ang[target];
3661 targsect=cursectnum[target];
3662
3663 prevx=sprptr[i]->x;
3664 prevy=sprptr[i]->y;
3665 prevz=sprptr[i]->z;
3666 prevsect=sprptr[i]->sectnum;
3667
3668 if( ((sprptr[i]->ang+2048-daang)&2047) < 1024 ) {
3669 sprptr[i]->ang=((sprptr[i]->ang+2048-(TICSPERFRAME<<1))&2047);
3670 }
3671 else {
3672 sprptr[i]->ang=((sprptr[i]->ang+(TICSPERFRAME<<1))&2047);
3673 }
3674 dax=( ((sintable[(sprptr[i]->ang+512)&2047])*sprptr[i]->xvel) <<3 );
3675 day=( ((sintable[sprptr[i]->ang])*sprptr[i]->yvel) <<3 );
3676
3677 movestat=movesprite(( short)i,dax,day,0L,1024L,1024L,2);
3678
3679 switch( movestat&0xC000 ) {
3680 case 32768: // blocked by a wall
3681 sprptr[i]->ang=walldeflect(movestat&0x0FFF,sprptr[i]->ang);
3682 break;
3683 case 49152: // blocked by a sprite
3684 sprptr[i]->ang=spritedeflect(movestat&0x0FFF,sprptr[i]->ang);
3685 break;
3686 case 16384:
3687 sprptr[i]->ang=arbitraryangle();
3688 break;
3689 }
3690
3691 rodentcontinue:
3692 sprXTptr[ext]->aimask&=~AI_JUSTSHOTAT;
3693 sprXTptr[ext]->aimask&=~AI_WASDRAWN;
3694 #ifdef VERIFYSTATS
3695 verifystatus(nexti,RODENT);
3696 #endif
3697 i = nexti;
3698 }
3699
3700 i=headspritestat[STANDING];
3701 while( i >= 0 )
3702 {
3703 nexti = nextspritestat[i];
3704
3705 ext=sprptr[i]->extra;
3706 if( !validext(ext) ) {
3707 noextcrash(i,8);
3708 }
3709
3710 mindist = 0x7fffffff; target = connecthead;
3711 for(p=connecthead;p>=0;p=connectpoint2[p])
3712 {
3713 dist = labs(sprite[i].x-posx[p])+labs(sprite[i].y-posy[p]);
3714 if (dist < mindist) mindist = dist, target = p;
3715 }
3716 if( sectptr[sprptr[i]->sectnum]->lotag == SECT_LOTAG_NOSTANDING ) {
3717 sprptr[i]->lotag=0;
3718 sprptr[i]->hitag=0;
3719 sprptr[i]->picnum=sprXTptr[ext]->basepic;
3720 newstatus(i, sprXTptr[ext]->basestat);
3721 }
3722
3723 if( ((sprXTptr[ext]->aimask)&AI_JUSTSHOTAT) != 0 ) {
3724 sprptr[i]->lotag=0;
3725 }
3726 if( ((sprXTptr[ext]->aimask)&AI_ENCROACHMENT) != 0 ) {
3727 sprptr[i]->lotag=0;
3728 }
3729 if( (drawweap[target]) ) {
3730 if( isvisible(i, target) )
3731 sprptr[i]->lotag=0;
3732 }
3733
3734 sprptr[i]->lotag -= ((int)TICSPERFRAME);
3735 if (sprptr[i]->lotag < 0) {
3736 sprptr[i]->lotag=0;
3737 newstatus(i, sprXTptr[ext]->basestat);
3738 }
3739
3740 sprXTptr[ext]->aimask&=~AI_JUSTSHOTAT;
3741 sprXTptr[ext]->aimask&=~AI_WASDRAWN;
3742 #ifdef VERIFYSTATS
3743 verifystatus(nexti,STANDING);
3744 #endif
3745 i = nexti;
3746 }
3747
3748 i=headspritestat[ATTACK];
3749 while (i >= 0)
3750 {
3751 nexti = nextspritestat[i];
3752
3753 ext=sprptr[i]->extra;
3754 if( !validext(ext) ) {
3755 noextcrash(i,9);
3756 }
3757
3758 if( sprptr[i]->lotag == sprptr[i]->hitag ) { // fire instance
3759 enemyshootgun(i, sprptr[i]->x,sprptr[i]->y,sprptr[i]->z,
3760 sprptr[i]->ang, 100, sprptr[i]->sectnum,
3761 sprXTptr[ext]->weapon);
3762 }
3763
3764 sprptr[i]->lotag -= ((int)TICSPERFRAME);
3765
3766 if (sprptr[i]->lotag < 0) {
3767 sprptr[i]->lotag=0;
3768 if( ((sprXTptr[ext]->aimask)&AI_TIMETODODGE) ){
3769 sprXTptr[ext]->aimask&=~AI_TIMETODODGE;
3770 newstatus(i, DODGE);
3771 }
3772 else {
3773 newstatus(i, sprXTptr[ext]->basestat);
3774 }
3775 }
3776
3777 sprXTptr[ext]->aimask&=~AI_JUSTSHOTAT;
3778 sprXTptr[ext]->aimask&=~AI_WASDRAWN;
3779 #ifdef VERIFYSTATS
3780 verifystatus(nexti,ATTACK);
3781 #endif
3782 i = nexti;
3783 }
3784
3785 i=headspritestat[DELAYEDATTACK];
3786 while (i >= 0)
3787 {
3788 nexti = nextspritestat[i];
3789
3790 ext=sprptr[i]->extra;
3791 if( !validext(ext) ) {
3792 noextcrash(i,10);
3793 }
3794
3795 sprptr[i]->lotag -= ((int)TICSPERFRAME);
3796
3797 if (sprptr[i]->lotag < 0) {
3798 sprptr[i]->lotag=0;
3799 newstatus(i, ATTACK);
3800 }
3801
3802 sprXTptr[ext]->aimask&=~AI_JUSTSHOTAT;
3803 sprXTptr[ext]->aimask&=~AI_WASDRAWN;
3804 #ifdef VERIFYSTATS
3805 verifystatus(nexti,DELAYEDATTACK);
3806 #endif
3807 i = nexti;
3808 }
3809
3810 i=headspritestat[SQUAT];
3811 while (i >= 0)
3812 {
3813 nexti = nextspritestat[i];
3814
3815 ext=sprptr[i]->extra;
3816 if( !validext(ext) ) {
3817 noextcrash(i,11);
3818 }
3819
3820 if( sectptr[sprptr[i]->sectnum]->lotag == SECT_LOTAG_NOSTANDING ) {
3821 sprptr[i]->lotag=0;
3822 sprptr[i]->hitag=0;
3823 sprptr[i]->picnum=sprXTptr[ext]->basepic;
3824 newstatus(i, sprXTptr[ext]->basestat);
3825 }
3826
3827 sprptr[i]->lotag -= ((int)TICSPERFRAME);
3828 if (sprptr[i]->lotag < 0) {
3829 sprptr[i]->hitag -= ((int)TICSPERFRAME);
3830 if( sprptr[i]->hitag < 0 ) {
3831 sprptr[i]->lotag=0;
3832 sprptr[i]->hitag=0;
3833 newstatus(i, UNSQUAT);
3834 }
3835 }
3836 else {
3837 sprptr[i]->picnum = sprXTptr[ext]->squatpic + ((47-sprptr[i]->lotag)>>4);
3838 }
3839
3840 sprXTptr[ext]->aimask&=~AI_JUSTSHOTAT;
3841 sprXTptr[ext]->aimask&=~AI_WASDRAWN;
3842 #ifdef VERIFYSTATS
3843 verifystatus(nexti,SQUAT);
3844 #endif
3845 i = nexti;
3846 }
3847
3848 i=headspritestat[UNSQUAT];
3849 while (i >= 0)
3850 {
3851 nexti = nextspritestat[i];
3852
3853 ext=sprptr[i]->extra;
3854 if( !validext(ext) ) {
3855 noextcrash(i,12);
3856 }
3857
3858 sprptr[i]->lotag -= ((int)TICSPERFRAME);
3859 if (sprptr[i]->lotag < 0) {
3860 sprptr[i]->lotag=0;
3861 sprptr[i]->hitag=0;
3862 sprptr[i]->picnum=sprXTptr[ext]->basepic;
3863 newstatus(i, sprXTptr[ext]->basestat);
3864 }
3865 else {
3866 sprptr[i]->picnum = sprXTptr[ext]->squatpic + (((47)>>4)) - ((47-sprptr[i]->lotag)>>4);
3867 }
3868
3869 sprXTptr[ext]->aimask&=~AI_JUSTSHOTAT;
3870 sprXTptr[ext]->aimask&=~AI_WASDRAWN;
3871 #ifdef VERIFYSTATS
3872 verifystatus(nexti,UNSQUAT);
3873 #endif
3874 i = nexti;
3875 }
3876
3877 i=headspritestat[HIDE];
3878 while (i >= 0)
3879 {
3880 nexti = nextspritestat[i];
3881
3882 ext=sprptr[i]->extra;
3883 if( !validext(ext) ) {
3884 noextcrash(i,13);
3885 }
3886
3887 if( sectptr[sprptr[i]->sectnum]->lotag == SECT_LOTAG_NOSTANDING ) {
3888 sprptr[i]->lotag=0;
3889 sprptr[i]->hitag=0;
3890 sprptr[i]->picnum=sprXTptr[ext]->basepic;
3891 newstatus(i, sprXTptr[ext]->basestat);
3892 }
3893
3894 if( ((sprXTptr[ext]->aimask)&AI_JUSTSHOTAT) != 0 ) {
3895 sprptr[i]->lotag=0;
3896 sprptr[i]->hitag=0;
3897 }
3898
3899 sprptr[i]->lotag -= ((int)TICSPERFRAME);
3900 if (sprptr[i]->lotag < 0) {
3901 sprptr[i]->hitag -= ((int)TICSPERFRAME);
3902 if( sprptr[i]->hitag < 0 ) {
3903 sprptr[i]->lotag=0;
3904 sprptr[i]->hitag=0;
3905 newstatus(i, UNHIDE);
3906 }
3907 }
3908 else {
3909 sprptr[i]->picnum = sprXTptr[ext]->squatpic + ((47-sprptr[i]->lotag)>>4);
3910 }
3911
3912 sprXTptr[ext]->aimask&=~AI_JUSTSHOTAT;
3913 sprXTptr[ext]->aimask&=~AI_WASDRAWN;
3914 #ifdef VERIFYSTATS
3915 verifystatus(nexti,HIDE);
3916 #endif
3917 i = nexti;
3918 }
3919
3920 i=headspritestat[UNHIDE];
3921 while (i >= 0)
3922 {
3923 nexti = nextspritestat[i];
3924
3925 ext=sprptr[i]->extra;
3926 if( !validext(ext) ) {
3927 noextcrash(i,14);
3928 }
3929
3930 sprptr[i]->lotag -= ((int)TICSPERFRAME);
3931 if (sprptr[i]->lotag < 0) {
3932 sprptr[i]->lotag=0;
3933 sprptr[i]->hitag=0;
3934 sprptr[i]->picnum=sprXTptr[ext]->basepic;
3935 newstatus(i, FLEE);
3936 }
3937 else {
3938 sprptr[i]->picnum = sprXTptr[ext]->squatpic + (((47)>>4)) - ((47-sprptr[i]->lotag)>>4);
3939 }
3940
3941 sprXTptr[ext]->aimask&=~AI_JUSTSHOTAT;
3942 sprXTptr[ext]->aimask&=~AI_WASDRAWN;
3943 #ifdef VERIFYSTATS
3944 verifystatus(nexti,UNHIDE);
3945 #endif
3946 i = nexti;
3947 }
3948
3949 i=headspritestat[PAIN];
3950 while( i >= 0 )
3951 {
3952 nexti = nextspritestat[i];
3953
3954 ext=sprptr[i]->extra;
3955 if( !validext(ext) ) {
3956 noextcrash(i,15);
3957 }
3958
3959 sprptr[i]->lotag -= ((int)TICSPERFRAME);
3960 if (sprptr[i]->lotag < 0) {
3961 sprptr[i]->lotag=0;
3962 newstatus(i, sprXTptr[ext]->basestat);
3963 }
3964
3965 #ifdef VERIFYSTATS
3966 verifystatus(nexti,PAIN);
3967 #endif
3968 i = nexti;
3969 }
3970
3971 i=headspritestat[DEATH];
3972 while (i >= 0)
3973 {
3974 nexti = nextspritestat[i];
3975
3976 ext=sprptr[i]->extra;
3977 if( !validext(ext) ) {
3978 noextcrash(i,16);
3979 }
3980
3981 if( isanandroid(i) ) {
3982 androidexplosion(( int)i);
3983 jsdeletesprite(i);
3984 showmessage("WAS AN ANDROID");
3985 goto deathcontinue;
3986 }
3987
3988 targsect=sprptr[i]->sectnum;
3989 if( sectptr[targsect]->lotag != 4 ) {
3990 if( sprptr[i]->z < sectptr[targsect]->floorz ) {
3991 sprptr[i]->z+=1024;
3992 }
3993 else {
3994 sprptr[i]->z=sectptr[targsect]->floorz;
3995 }
3996 }
3997
3998 sprptr[i]->lotag-=((int)TICSPERFRAME<<1);
3999 if (sprptr[i]->lotag < 0) {
4000 sprptr[i]->lotag=0;
4001 tweakdeathdist(i);
4002 sprptr[i]->cstat&=0xFFFE;
4003 if( isahologram(i) ) {
4004 showmessage("WAS A HOLOGRAM");
4005 jsdeletesprite(i);
4006 }
4007 else {
4008 missionaccomplished(i);
4009 newstatus(i, FLOATING);
4010 }
4011 }
4012 else {
4013 sprptr[i]->picnum = sprXTptr[ext]->deathpic + ((sprptr[i]->hitag-sprptr[i]->lotag)>>4);
4014 }
4015
4016 deathcontinue:
4017 #ifdef VERIFYSTATS
4018 verifystatus(nexti,DEATH);
4019 #endif
4020 i = nexti;
4021 }
4022
4023 i=headspritestat[PLRVIRUS];
4024 while( i >= 0 )
4025 {
4026 nexti = nextspritestat[i];
4027
4028 host=sprptr[i]->owner;
4029 if( !validplayer(host) ) {
4030 crash("plrvirus lost host");
4031 }
4032
4033 sprptr[i]->x=posx[host];
4034 sprptr[i]->y=posy[host];
4035 sprptr[i]->z=posz[host]+(8<<8);
4036
4037 sprptr[i]->lotag -= ((int)TICSPERFRAME);
4038 if( (sprptr[i]->lotag > 0) && ((sprptr[i]->lotag&3) == 0) ) {
4039 if( changehealth(host, -64) != 0 ) {
4040 sprptr[i]->lotag=0;
4041 }
4042 #ifdef NETDEBUG
4043 fprintf(dbgfp2, "%ld %ld %d %d\n", lockclock,randomseed,host,health[host]);
4044 #endif
4045 }
4046 if( sprptr[i]->lotag <= 0 ) {
4047 changehealth(host, -8192);
4048 if( host == screenpeek ) {
4049 showmessage("BURNED");
4050 }
4051 jsdeletesprite(i);
4052 }
4053
4054 #ifdef VERIFYSTATS
4055 verifystatus(nexti,PLRVIRUS);
4056 #endif
4057 i = nexti;
4058 }
4059
4060 i=headspritestat[VIRUS];
4061 while( i >= 0 )
4062 {
4063 nexti = nextspritestat[i];
4064
4065 host=sprptr[i]->owner;
4066 if( (host < 0) || (host >=MAXSPRITES) || (sprptr[host]->statnum >= MAXSTATUS) ) {
4067 jsdeletesprite(i);
4068 i=nexti;
4069 continue;
4070 }
4071
4072 sprptr[i]->x=sprptr[host]->x;
4073 sprptr[i]->y=sprptr[host]->y;
4074 if( sprptr[i]->picnum == FIREPIC ) {
4075 sprptr[i]->z=sprptr[host]->z-(tilesiz[sprptr[host]->picnum].y<<4);
4076 }
4077 else {
4078 sprptr[i]->z=sprptr[host]->z;
4079 }
4080
4081 if( sprptr[i]->picnum == FIREPIC ) {
4082 sprptr[i]->hitag+=4;
4083 if( sprptr[i]->hitag >= (TICSPERFRAME<<3) ) {
4084 sprptr[host]->shade++;
4085 sprptr[i]->hitag=0;
4086 }
4087 if( sprptr[host]->shade > 12 ) {
4088 damagesprite(host, 1024);
4089 sprptr[i]->lotag=0;
4090 }
4091 }
4092 else {
4093 sprptr[i]->lotag -= ((int)TICSPERFRAME);
4094 if( damagesprite(host, 4) == 1 ) { // killed 'em
4095 // NOT NETWORK COMPATIBLE
4096 killscore(host, screenpeek, 0);
4097 sprptr[i]->lotag=0;
4098 }
4099 }
4100
4101 if (sprptr[i]->lotag <= 0) {
4102 jsdeletesprite(i);
4103 }
4104
4105 #ifdef VERIFYSTATS
4106 verifystatus(nexti,VIRUS);
4107 #endif
4108 i = nexti;
4109 }
4110
4111 menuison:
4112
4113 i=headspritestat[MIRRORMAN1];
4114 while (i >= 0)
4115 {
4116 nexti = nextspritestat[i];
4117
4118 px=posx[screenpeek];
4119 py=posy[screenpeek];
4120 pz=posz[screenpeek];
4121
4122 if( (px < -55326) || (px > -52873) || (py > 40521) || (py < 36596) ) {
4123 i=nexti;
4124 continue;
4125 }
4126 deltapy=py-36596;
4127
4128 if( drawweap[screenpeek] )
4129 sprptr[i]->picnum=1079;
4130 else
4131 sprptr[i]->picnum=1074;
4132
4133 prevx=sprptr[i]->x;
4134 prevy=sprptr[i]->y;
4135 prevz=sprptr[i]->z;
4136
4137 sprptr[i]->x=px;
4138 sprptr[i]->y=36596-deltapy;
4139 sprptr[i]->z=pz+(42<<8);
4140
4141 sprptr[i]->ang=(ang[screenpeek]+1024)&2047;
4142
4143 #ifdef VERIFYSTATS
4144 verifystatus(nexti,MIRRORMAN1);
4145 #endif
4146 i = nexti;
4147 }
4148
4149 i=headspritestat[MIRRORMAN2];
4150 while (i >= 0)
4151 {
4152 nexti = nextspritestat[i];
4153
4154 px=posx[screenpeek];
4155 py=posy[screenpeek];
4156 pz=posz[screenpeek];
4157
4158 if( (px < -34792) || (px > -32404) || (py > 38980) || (py < 35074) ) {
4159 i=nexti;
4160 continue;
4161 }
4162 deltapy=38980-py;
4163
4164 if( drawweap[screenpeek] )
4165 sprptr[i]->picnum=1079;
4166 else
4167 sprptr[i]->picnum=1074;
4168
4169 prevx=sprptr[i]->x;
4170 prevy=sprptr[i]->y;
4171 prevz=sprptr[i]->z;
4172
4173 sprptr[i]->x=px;
4174 sprptr[i]->y=38980+deltapy;
4175 sprptr[i]->z=pz+(42<<8);
4176
4177 sprptr[i]->ang=(ang[screenpeek]+1024)&2047;
4178
4179 #ifdef VERIFYSTATS
4180 verifystatus(nexti,MIRRORMAN2);
4181 #endif
4182 i = nexti;
4183 }
4184
4185 i = headspritestat[PROJECTILE];
4186 while (i != -1)
4187 {
4188 nexti = nextspritestat[i];
4189
4190 dax = ((((int)sprptr[i]->xvel)*TICSPERFRAME)<<11);
4191 day = ((((int)sprptr[i]->yvel)*TICSPERFRAME)<<11);
4192 daz = ((((int)sprptr[i]->zvel)*TICSPERFRAME)>>2); // was 3
4193
4194 hitobject = movesprite((short)i,dax,day,daz,4L<<8,4L<<8,1);
4195
4196 if( hitobject != 0 ) {
4197 if( (hitobject&0xc000) == 16384 ) { // hit a ceiling or floor
4198 }
4199 else if( (hitobject&0xc000) == 32768 ) { // hit a wall
4200 //playsound( ??? , sprptr[i]->x,sprptr[i]->y, 0,ST_UPDATE);
4201 }
4202 else if( (hitobject&0xc000) == 49152 ) { // hit a sprite
4203 hitsprite=(hitobject&4095);
4204 if( playerhit(hitsprite, &pnum) ) {
4205 playerpainsound(pnum);
4206 enemywoundplayer(pnum,sprptr[i]->owner,6);
4207 }
4208 else {
4209 damagesprite(hitsprite,
4210 tekgundamage(6,sprptr[i]->x,sprptr[i]->y,sprptr[i]->z,hitsprite));
4211 }
4212 }
4213 jsdeletesprite(i);
4214 }
4215
4216 #ifdef VERIFYSTATS
4217 verifystatus(nexti,PROJECTILE);
4218 #endif
4219 i = nexti;
4220 }
4221
4222 for( i=0; i<MAXSPRITES; i++ ) {
4223 ext=sprptr[i]->extra;
4224 if( validext(ext) ) {
4225 if( ((sprXTptr[ext]->fxmask)&FX_NXTSTTDEATH) != 0 ) {
4226 sprXTptr[ext]->fxmask&=(~FX_NXTSTTDEATH);
4227 newstatus(i, DEATH);
4228 }
4229 else if( ((sprXTptr[ext]->fxmask)&FX_NXTSTTPAIN) != 0 ) {
4230 sprXTptr[ext]->fxmask&=(~FX_NXTSTTPAIN);
4231 newstatus(i, PAIN);
4232 }
4233 }
4234 }
4235
4236 gunstatuslistcode();
4237 }
4238
4239 int
playerhit(int hitsprite,int * pnum)4240 playerhit(int hitsprite, int *pnum)
4241 {
4242 int j;
4243
4244 for( j=connecthead ; j >= 0 ; j=connectpoint2[j] ) {
4245 if( playersprite[j] == hitsprite ) {
4246 if( sprptr[hitsprite]->statnum != 8 ) {
4247 crash("plrhit: plrsprt lost sttnm 8");
4248 }
4249 *pnum=j;
4250 return(1);
4251 }
4252 }
4253
4254 return(0);
4255 }
4256
4257 void
checkblastarea(int spr)4258 checkblastarea(int spr)
4259 {
4260 int sect,i,j,nexti,xydist,zdist;
4261
4262 #ifdef PLRSPRDEBUG
4263 if( isaplayersprite(spr) ) {
4264 crash("messing w plrsprite at 27");
4265 }
4266 #endif
4267
4268 sect=sprptr[spr]->sectnum;
4269
4270 for( j=connecthead ; j >= 0 ; j=connectpoint2[j] ) {
4271 xydist=klabs(sprptr[spr]->x-posx[j])+klabs(sprptr[spr]->y-posy[j]);
4272 zdist=klabs(sprptr[spr]->z-posz[j]);
4273 if( (xydist < 512) && (zdist < 10240) ) {
4274 changehealth(j, -5000);
4275 }
4276 else if( (xydist < 2048) && (zdist < 20480) ) {
4277 changehealth(j, -800);
4278 }
4279 else if( (xydist < 4096) && (zdist < 40960) ) {
4280 changehealth(j, -200);
4281 }
4282 }
4283
4284 if( option[4] == 0 ) {
4285 for( i=headspritesect[sect]; i>=0; i=nexti ) {
4286 nexti = nextspritesect[i];
4287 if( (i != spr) && (!isaplayersprite(i)) ) {
4288 switch( sprptr[i]->statnum ) {
4289 case PLAYER:
4290 case BOMBPROJECTILESTAT:
4291 case BOMBPROJECTILESTAT2:
4292 case RUNTHRU:
4293 case INACTIVE:
4294 case DEATH:
4295 break;
4296 default:
4297 xydist=klabs(sprptr[spr]->x-sprptr[i]->x)+klabs(sprptr[spr]->y-sprptr[i]->y);
4298 zdist=klabs(sprptr[spr]->z - sprptr[i]->z);
4299 if( (xydist < 2560) && (zdist < 16384) ) {
4300 damagesprite(i, -500);
4301 }
4302 break;
4303 }
4304 }
4305 }
4306 }
4307 }
4308
4309 void
genexplosion1(int i)4310 genexplosion1(int i)
4311 {
4312 int j;
4313
4314 #ifdef PLRSPRDEBUG
4315 if( isaplayersprite(i) ) {
4316 crash("messing w plrsprite at 30");
4317 }
4318 #endif
4319
4320 j=jsinsertsprite(sprptr[i]->sectnum, 5);
4321 if( j != -1 ) {
4322 fillsprite(j,sprptr[i]->x,sprptr[i]->y,sprptr[i]->z,0,
4323 -16,0,0,64,64,0,0,GENEXP1PIC+1,sprptr[i]->ang,
4324 sintable[(sprptr[i]->ang+2560)&2047]>>6,sintable[(sprptr[i]->ang+2048)&2047]>>6,
4325 30L,i+4096,sprptr[i]->sectnum, 5,24,0,-1);
4326 playsound(S_SMALLGLASS1+RMOD2("STAT4534"), sprptr[i]->x,sprptr[i]->y,0,ST_NOUPDATE);
4327 return;
4328 }
4329 }
4330
4331 void
genexplosion2(int i)4332 genexplosion2(int i)
4333 {
4334 int j;
4335
4336 #ifdef PLRSPRDEBUG
4337 if( isaplayersprite(i) ) {
4338 crash("messing w plrsprite at 31");
4339 }
4340 #endif
4341
4342 sectorflash(sprptr[i]->sectnum);
4343 checkblastarea(i);
4344
4345 j=jsinsertsprite(sprptr[i]->sectnum, 5);
4346 if( j != -1 ) {
4347 fillsprite(j,sprptr[i]->x,sprptr[i]->y,sprptr[i]->z-(tilesiz[sprptr[i]->picnum].y<<3),0,
4348 -16,0,0,64,64,0,0,GENEXP2PIC,sprptr[i]->ang,
4349 sintable[(sprptr[i]->ang+2560)&2047]>>6,sintable[(sprptr[i]->ang+2048)&2047]>>6,
4350 30L,i+4096,sprptr[i]->sectnum, 5,32,0,-1);
4351 playsound(S_EXPLODE1+RMOD2("STAT4559"), sprptr[i]->x,sprptr[i]->y,0,ST_NOUPDATE);
4352 }
4353 }
4354
4355 void
bombexplosion(int i)4356 bombexplosion(int i)
4357 {
4358 int j;
4359
4360 #ifdef PLRSPRDEBUG
4361 if( isaplayersprite(i) ) {
4362 crash("messing w plrsprite at 32");
4363 }
4364 #endif
4365
4366 j=jsinsertsprite(sprptr[i]->sectnum, 5);
4367 if( j != -1 ) {
4368 fillsprite(j,sprptr[i]->x,sprptr[i]->y,sprptr[i]->z,0,
4369 -16,0,0,34,34,0,0,BOMBEXP1PIC,sprptr[i]->ang,
4370 sintable[(sprptr[i]->ang+2560)&2047]>>6,sintable[(sprptr[i]->ang+2048)&2047]>>6,
4371 30L,i+4096,sprptr[i]->sectnum, 5,32,0,-1);
4372 playsound(S_RIC2, sprptr[i]->x,sprptr[i]->y,0,ST_NOUPDATE);
4373 }
4374 }
4375
4376 void
androidexplosion(int i)4377 androidexplosion(int i)
4378 {
4379 int j;
4380
4381 j=jsinsertsprite(sprptr[i]->sectnum, 5);
4382 if( j != -1 ) {
4383 fillsprite(j,sprptr[i]->x,sprptr[i]->y,sprptr[i]->z,0,
4384 -16,0,0,34,34,0,0,456,sprptr[i]->ang,
4385 sintable[(sprptr[i]->ang+2560)&2047]>>6,sintable[(sprptr[i]->ang+2048)&2047]>>6,
4386 30L,i+4096,sprptr[i]->sectnum, 5,32,0,-1);
4387 }
4388 playsound(S_ANDROID_DIE, sprptr[i]->x,sprptr[i]->y,0,ST_NOUPDATE);
4389 }
4390
4391 void
blastmark(int i)4392 blastmark(int i)
4393 {
4394 int j;
4395
4396 #ifdef PLRSPRDEBUG
4397 if( isaplayersprite(i) ) {
4398 crash("messing w plrsprite at 33");
4399 }
4400 #endif
4401
4402 switch( sprptr[i]->statnum ) {
4403 case GENEXPLODE2:
4404 break;
4405 default:
4406 return;
4407 }
4408 switch( sprptr[i]->picnum ) {
4409 case BARRELL:
4410 case 175:
4411 break;
4412 default:
4413 return;
4414 }
4415
4416 j=jsinsertsprite(sprptr[i]->sectnum, 100);
4417 if( j != -1 ) {
4418 fillsprite(j,sprptr[i]->x,sprptr[i]->y,sectptr[sprptr[i]->sectnum]->floorz,0x00A2,
4419 4,0,0,34,34,0,0,465,sprptr[i]->ang,0,0,
4420 30L,i+4096,sprptr[i]->sectnum,100,0,0,-1);
4421 }
4422 }
4423
4424 void
forceexplosion(int i)4425 forceexplosion(int i)
4426 {
4427 int j,k;
4428
4429 #ifdef PLRSPRDEBUG
4430 if( isaplayersprite(i) ) {
4431 crash("messing w plrsprite at 34");
4432 }
4433 #endif
4434
4435 j=jsinsertsprite(sprite[i].sectnum, 5);
4436 if( j != -1 ) {
4437 fillsprite(j,sprite[i].x,sprite[i].y,sprite[i].z,0,-4,0,
4438 32,34,34,0,0,FORCEBALLPIC,sprite[i].ang,
4439 0,0,0,sprite[i].owner,sprite[i].sectnum,5,31,0,-1);
4440 }
4441
4442 for(k=0;k<6;k++)
4443 {
4444 j=jsinsertsprite(sprite[i].sectnum, 7);
4445 if( j != -1 ) {
4446 fillsprite(j,sprite[i].x,sprite[i].y,sprite[i].z+(8<<10),2,-4,0,
4447 32,24,24,0,0,FORCEBALLPIC,sprite[i].ang,
4448 (krand_intercept("STAT4497")&511)-256,(krand_intercept("STAT4497")&511)-256,(krand_intercept("STAT4497")&16384)-8192,
4449 sprite[i].owner,sprite[i].sectnum,7,96,0,-1);
4450 }
4451 }
4452
4453 playsound(S_FORCEFIELD2, sprptr[i]->x,sprptr[i]->y,0, ST_UPDATE);
4454 }
4455
4456 void
sectorflash(short s)4457 sectorflash(short s)
4458 {
4459 if( sectflash.step != 0 ) {
4460 return;
4461 }
4462 sectflash.sectnum=s;
4463 sectflash.step=1;
4464 sectflash.ovis=sectptr[s]->visibility;
4465 }
4466
4467 void
dosectorflash()4468 dosectorflash()
4469 {
4470 switch( sectflash.step ) {
4471 case 0:
4472 break;
4473 case 1:
4474 sectptr[sectflash.sectnum]->visibility=0;
4475 sectflash.step=2;
4476 break;
4477 case 2:
4478 sectptr[sectflash.sectnum]->visibility=128;
4479 sectflash.step=3;
4480 break;
4481 case 3:
4482 sectptr[sectflash.sectnum]->visibility=0;
4483 sectflash.step=4;
4484 break;
4485 case 4:
4486 sectptr[sectflash.sectnum]->visibility=sectflash.ovis;
4487 sectflash.sectnum=0;
4488 sectflash.ovis=0;
4489 sectflash.step=0;
4490 }
4491 }
4492
4493 void
tekstatsave(int fh)4494 tekstatsave(int fh)
4495 {
4496 int i;
4497
4498 for (i=0 ; i < MAXSPRITES ; i++) {
4499 write(fh,&spriteXT[i],sizeof(struct spriteextension));
4500 }
4501 }
4502
4503 void
tekstatload(int fh)4504 tekstatload(int fh)
4505 {
4506 int i;
4507
4508 for (i=0 ; i < MAXSPRITES ; i++) {
4509 read(fh,&spriteXT[i],sizeof(struct spriteextension));
4510 }
4511 }
4512