1 //-------------------------------------------------------------------------
2 /*
3 Copyright (C) 1996, 2003 - 3D Realms Entertainment
4 Copyright (C) 2017-2019 Nuke.YKT
5 
6 This file is part of Duke Nukem 3D version 1.5 - Atomic Edition
7 
8 Duke Nukem 3D is free software; you can redistribute it and/or
9 modify it under the terms of the GNU General Public License
10 as published by the Free Software Foundation; either version 2
11 of the License, or (at your option) any later version.
12 
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
16 
17 See the GNU General Public License for more details.
18 
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
22 
23 Original Source: 1996 - Todd Replogle
24 Prepared for public release: 03/21/2003 - Charlie Wiederhold, 3D Realms
25 */
26 //-------------------------------------------------------------------------
27 
28 #include "duke3d.h"
29 
30 #include "lava.h"
31 
32 // PRIMITIVE
33 
34 
35 char haltsoundhack;
36 
callsound2(short sn,short snum)37 short callsound2(short sn, short snum)
38 {
39     short i;
40     struct player_struct *p;
41     p = &ps[snum];
42     i = p->i;
43     spritesound(sn,i);
44     return 1;
45 }
callsound(short sn,short whatsprite)46 short callsound(short sn,short whatsprite)
47 {
48     short i;
49 
50     i = headspritesect[sn];
51     while(i >= 0)
52     {
53         if( PN == MUSICANDSFX && SLT < 1000 )
54         {
55             if(whatsprite == -1) whatsprite = i;
56 
57             if(T1 == 0)
58             {
59                 if( (soundm[SLT]&16) == 0)
60                 {
61                     if(SLT)
62                     {
63                         spritesound(SLT,whatsprite);
64                         if(SHT && SLT != SHT && SHT < NUM_SOUNDS)
65                             stopsound(SHT);
66                     }
67 
68                     if( (sector[SECT].lotag&0xff) != 22)
69                         T1 = 1;
70                 }
71             }
72             else if(SHT < NUM_SOUNDS)
73             {
74                 if(SHT) spritesound(SHT,whatsprite);
75                 if( (soundm[SLT]&1) || ( SHT && SHT != SLT ) )
76                     stopsound(SLT);
77                 T1 = 0;
78             }
79             return SLT;
80         }
81         i = nextspritesect[i];
82     }
83     return -1;
84 }
85 
86 
check_activator_motion(short lotag)87 short check_activator_motion( short lotag )
88 {
89     short i, j;
90     spritetype *s;
91 
92     i = headspritestat[8];
93     while ( i >= 0 )
94     {
95         if ( sprite[i].lotag == lotag )
96         {
97             s = &sprite[i];
98 
99             for ( j = animatecnt-1; j >= 0; j-- )
100                 if ( s->sectnum == animatesect[j] )
101                     return( 1 );
102 
103             j = headspritestat[3];
104             while ( j >= 0 )
105             {
106                 if(s->sectnum == sprite[j].sectnum)
107                     switch(sprite[j].lotag)
108                     {
109                         case 11:
110                         case 30:
111                             if ( hittype[j].temp_data[4] )
112                                 return( 1 );
113                             break;
114                         case 20:
115                         case 31:
116                         case 32:
117 #ifndef RRRA
118                         case 18:
119 #endif
120                             if ( hittype[j].temp_data[0] )
121                                 return( 1 );
122                             break;
123                     }
124 
125                 j = nextspritestat[j];
126             }
127         }
128         i = nextspritestat[i];
129     }
130     return( 0 );
131 }
132 
isadoorwall(short dapic)133 char isadoorwall(short dapic)
134 {
135     switch(dapic)
136     {
137         case DOORTILE1:
138         case DOORTILE2:
139         case DOORTILE3:
140         case DOORTILE4:
141         case DOORTILE5:
142         case DOORTILE6:
143         case DOORTILE7:
144         case DOORTILE8:
145         case DOORTILE9:
146         case DOORTILE10:
147         case DOORTILE11:
148         case DOORTILE12:
149         case DOORTILE14:
150         case DOORTILE15:
151         case DOORTILE16:
152         case DOORTILE17:
153         case DOORTILE18:
154         case DOORTILE19:
155         case DOORTILE20:
156         case DOORTILE21:
157         case DOORTILE22:
158         case RRTILE1856:
159         case RRTILE1877:
160             return 1;
161     }
162     return 0;
163 }
164 
isablockdoor(short dapic)165 char isablockdoor(short dapic)
166 {
167     switch (dapic)
168     {
169         case RRTILE1792:
170         case RRTILE1801:
171         case RRTILE1805:
172         case RRTILE1807:
173         case RRTILE1808:
174         case RRTILE1812:
175         case RRTILE1821:
176         case RRTILE1826:
177         case RRTILE1850:
178         case RRTILE1851:
179         case RRTILE1856:
180         case RRTILE1877:
181         case RRTILE1938:
182         case RRTILE1942:
183         case RRTILE1944:
184         case RRTILE1945:
185         case RRTILE1951:
186         case RRTILE1961:
187         case RRTILE1964:
188         case RRTILE1985:
189         case RRTILE1995:
190         case RRTILE2022:
191         case RRTILE2052:
192         case RRTILE2053:
193         case RRTILE2060:
194         case RRTILE2074:
195         case RRTILE2132:
196         case RRTILE2136:
197         case RRTILE2139:
198         case RRTILE2150:
199         case RRTILE2178:
200         case RRTILE2186:
201         case RRTILE2319:
202         case RRTILE2321:
203         case RRTILE2326:
204         case RRTILE2329:
205         case RRTILE2578:
206         case RRTILE2581:
207         case RRTILE2610:
208         case RRTILE2613:
209         case RRTILE2621:
210         case RRTILE2622:
211         case RRTILE2676:
212         case RRTILE2732:
213         case RRTILE2831:
214         case RRTILE2832:
215         case RRTILE2842:
216         case RRTILE2940:
217         case RRTILE2970:
218         case RRTILE3083:
219         case RRTILE3100:
220         case RRTILE3155:
221         case RRTILE3195:
222         case RRTILE3232:
223         case RRTILE3600:
224         case RRTILE3631:
225         case RRTILE3635:
226         case RRTILE3637:
227         case RRTILE3643+2:
228         case RRTILE3643+3:
229         case RRTILE3647:
230         case RRTILE3652:
231         case RRTILE3653:
232         case RRTILE3671:
233         case RRTILE3673:
234         case RRTILE3684:
235         case RRTILE3708:
236         case RRTILE3714:
237         case RRTILE3716:
238         case RRTILE3723:
239         case RRTILE3725:
240         case RRTILE3737:
241         case RRTILE3754:
242         case RRTILE3762:
243         case RRTILE3763:
244         case RRTILE3764:
245         case RRTILE3765:
246         case RRTILE3767:
247         case RRTILE3793:
248         case RRTILE3814:
249         case RRTILE3815:
250         case RRTILE3819:
251         case RRTILE3827:
252         case RRTILE3837:
253 #ifdef RRRA
254         case RRTILE1996:
255         case RRTILE2382:
256         case RRTILE2961:
257         case RRTILE3804:
258         case RRTILE7430:
259         case RRTILE7467:
260         case RRTILE7469:
261         case RRTILE7470:
262         case RRTILE7475:
263         case RRTILE7566:
264         case RRTILE7576:
265         case RRTILE7716:
266         case RRTILE8063:
267         case RRTILE8067:
268         case RRTILE8076:
269         case RRTILE8106:
270         case RRTILE8379:
271         case RRTILE8380:
272         case RRTILE8565:
273         case RRTILE8605:
274 #endif
275             return 1;
276     }
277     return 0;
278 }
279 
280 
isanunderoperator(short lotag)281 char isanunderoperator(short lotag)
282 {
283     switch(lotag&0xff)
284     {
285         case 15:
286         case 16:
287         case 17:
288         case 18:
289         case 19:
290         case 26:
291             return 1;
292     }
293     return 0;
294 }
295 
isanearoperator(short lotag)296 char isanearoperator(short lotag)
297 {
298     switch(lotag&0xff)
299     {
300         case 9:
301         case 15:
302         case 16:
303         case 17:
304         case 18:
305         case 19:
306         case 20:
307         case 21:
308         case 22:
309         case 23:
310         case 25:
311         case 26:
312         case 29://Toothed door
313         case 41:
314             return 1;
315     }
316     return 0;
317 }
318 
checkcursectnums(short sect)319 short checkcursectnums(short sect)
320 {
321     short i;
322     for(i=connecthead;i>=0;i=connectpoint2[i])
323         if( sprite[ps[i].i].sectnum == sect ) return i;
324     return -1;
325 }
326 
ldist(spritetype * s1,spritetype * s2)327 long ldist(spritetype *s1,spritetype *s2)
328 {
329     long vx,vy;
330     vx = s1->x - s2->x;
331     vy = s1->y - s2->y;
332     return(FindDistance2D(vx,vy) + 1);
333 }
334 
dist(spritetype * s1,spritetype * s2)335 long dist(spritetype *s1,spritetype *s2)
336 {
337     long vx,vy,vz;
338     vx = s1->x - s2->x;
339     vy = s1->y - s2->y;
340     vz = s1->z - s2->z;
341     return(FindDistance3D(vx,vy,vz>>4));
342 }
343 
findplayer(spritetype * s,long * d)344 short findplayer(spritetype *s,long *d)
345 {
346     short j, closest_player;
347     long x, closest;
348 
349     if(ud.multimode < 2)
350     {
351         *d = klabs(ps[myconnectindex].oposx-s->x) + klabs(ps[myconnectindex].oposy-s->y) + ((klabs(ps[myconnectindex].oposz-s->z+(28<<8)))>>4);
352         return myconnectindex;
353     }
354 
355     closest = 0x7fffffff;
356     closest_player = 0;
357 
358     for(j=connecthead;j>=0;j=connectpoint2[j])
359     {
360         x = klabs(ps[j].oposx-s->x) + klabs(ps[j].oposy-s->y) + ((klabs(ps[j].oposz-s->z+(28<<8)))>>4);
361         if( x < closest && sprite[ps[j].i].extra > 0 )
362         {
363             closest_player = j;
364             closest = x;
365         }
366     }
367 
368     *d = closest;
369     return closest_player;
370 }
371 
findotherplayer(short p,long * d)372 short findotherplayer(short p,long *d)
373 {
374     short j, closest_player;
375     long x, closest;
376 
377     closest = 0x7fffffff;
378     closest_player = p;
379 
380     for(j=connecthead;j>=0;j=connectpoint2[j])
381         if(p != j && sprite[ps[j].i].extra > 0)
382     {
383         x = klabs(ps[j].oposx-ps[p].posx) + klabs(ps[j].oposy-ps[p].posy) + (klabs(ps[j].oposz-ps[p].posz)>>4);
384 
385         if( x < closest )
386         {
387             closest_player = j;
388             closest = x;
389         }
390     }
391 
392     *d = closest;
393     return closest_player;
394 }
395 
396 
397 
doanimations(void)398 void doanimations(void)
399 {
400 	long i, j, a, p, v, dasect;
401 
402 	for(i=animatecnt-1;i>=0;i--)
403 	{
404 		a = *animateptr[i];
405 		v = animatevel[i]*TICSPERFRAME;
406 		dasect = animatesect[i];
407 
408         if (a == animategoal[i])
409         {
410             stopinterpolation(animateptr[i]);
411 
412             animatecnt--;
413             animateptr[i] = animateptr[animatecnt];
414             animategoal[i] = animategoal[animatecnt];
415             animatevel[i] = animatevel[animatecnt];
416             animatesect[i] = animatesect[animatecnt];
417             if( sector[animatesect[i]].lotag == 18 || sector[animatesect[i]].lotag == 19 )
418                 if(animateptr[i] == &sector[animatesect[i]].ceilingz)
419                     continue;
420 
421            if( (sector[dasect].lotag&0xff) != 22 )
422                 callsound(dasect,-1);
423 
424             continue;
425         }
426 
427         if (v > 0) { a = min(a+v,animategoal[i]); }
428               else { a = max(a+v,animategoal[i]); }
429 
430         if( animateptr[i] == &sector[animatesect[i]].floorz)
431         {
432             for(p=connecthead;p>=0;p=connectpoint2[p])
433                 if (ps[p].cursectnum == dasect)
434                     if ((sector[dasect].floorz-ps[p].posz) < (64<<8))
435                         if (sprite[ps[p].i].owner >= 0)
436             {
437                 ps[p].posz += v;
438                 ps[p].poszv = 0;
439                 if (p == myconnectindex)
440                 {
441                     myz += v;
442                     myzvel = 0;
443                     myzbak[((movefifoplc-1)&(MOVEFIFOSIZ-1))] = ps[p].posz;
444                 }
445             }
446 
447             for(j=headspritesect[dasect];j>=0;j=nextspritesect[j])
448                 if (sprite[j].statnum != 3)
449                 {
450                     hittype[j].bposz = sprite[j].z;
451                     sprite[j].z += v;
452                     hittype[j].floorz = sector[dasect].floorz+v;
453                 }
454         }
455 
456 		*animateptr[i] = a;
457 	}
458 }
459 
getanimationgoal(long * animptr)460 getanimationgoal(long *animptr)
461 {
462 	long i, j;
463 
464 	j = -1;
465     for(i=animatecnt-1;i>=0;i--)
466         if (animptr == (long *)animateptr[i])
467 		{
468 			j = i;
469 			break;
470 		}
471 	return(j);
472 }
473 
setanimation(short animsect,long * animptr,long thegoal,long thevel)474 setanimation(short animsect,long *animptr, long thegoal, long thevel)
475 {
476 	long i, j;
477 
478 	if (animatecnt >= MAXANIMATES-1)
479 		return(-1);
480 
481 	j = animatecnt;
482     for(i=0;i<animatecnt;i++)
483 		if (animptr == animateptr[i])
484 		{
485 			j = i;
486 			break;
487 		}
488 
489     animatesect[j] = animsect;
490 	animateptr[j] = animptr;
491 	animategoal[j] = thegoal;
492     if (thegoal >= *animptr)
493        animatevel[j] = thevel;
494     else
495        animatevel[j] = -thevel;
496 
497     if (j == animatecnt) animatecnt++;
498 
499     setinterpolation(animptr);
500 
501     return(j);
502 }
503 
504 
505 
506 
animatecamsprite(void)507 void animatecamsprite(void)
508 {
509     short i;
510 
511     if(camsprite <= 0) return;
512 
513     i = camsprite;
514 
515     if(T1 >= 11)
516     {
517         T1 = 0;
518 
519         if(ps[screenpeek].newowner >= 0)
520             OW = ps[screenpeek].newowner;
521 
522         else if(OW >= 0 && dist(&sprite[ps[screenpeek].i],&sprite[i]) < 2048)
523             xyzmirror(OW,PN);
524     }
525     else T1++;
526 }
527 
animatewalls(void)528 void animatewalls(void)
529 {
530     long i, j, p, t;
531 
532 #ifdef RRRA
533     if (ps[screenpeek].raat5dd == 1)
534     {
535         for (i = 0; i < MAXWALLS; i++)
536         {
537             if (wall[i].picnum == RRTILE7873)
538                 wall[i].xpanning += 6;
539             else if (wall[i].picnum == RRTILE7870)
540                 wall[i].xpanning += 6;
541         }
542     }
543 #endif
544 
545     for(p=0;p < numanimwalls ;p++)
546 //    for(p=numanimwalls-1;p>=0;p--)
547     {
548         i = animwall[p].wallnum;
549         j = wall[i].picnum;
550 
551             switch(j)
552             {
553                 case SCREENBREAK1:
554                 case SCREENBREAK2:
555                 case SCREENBREAK3:
556                 case SCREENBREAK4:
557                 case SCREENBREAK5:
558 
559                 case SCREENBREAK9:
560                 case SCREENBREAK10:
561                 case SCREENBREAK11:
562                 case SCREENBREAK12:
563                 case SCREENBREAK13:
564 
565                     if( (TRAND&255) < 16)
566                     {
567                         animwall[p].tag = wall[i].picnum;
568                         wall[i].picnum = SCREENBREAK6;
569                     }
570 
571                     continue;
572 
573                 case SCREENBREAK6:
574                 case SCREENBREAK7:
575                 case SCREENBREAK8:
576 
577                     if(animwall[p].tag >= 0)
578                         wall[i].picnum = animwall[p].tag;
579                     else
580                     {
581                         wall[i].picnum++;
582                         if(wall[i].picnum == (SCREENBREAK6+3) )
583                             wall[i].picnum = SCREENBREAK6;
584                     }
585                     continue;
586 
587             }
588 
589         if(wall[i].cstat&16)
590             switch(wall[i].overpicnum)
591         {
592             case W_FORCEFIELD:
593             case W_FORCEFIELD+1:
594             case W_FORCEFIELD+2:
595 
596                 t = animwall[p].tag;
597 
598                 if(wall[i].cstat&254)
599                 {
600                     wall[i].xpanning -= t>>10; // sintable[(t+512)&2047]>>12;
601                     wall[i].ypanning -= t>>10; // sintable[t&2047]>>12;
602 
603                     if(wall[i].extra == 1)
604                     {
605                         wall[i].extra = 0;
606                         animwall[p].tag = 0;
607                     }
608                     else
609                         animwall[p].tag+=128;
610 
611                     if( animwall[p].tag < (128<<4) )
612                     {
613                         if( animwall[p].tag&128 )
614                             wall[i].overpicnum = W_FORCEFIELD;
615                         else wall[i].overpicnum = W_FORCEFIELD+1;
616                     }
617                     else
618                     {
619                         if( (TRAND&255) < 32 )
620                             animwall[p].tag = 128<<(TRAND&3);
621                         else wall[i].overpicnum = W_FORCEFIELD+1;
622                     }
623                 }
624 
625                 break;
626         }
627     }
628 }
629 
activatewarpelevators(short s,short d)630 char activatewarpelevators(short s,short d) //Parm = sectoreffectornum
631 {
632     short i, sn;
633 
634     sn = sprite[s].sectnum;
635 
636     // See if the sector exists
637 
638     i = headspritestat[3];
639     while(i >= 0)
640     {
641 #ifdef RRRA
642         if( SLT == 17 || SLT == 18 )
643 #else
644         if( SLT == 17 )
645 #endif
646             if( SHT == sprite[s].hitag )
647                 if( (klabs(sector[sn].floorz-hittype[s].temp_data[2]) > SP) ||
648                     (sector[SECT].hitag == (sector[sn].hitag-d) ) )
649                         break;
650         i = nextspritestat[i];
651     }
652 
653     if(i==-1)
654     {
655         d = 0;
656         return 1; // No find
657     }
658     else
659     {
660         if(d == 0)
661             spritesound(ELEVATOR_OFF,s);
662         else spritesound(ELEVATOR_ON,s);
663     }
664 
665 
666     i = headspritestat[3];
667     while(i >= 0)
668     {
669 #ifdef RRRA
670         if( SLT == 17 || SLT == 18 )
671 #else
672         if( SLT == 17 )
673 #endif
674             if( SHT == sprite[s].hitag )
675             {
676                 T1 = d;
677                 T2 = d; //Make all check warp
678             }
679         i = nextspritestat[i];
680     }
681     return 0;
682 }
683 
684 
685 
operatesectors(short sn,short ii)686 void operatesectors(short sn,short ii)
687 {
688     long j, l, q, startwall, endwall;
689     long u6,u7;
690     short i;
691     char sect_error;
692     sectortype *sptr;
693 
694     long u1,u2,u3,u4,u5;
695 
696     sect_error = 0;
697     sptr = &sector[sn];
698 
699     switch(sptr->lotag&(0xffff-49152))
700     {
701 
702         case 41:
703             for (i = 0; i < jaildoorcnt; i++)
704             {
705                 if (jaildoorsecthtag[i] == sptr->hitag)
706                 {
707                     if (jaildooropen[i] == 0)
708                     {
709                         jaildooropen[i] = 1;
710                         jaildoordrag[i] = jaildoordist[i];
711 #ifdef RRRA
712                         if (jaildoorsound[i] != 0)
713 #endif
714                         callsound2(jaildoorsound[i],screenpeek);
715                     }
716                     if (jaildooropen[i] == 2)
717                     {
718                         jaildooropen[i] = 3;
719                         jaildoordrag[i] = jaildoordist[i];
720 #ifdef RRRA
721                         if (jaildoorsound[i] != 0)
722 #endif
723                         callsound2(jaildoorsound[i],screenpeek);
724                     }
725                 }
726             }
727             break;
728 
729         case 7:
730             startwall = sptr->wallptr;
731             endwall = startwall+sptr->wallnum;
732             for (j = startwall; j < endwall; j++)
733             {
734                 setanimation(sn,&wall[j].x,wall[j].x+1024,4);
735                 setanimation(sn,&wall[wall[j].nextwall].x,wall[wall[j].nextwall].x+1024,4);
736             }
737             break;
738 
739         case 30:
740             j = sector[sn].hitag;
741             if( hittype[j].tempang == 0 ||
742                 hittype[j].tempang == 256)
743                     callsound(sn,ii);
744             if(sprite[j].extra == 1)
745                 sprite[j].extra = 3;
746             else sprite[j].extra = 1;
747             break;
748 
749         case 31:
750 
751             j = sector[sn].hitag;
752             if(hittype[j].temp_data[4] == 0)
753                 hittype[j].temp_data[4] = 1;
754 
755             callsound(sn,ii);
756             break;
757 
758         case 26: //The split doors
759             i = getanimationgoal(&sptr->ceilingz);
760             if(i == -1) //if the door has stopped
761             {
762                 haltsoundhack = 1;
763                 sptr->lotag &= 0xff00;
764                 sptr->lotag |= 22;
765                 operatesectors(sn,ii);
766                 sptr->lotag &= 0xff00;
767                 sptr->lotag |= 9;
768                 operatesectors(sn,ii);
769                 sptr->lotag &= 0xff00;
770                 sptr->lotag |= 26;
771             }
772             return;
773 
774         case 9:
775         {
776             long dax,day,dax2,day2,sp;
777             long wallfind[2];
778 
779             startwall = sptr->wallptr;
780             endwall = startwall+sptr->wallnum-1;
781 
782             sp = sptr->extra>>4;
783 
784             //first find center point by averaging all points
785             dax = 0L, day = 0L;
786             for(i=startwall;i<=endwall;i++)
787             {
788                 dax += wall[i].x;
789                 day += wall[i].y;
790             }
791             dax /= (endwall-startwall+1);
792             day /= (endwall-startwall+1);
793 
794             //find any points with either same x or same y coordinate
795             //  as center (dax, day) - should be 2 points found.
796             wallfind[0] = -1;
797             wallfind[1] = -1;
798             for(i=startwall;i<=endwall;i++)
799                 if ((wall[i].x == dax) || (wall[i].y == day))
800                 {
801                     if (wallfind[0] == -1)
802                         wallfind[0] = i;
803                     else wallfind[1] = i;
804                 }
805 
806             for(j=0;j<2;j++)
807             {
808                 if ((wall[wallfind[j]].x == dax) && (wall[wallfind[j]].y == day))
809                 {
810                     //find what direction door should open by averaging the
811                     //  2 neighboring points of wallfind[0] & wallfind[1].
812                     i = wallfind[j]-1; if (i < startwall) i = endwall;
813                     dax2 = ((wall[i].x+wall[wall[wallfind[j]].point2].x)>>1)-wall[wallfind[j]].x;
814                     day2 = ((wall[i].y+wall[wall[wallfind[j]].point2].y)>>1)-wall[wallfind[j]].y;
815                     if (dax2 != 0)
816                     {
817                         dax2 = wall[wall[wall[wallfind[j]].point2].point2].x;
818                         dax2 -= wall[wall[wallfind[j]].point2].x;
819                         setanimation(sn,&wall[wallfind[j]].x,wall[wallfind[j]].x+dax2,sp);
820                         setanimation(sn,&wall[i].x,wall[i].x+dax2,sp);
821                         setanimation(sn,&wall[wall[wallfind[j]].point2].x,wall[wall[wallfind[j]].point2].x+dax2,sp);
822                         callsound(sn,ii);
823                     }
824                     else if (day2 != 0)
825                     {
826                         day2 = wall[wall[wall[wallfind[j]].point2].point2].y;
827                         day2 -= wall[wall[wallfind[j]].point2].y;
828                         setanimation(sn,&wall[wallfind[j]].y,wall[wallfind[j]].y+day2,sp);
829                         setanimation(sn,&wall[i].y,wall[i].y+day2,sp);
830                         setanimation(sn,&wall[wall[wallfind[j]].point2].y,wall[wall[wallfind[j]].point2].y+day2,sp);
831                         callsound(sn,ii);
832                     }
833                 }
834                 else
835                 {
836                     i = wallfind[j]-1; if (i < startwall) i = endwall;
837                     dax2 = ((wall[i].x+wall[wall[wallfind[j]].point2].x)>>1)-wall[wallfind[j]].x;
838                     day2 = ((wall[i].y+wall[wall[wallfind[j]].point2].y)>>1)-wall[wallfind[j]].y;
839                     if (dax2 != 0)
840                     {
841                         setanimation(sn,&wall[wallfind[j]].x,dax,sp);
842                         setanimation(sn,&wall[i].x,dax+dax2,sp);
843                         setanimation(sn,&wall[wall[wallfind[j]].point2].x,dax+dax2,sp);
844                         callsound(sn,ii);
845                     }
846                     else if (day2 != 0)
847                     {
848                         setanimation(sn,&wall[wallfind[j]].y,day,sp);
849                         setanimation(sn,&wall[i].y,day+day2,sp);
850                         setanimation(sn,&wall[wall[wallfind[j]].point2].y,day+day2,sp);
851                         callsound(sn,ii);
852                     }
853                 }
854             }
855 
856         }
857         return;
858 
859         case 15://Warping elevators
860 
861             if(sprite[ii].picnum != APLAYER) return;
862 //            if(ps[sprite[ii].yvel].select_dir == 1) return;
863 
864             i = headspritesect[sn];
865             while(i >= 0)
866             {
867                 if(PN==SECTOREFFECTOR && SLT == 17 ) break;
868                 i = nextspritesect[i];
869             }
870 
871             if(sprite[ii].sectnum == sn)
872             {
873                 if( activatewarpelevators(i,-1) )
874                     activatewarpelevators(i,1);
875                 else if( activatewarpelevators(i,1) )
876                     activatewarpelevators(i,-1);
877                 return;
878             }
879             else
880             {
881                 if(sptr->floorz > SZ)
882                     activatewarpelevators(i,-1);
883                 else
884                     activatewarpelevators(i,1);
885             }
886 
887             return;
888 
889         case 16:
890         case 17:
891 
892             i = getanimationgoal(&sptr->floorz);
893 
894             if(i == -1)
895             {
896                 i = nextsectorneighborz(sn,sptr->floorz,1,1);
897                 if( i == -1 )
898                 {
899                     i = nextsectorneighborz(sn,sptr->floorz,1,-1);
900                     if( i == -1 ) return;
901                     j = sector[i].floorz;
902                     setanimation(sn,&sptr->floorz,j,sptr->extra);
903                 }
904                 else
905                 {
906                     j = sector[i].floorz;
907                     setanimation(sn,&sptr->floorz,j,sptr->extra);
908                 }
909                 callsound(sn,ii);
910             }
911 
912             return;
913 
914         case 18:
915         case 19:
916 
917             i = getanimationgoal(&sptr->floorz);
918 
919             if(i==-1)
920             {
921                 i = nextsectorneighborz(sn,sptr->floorz,1,-1);
922                 if(i==-1) i = nextsectorneighborz(sn,sptr->floorz,1,1);
923                 if(i==-1) return;
924                 j = sector[i].floorz;
925                 q = sptr->extra;
926                 l = sptr->ceilingz-sptr->floorz;
927                 setanimation(sn,&sptr->floorz,j,q);
928                 setanimation(sn,&sptr->ceilingz,j+l,q);
929                 callsound(sn,ii);
930             }
931             return;
932 
933         case 29:
934 
935             if(sptr->lotag&0x8000)
936                 j = sector[nextsectorneighborz(sn,sptr->ceilingz,1,1)].floorz;
937             else
938                 j = sector[nextsectorneighborz(sn,sptr->ceilingz,-1,-1)].ceilingz;
939 
940             i = headspritestat[3]; //Effectors
941             while(i >= 0)
942             {
943                 if( (SLT == 22) &&
944                     (SHT == sptr->hitag) )
945                 {
946                     sector[SECT].extra = -sector[SECT].extra;
947 
948                     T1 = sn;
949                     T2 = 1;
950                 }
951                 i = nextspritestat[i];
952             }
953 
954             sptr->lotag ^= 0x8000;
955 
956             setanimation(sn,&sptr->ceilingz,j,sptr->extra);
957 
958             callsound(sn,ii);
959 
960             return;
961 
962         case 20:
963 
964             REDODOOR:
965 
966             if(sptr->lotag&0x8000)
967             {
968                 i = headspritesect[sn];
969                 while(i >= 0)
970                 {
971                     if(sprite[i].statnum == 3 && SLT==9)
972                     {
973                         j = SZ;
974                         break;
975                     }
976                     i = nextspritesect[i];
977                 }
978                 if(i==-1)
979                     j = sptr->floorz;
980             }
981             else
982             {
983                 j = nextsectorneighborz(sn,sptr->ceilingz,-1,-1);
984 
985                 if(j >= 0) j = sector[j].ceilingz;
986                 else
987                 {
988                     sptr->lotag |= 32768;
989                     goto REDODOOR;
990                 }
991             }
992 
993             sptr->lotag ^= 0x8000;
994 
995             setanimation(sn,&sptr->ceilingz,j,sptr->extra);
996             callsound(sn,ii);
997 
998             return;
999 
1000         case 21:
1001             i = getanimationgoal(&sptr->floorz);
1002             if (i >= 0)
1003             {
1004                 if (animategoal[sn] == sptr->ceilingz)
1005                     animategoal[i] = sector[nextsectorneighborz(sn,sptr->ceilingz,1,1)].floorz;
1006                 else animategoal[i] = sptr->ceilingz;
1007                 j = animategoal[i];
1008             }
1009             else
1010             {
1011                 if (sptr->ceilingz == sptr->floorz)
1012                     j = sector[nextsectorneighborz(sn,sptr->ceilingz,1,1)].floorz;
1013                 else j = sptr->ceilingz;
1014 
1015                 sptr->lotag ^= 0x8000;
1016 
1017                 if(setanimation(sn,&sptr->floorz,j,sptr->extra) >= 0)
1018                     callsound(sn,ii);
1019             }
1020             return;
1021 
1022         case 22:
1023 
1024             // REDODOOR22:
1025 
1026             if ( (sptr->lotag&0x8000) )
1027             {
1028                 q = (sptr->ceilingz+sptr->floorz)>>1;
1029                 j = setanimation(sn,&sptr->floorz,q,sptr->extra);
1030                 j = setanimation(sn,&sptr->ceilingz,q,sptr->extra);
1031             }
1032             else
1033             {
1034                 q = sector[nextsectorneighborz(sn,sptr->floorz,1,1)].floorz;
1035                 j = setanimation(sn,&sptr->floorz,q,sptr->extra);
1036                 q = sector[nextsectorneighborz(sn,sptr->ceilingz,-1,-1)].ceilingz;
1037                 j = setanimation(sn,&sptr->ceilingz,q,sptr->extra);
1038             }
1039 
1040             sptr->lotag ^= 0x8000;
1041 
1042             callsound(sn,ii);
1043 
1044             return;
1045 
1046         case 23: //Swingdoor
1047 
1048             j = -1;
1049             q = 0;
1050 
1051             i = headspritestat[3];
1052             while(i >= 0)
1053             {
1054                 if( SLT == 11 && SECT == sn && !T5)
1055                 {
1056                     j = i;
1057                     break;
1058                 }
1059                 i = nextspritestat[i];
1060             }
1061 
1062             l = sector[SECT].lotag&0x8000;
1063 
1064             if(j >= 0)
1065             {
1066                 i = headspritestat[3];
1067                 while(i >= 0)
1068                 {
1069                     if( l == (sector[SECT].lotag&0x8000) && SLT == 11 && sprite[j].hitag == SHT && !T5 )
1070                     {
1071                         if(sector[SECT].lotag&0x8000) sector[SECT].lotag &= 0x7fff;
1072                         else sector[SECT].lotag |= 0x8000;
1073                         T5 = 1;
1074                         T4 = -T4;
1075                         if(q == 0)
1076                         {
1077                             callsound(sn,i);
1078                             q = 1;
1079                         }
1080                     }
1081                     i = nextspritestat[i];
1082                 }
1083             }
1084             return;
1085 
1086         case 25: //Subway type sliding doors
1087 
1088             j = headspritestat[3];
1089             while(j >= 0)//Find the sprite
1090             {
1091                 if( (sprite[j].lotag) == 15 && sprite[j].sectnum == sn )
1092                     break; //Found the sectoreffector.
1093                 j = nextspritestat[j];
1094             }
1095 
1096             if(j < 0)
1097                 return;
1098 
1099             i = headspritestat[3];
1100             while(i >= 0)
1101             {
1102                 if( SHT==sprite[j].hitag )
1103                 {
1104                     if( SLT == 15 )
1105                     {
1106                         sector[SECT].lotag ^= 0x8000; // Toggle the open or close
1107                         SA += 1024;
1108                         if(T5) callsound(SECT,i);
1109                         callsound(SECT,i);
1110                         if(sector[SECT].lotag&0x8000) T5 = 1;
1111                         else T5 = 2;
1112                     }
1113                 }
1114                 i = nextspritestat[i];
1115             }
1116             return;
1117 
1118         case 27:  //Extended bridge
1119 
1120             j = headspritestat[3];
1121             while(j >= 0)
1122             {
1123                 if( (sprite[j].lotag&0xff)==20 && sprite[j].sectnum == sn) //Bridge
1124                 {
1125 
1126                     sector[sn].lotag ^= 0x8000;
1127                     if(sector[sn].lotag&0x8000) //OPENING
1128                         hittype[j].temp_data[0] = 1;
1129                     else hittype[j].temp_data[0] = 2;
1130                     callsound(sn,ii);
1131                     break;
1132                 }
1133                 j = nextspritestat[j];
1134             }
1135             return;
1136 
1137 
1138         case 28:
1139             //activate the rest of them
1140 
1141             j = headspritesect[sn];
1142             while(j >= 0)
1143             {
1144                 if(sprite[j].statnum==3 && (sprite[j].lotag&0xff)==21)
1145                     break; //Found it
1146                 j = nextspritesect[j];
1147             }
1148 
1149             j = sprite[j].hitag;
1150 
1151             l = headspritestat[3];
1152             while(l >= 0)
1153             {
1154                 if( (sprite[l].lotag&0xff)==21 && !hittype[l].temp_data[0] &&
1155                     (sprite[l].hitag) == j )
1156                     hittype[l].temp_data[0] = 1;
1157                 l = nextspritestat[l];
1158             }
1159             callsound(sn,ii);
1160 
1161             return;
1162     }
1163 }
1164 
1165 
1166 
operaterespawns(short low)1167 void operaterespawns(short low)
1168 {
1169     short i, j, nexti;
1170 
1171     i = headspritestat[11];
1172     while(i >= 0)
1173     {
1174         nexti = nextspritestat[i];
1175         if(SLT == low) switch(PN)
1176         {
1177             case RESPAWN:
1178                 if( badguypic(SHT) && ud.monsters_off ) break;
1179 
1180                 j = spawn(i,TRANSPORTERSTAR);
1181                 sprite[j].z -= (32<<8);
1182 
1183                 sprite[i].extra = 66-12;   // Just a way to killit
1184                 break;
1185 #ifdef RRRA
1186             case RRTILE7424:
1187                 if (!ud.monsters_off)
1188                     changespritestat(i,119);
1189                 break;
1190 
1191 #endif
1192         }
1193         i = nexti;
1194     }
1195 }
1196