1 /***************************************************************************
2  *   TEKTAG.C  - Tag specific code for TEKWAR game                         *
3  *                                                                         *
4  *                                                                         *
5  ***************************************************************************/
6 
7 #include "build.h"
8 #include "names.h"
9 #include "pragmas.h"
10 #include "mmulti.h"
11 
12 #include "tekwar.h"
13 
14 #define   AMBUPDATEDIST  4000L
15 
16 #define   BOBBMAX        512
17 #define   BOBBDELTA      128
18 
19 int       headbobon=1;
20 int       headbob,bobstep=BOBBDELTA;
21 
22 #define   VEHICLEHEIGHT  -13312
23 
24 #define   MAXANIMPICS         32
25 #define   MAXDELAYFUNCTIONS   32
26 
27 #define   BLUEKEYITEM         0
28 #define   REDKEYITEM          1
29 #define   ELEVACTIVATED       31
30 
31 #define   DOORUPTAG           6
32 #define   DOORDOWNTAG         7
33 #define   DOORSPLITHOR        8
34 #define   DOORSPLITVER        9
35 #define   DOORSWINGTAG        13
36 #define   DOORREVOLVETAG      14        // sector tags
37 
38 #define   PLATFORMELEVTAG     1000      // additional sector tags
39 #define   BOXELEVTAG          1003
40 #define   PLATFORMDELAYTAG    1004
41 #define   BOXDELAYTAG         1005
42 #define   DOORFLOORTAG        1006
43 #define   PLATFORMDROPTAG     1007
44 
45 #define   DST_BAYDOOR         10
46 #define   DST_HYDRAULICDOOR   20
47 #define   DST_ELEVATORDOOR    30
48 #define   DST_MATRIXDOOR1     40
49 #define   DST_MATRIXDOOR2     50
50 #define   DST_MATRIXDOOR3     60
51 #define   DST_MATRIXDOOR4     70
52 
53 #define   SPRITEELEVATORTAG   1500
54 
55 #define   PULSELIGHT          0         // sector effect tags flags32[]
56 #define   FLICKERLIGHT        1
57 #define   DELAYEFFECT         2
58 #define   WPANNING            3
59 #define   FPANNING            4
60 #define   CPANNING            5
61 #define   FLICKERDELAY        6
62 #define   BLINKDELAY          7
63 #define   STEADYLIGHT         8
64 #define   WARPSECTOR          9
65 #define   KILLSECTOR          10
66 #define   DOORSPEEDEFFECT     11
67 #define   QUICKCLOSE          12
68 #define   SOUNDON             13
69 #define   SOUNDOFF            14
70 #define   DOORSUBTYPE         15
71 
72 #define   DOORDELAY      (CLKIPS*4)
73 #define   DOORSPEED      128L
74 #define   ELEVSPEED      256L
75 
76 char onelev[MAXPLAYERS];
77 
78 struct sectoreffect {
79      unsigned int sectorflags;
80      int animate;
81      int  hi,lo;
82      int  delay,delayreset;
83      int  ang;
84      int  triggerable;
85      int  warpto;
86      int warpx,warpy,warpz;
87      int sin,cos;
88      short damage;
89 };
90 struct    sectoreffect   sectoreffect[MAXSECTORS];
91 struct    sectoreffect   *septrlist[MAXSECTORS];
92 int       secnt,sexref[MAXSECTORS];
93 
94 #define   MAXDOORS       200
95 enum {
96      D_NOTHING=0,
97      D_OPENDOOR,
98      D_CLOSEDOOR,
99      D_OPENING,
100      D_CLOSING,
101      D_WAITING,
102      D_SHUTSOUND,
103      D_OPENSOUND
104 };
105 enum {
106      DOORCLOSED=0,
107      DOOROPENING,
108      DOOROPENED,
109      DOORCLOSING
110 };
111 struct doortype {
112      int  type;
113      int  state;
114      int  sector;
115      int  step;
116      int  delay;
117      int goalz[4];
118      int points[4];
119      int  walls[8];
120      int centx;
121      int centy;
122      int centz;
123      int  subtype;   // jeff added 9-20
124 };
125 struct    doortype  doortype[MAXDOORS];
126 struct    doortype  *doorptr[MAXDOORS];
127 int       doorxref[MAXSECTORS],numdoors;
128 
129 #define   MAXFLOORDOORS  25
130 struct floordoor {
131      int  state;
132      int  sectnum;
133      int  wall1,wall2;
134      int  dist1,dist2;
135      int  dir;
136 };
137 struct    floordoor      floordoor[MAXFLOORDOORS];
138 struct    floordoor      *floordoorptr[MAXFLOORDOORS];
139 int       fdxref[MAXSECTORS],numfloordoors;
140 
141 #define   MAXSECTORVEHICLES   10
142 #define   MAXVEHICLEPOINTS    200
143 #define   MAXVEHICLETRACKS    50
144 #define   MAXVEHICLESECTORS   30
145 #define   SECTORVEHICLETAG    1010
146 struct sectorvehicle {
147      short acceleration,accelto;
148      short speed,speedto,movespeed;
149      short angle,angleto;
150      int pivotx,pivoty;
151      short numpoints;
152      short point[MAXVEHICLEPOINTS];
153      int pointx[MAXVEHICLEPOINTS];
154      int pointy[MAXVEHICLEPOINTS];
155      short track;
156      short tracknum;
157      int trackx[MAXVEHICLETRACKS];
158      int tracky[MAXVEHICLETRACKS];
159      char stop[MAXVEHICLETRACKS];
160      int distx,disty;
161      short sector[MAXVEHICLESECTORS];
162      short numsectors;
163      int waittics,waitdelay;
164      short stoptrack;
165      short killw[4];
166      int  soundindex;
167 };
168 struct    sectorvehicle  sectorvehicle[MAXSECTORVEHICLES];
169 struct    sectorvehicle  *sectvehptr[MAXSECTORVEHICLES];
170 int       numvehicles;
171 
172 #define   MAXSPRITEELEVS 25
173 #define   MAXPARTS       20
174 #define   MAXELEVFLOORS  20
175 #define   MAXELEVDOORS   4
176 enum {
177      E_OPENINGDOOR=0,
178      E_CLOSINGDOOR,
179      E_WAITING,
180      E_MOVING,
181      E_NEXTFLOOR
182 };
183 enum {
184      E_GOINGUP=0,
185      E_GOINGDOWN
186 };
187 #define   E_WAITDELAY    CLKIPS*4
188 #define   E_DOOROPENPOS  15360
189 struct elevatortype {
190      int hilevel;
191      int lolevel;
192 };
193 struct    elevatortype   elevator[MAXSECTORS];
194 struct    elevatortype   *evptrlist[MAXSECTORS];
195 
196 struct spriteelev {
197      int  state;
198      int  parts;
199      int  sprnum[MAXPARTS];
200      int  door[MAXELEVDOORS];
201      int doorpos;
202      int startz[MAXPARTS];
203      int floorz[MAXELEVFLOORS];
204      int  curfloor;
205      int  curdir;
206      int  delay;
207      int  floors;
208      int floorpos;
209      int  doors;
210 };
211 struct    spriteelev     spriteelev[MAXSPRITEELEVS];
212 struct    spriteelev     *sprelevptr[MAXSPRITEELEVS];
213 int       sprelevcnt;
214 
215 uint32_t flags32[32]={
216      0x80000000,0x40000000,0x20000000,0x10000000,
217      0x08000000,0x04000000,0x02000000,0x01000000,
218      0x00800000,0x00400000,0x00200000,0x00100000,
219      0x00080000,0x00040000,0x00020000,0x00010000,
220      0x00008000,0x00004000,0x00002000,0x00001000,
221      0x00000800,0x00000400,0x00000200,0x00000100,
222      0x00000080,0x00000040,0x00000020,0x00000010,
223      0x00000008,0x00000004,0x00000002,0x00000001
224 };
225 
226 #define   MAXMAPSOUNDFX            32
227 #define   MAP_SFX_AMBIENT          0
228 #define   MAP_SFX_SECTOR           1
229 #define   MAP_SFX_TOGGLED          2
230 #define   MAP_SFX_TURN_ON          3
231 #define   MAP_SFX_TURN_OFF         4
232 struct mapsndfxtype {
233      int      x,y;
234      short     sector;
235      int       snum;
236      int       loops;
237      int       type;
238      int       id;
239 };
240 struct    mapsndfxtype    mapsndfx[MAXMAPSOUNDFX];
241 struct    mapsndfxtype    *mapsndfxptr[MAXMAPSOUNDFX];
242 int       totalmapsndfx=0;
243 
244 int      ambupdateclock;
245 
246 struct animpic {
247      short frames;
248      short *pic;
249      short tics;
250      int nextclock;
251 } animpic[MAXANIMPICS],*animpicptr[MAXANIMPICS];
252 
253 struct delayfunc {
254      void (*func)(short);
255      int  tics;
256      short parm;
257 } delayfunc[MAXDELAYFUNCTIONS],*delayfuncptr[MAXDELAYFUNCTIONS];
258 
259 int      subwaystopdir[4] = { 1L, 1L, 1L, 1L };
260 void      checktoggledmapsndfx(short dasect) ;
261 int       numanimates;
262 short     numdelayfuncs;
263 int       loopinsound=-1;
264 int       baydoorloop=-1;
265 int       ambsubloop=-1;
266 
267 void
operatesector(short dasector)268 operatesector(short dasector)
269 {     //Door code
270      int i, j, datag;
271      int dax2, day2, centx, centy;
272      short startwall, endwall, wallfind[2];
273 
274      datag = sector[dasector].lotag;
275 
276      // lights out / on
277      if( datag == 33 ) {
278           if( sectptr[dasector]->visibility >= 212 ) {
279                sectptr[dasector]->visibility=0;
280           }
281           else {
282                sectptr[dasector]->visibility=212;
283           }
284           return;
285      }
286 
287      startwall = sector[dasector].wallptr;
288      endwall = startwall + sector[dasector].wallnum - 1;
289      centx = 0L, centy = 0L;
290      for(i=startwall;i<=endwall;i++)
291      {
292           centx += wall[i].x;
293           centy += wall[i].y;
294      }
295      centx /= (endwall-startwall+1);
296      centy /= (endwall-startwall+1);
297 
298      // kens swinging door
299      if( datag == 13 ) {
300           for( i=0; i<swingcnt; i++ ) {
301                if( swingsector[i] == dasector ) {
302                     if( swinganginc[i] == 0 ) {
303                          if( swingang[i] == swingangclosed[i] ) {
304                               swinganginc[i] = swingangopendir[i];
305                          }
306                          else {
307                               swinganginc[i] = -swingangopendir[i];
308                          }
309                     }
310                     else {
311                          swinganginc[i] = -swinganginc[i];
312                     }
313                }
314           }
315      }
316 
317      // kens true sideways double-sliding door
318      if( datag == 16 ) {
319           // get 2 closest line segments to center (dax, day)
320           wallfind[0] = -1;
321           wallfind[1] = -1;
322           for( i=startwall;i<=endwall;i++ )
323                if (wall[i].lotag == 6)
324                {
325                     if (wallfind[0] == -1)
326                          wallfind[0] = i;
327                     else
328                          wallfind[1] = i;
329                }
330 
331           for(j=0;j<2;j++)
332           {
333                if ((((wall[wallfind[j]].x+wall[wall[wallfind[j]].point2].x)>>1) == centx) && (((wall[wallfind[j]].y+wall[wall[wallfind[j]].point2].y)>>1) == centy))
334                {     //door was closed
335                          //find what direction door should open
336                     i = wallfind[j]-1; if (i < startwall) i = endwall;
337                     dax2 = wall[i].x-wall[wallfind[j]].x;
338                     day2 = wall[i].y-wall[wallfind[j]].y;
339                     if (dax2 != 0)
340                     {
341                          dax2 = wall[wall[wall[wall[wallfind[j]].point2].point2].point2].x;
342                          dax2 -= wall[wall[wall[wallfind[j]].point2].point2].x;
343                          setanimation(&wall[wallfind[j]].x,wall[wallfind[j]].x+dax2,4L,0L);
344                          setanimation(&wall[i].x,wall[i].x+dax2,4L,0L);
345                          setanimation(&wall[wall[wallfind[j]].point2].x,wall[wall[wallfind[j]].point2].x+dax2,4L,0L);
346                          setanimation(&wall[wall[wall[wallfind[j]].point2].point2].x,wall[wall[wall[wallfind[j]].point2].point2].x+dax2,4L,0L);
347                     }
348                     else if (day2 != 0)
349                     {
350                          day2 = wall[wall[wall[wall[wallfind[j]].point2].point2].point2].y;
351                          day2 -= wall[wall[wall[wallfind[j]].point2].point2].y;
352                          setanimation(&wall[wallfind[j]].y,wall[wallfind[j]].y+day2,4L,0L);
353                          setanimation(&wall[i].y,wall[i].y+day2,4L,0L);
354                          setanimation(&wall[wall[wallfind[j]].point2].y,wall[wall[wallfind[j]].point2].y+day2,4L,0L);
355                          setanimation(&wall[wall[wall[wallfind[j]].point2].point2].y,wall[wall[wall[wallfind[j]].point2].point2].y+day2,4L,0L);
356                     }
357                }
358                else
359                {    //door was not closed
360                     i = wallfind[j]-1; if (i < startwall) i = endwall;
361                     dax2 = wall[i].x-wall[wallfind[j]].x;
362                     day2 = wall[i].y-wall[wallfind[j]].y;
363                     if (dax2 != 0)
364                     {
365                          setanimation(&wall[wallfind[j]].x,centx,4L,0L);
366                          setanimation(&wall[i].x,centx+dax2,4L,0L);
367                          setanimation(&wall[wall[wallfind[j]].point2].x,centx,4L,0L);
368                          setanimation(&wall[wall[wall[wallfind[j]].point2].point2].x,centx+dax2,4L,0L);
369                     }
370                     else if (day2 != 0)
371                     {
372                          setanimation(&wall[wallfind[j]].y,centy,4L,0L);
373                          setanimation(&wall[i].y,centy+day2,4L,0L);
374                          setanimation(&wall[wall[wallfind[j]].point2].y,centy,4L,0L);
375                          setanimation(&wall[wall[wall[wallfind[j]].point2].point2].y,centy+day2,4L,0L);
376                     }
377                }
378           }
379      }
380 
381      tekoperatesector(dasector);
382 }
383 
384 
385 void
tagcode()386 tagcode()
387 {
388      int      i, j, k, l, s, dax, day, cnt, good;
389      short     startwall, endwall, dasector, p, oldang;
390 
391      for(i=0;i<warpsectorcnt;i++)
392      {
393           dasector = warpsectorlist[i];
394           j = ((lockclock&127)>>2);
395           if (j >= 16) j = 31-j;
396           {
397                sector[dasector].ceilingshade = j;
398                sector[dasector].floorshade = j;
399                startwall = sector[dasector].wallptr;
400                endwall = startwall+sector[dasector].wallnum-1;
401                for(s=startwall;s<=endwall;s++)
402                     wall[s].shade = j;
403           }
404      }
405 
406      for(p=connecthead;p>=0;p=connectpoint2[p])
407           if (sector[cursectnum[p]].lotag == 10)  //warp sector
408           {
409                if (cursectnum[p] != ocursectnum[p])
410                {
411                     warpsprite(playersprite[p]);
412                     posx[p] = sprite[playersprite[p]].x;
413                     posy[p] = sprite[playersprite[p]].y;
414                     posz[p] = sprite[playersprite[p]].z;
415                     ang[p] = sprite[playersprite[p]].ang;
416                     cursectnum[p] = sprite[playersprite[p]].sectnum;
417                     sprite[playersprite[p]].z += (KENSPLAYERHEIGHT<<8);
418                }
419           }
420 
421 
422      for( i=0; i<xpanningsectorcnt; i++ ) {
423           dasector = xpanningsectorlist[i];
424           startwall = sector[dasector].wallptr;
425           endwall = startwall+sector[dasector].wallnum-1;
426           for( s=startwall; s<=endwall; s++ ) {
427                wall[s].xpanning = ((lockclock>>2)&255);
428           }
429      }
430 
431      for( i=0; i<ypanningwallcnt; i++ ) {
432           wall[ypanningwalllist[i]].ypanning = ~(lockclock&255);
433      }
434 
435      for( i=0; i<rotatespritecnt; i++ ) {
436           sprite[rotatespritelist[i]].ang += (TICSPERFRAME<<2);
437           sprite[rotatespritelist[i]].ang &= 2047;
438      }
439 
440      // kens slime floor
441      for( i=0; i<floorpanningcnt; i++ ) {
442           sector[floorpanninglist[i]].floorxpanning = ((lockclock>>2)&255);
443           sector[floorpanninglist[i]].floorypanning = ((lockclock>>2)&255);
444      }
445 
446      for( i=0; i<dragsectorcnt; i++ ) {
447           dasector = dragsectorlist[i];
448           startwall = sector[dasector].wallptr;
449           endwall = startwall+sector[dasector].wallnum-1;
450           if (wall[startwall].x+dragxdir[i] < dragx1[i]) dragxdir[i] = 16;
451           if (wall[startwall].y+dragydir[i] < dragy1[i]) dragydir[i] = 16;
452           if (wall[startwall].x+dragxdir[i] > dragx2[i]) dragxdir[i] = -16;
453           if (wall[startwall].y+dragydir[i] > dragy2[i]) dragydir[i] = -16;
454           for( j=startwall; j<=endwall; j++) {
455                dragpoint(j,wall[j].x+dragxdir[i],wall[j].y+dragydir[i], 0);
456           }
457           j = sector[dasector].floorz;
458           sector[dasector].floorz = dragfloorz[i]+(sintable[(lockclock<<4)&2047]>>3);
459           for( p=connecthead; p>=0; p=connectpoint2[p] ) {
460                if( cursectnum[p] == dasector ) {
461                     posx[p] += dragxdir[i];
462                     posy[p] += dragydir[i];
463                     posz[p] += (sector[dasector].floorz-j);
464                     vec3_t pos;
465                     pos.x = posx[p]; pos.y = posy[p]; pos.z = posz[p] + (KENSPLAYERHEIGHT << 8);
466                     setsprite(playersprite[p],&pos);
467                     sprite[playersprite[p]].ang = ang[p];
468                     frameinterpolate = 0;
469                }
470           }
471      }
472 
473      for(i=0;i<swingcnt;i++)
474      {
475           if (swinganginc[i] != 0)
476           {
477                oldang = swingang[i];
478                for(j=0;j<(TICSPERFRAME<<2);j++)
479                {
480                     swingang[i] = ((swingang[i]+2048+swinganginc[i])&2047);
481                     if (swingang[i] == swingangclosed[i])
482                     {
483                          if( j == ((TICSPERFRAME<<2)-1) ) {
484                               playsound(S_JUMP,swingx[i][0],swingy[i][0],0,ST_UPDATE);
485                          }
486                          swinganginc[i] = 0;
487                     }
488                     if (swingang[i] == swingangopen[i]) {
489                          if( j == ((TICSPERFRAME<<2)-1) ) {
490                               playsound(S_JUMP,swingx[i][0],swingy[i][0],0,ST_UPDATE);
491                          }
492                          swinganginc[i] = 0;
493                     }
494                }
495                for (k = 1; k <= 3; k++)
496                {
497                    vec2_t pivot;
498                    pivot.x = swingx[i][0]; pivot.y = swingy[i][0];
499                    vec2_t p;
500                    p.x = swingx[i][k]; p.y = swingy[i][k];
501                    vec2_t p2;
502                    rotatepoint(pivot, p, swingang[i], &p2);
503                    wall[swingwall[i][k]].x = p.x;
504                    wall[swingwall[i][k]].y = p.y;
505                }
506 
507                if (swinganginc[i] != 0)
508                {
509                     for(p=connecthead;p>=0;p=connectpoint2[p])
510                          if ((cursectnum[p] == swingsector[i]) || (testneighborsectors(cursectnum[p],swingsector[i]) == 1))
511                          {
512                               cnt = 256;
513                               do
514                               {
515                                    good = 1;
516 
517                                         //swingangopendir is -1 if forwards, 1 is backwards
518                                    l = (swingangopendir[i] > 0);
519                                    for (k = l + 3; k >= l; k--)
520                                    {
521                                        vec2_t pos;
522                                        pos.x = posx[p]; pos.y = posy[p];
523                                        if (clipinsidebox(&pos, swingwall[i][k], 128L) != 0)
524                                        {
525                                            good = 0;
526                                            break;
527                                        }
528                                    }
529 
530                                    if (good == 0)
531                                    {
532                                         if (cnt == 256)
533                                         {
534                                              swinganginc[i] = -swinganginc[i];
535                                              swingang[i] = oldang;
536                                         }
537                                         else
538                                         {
539                                              swingang[i] = ((swingang[i]+2048-swinganginc[i])&2047);
540                                         }
541 
542                                         for (k = 1; k <= 3; k++)
543                                         {
544                                             vec2_t pivot;
545                                             pivot.x = swingx[i][0]; pivot.y = swingy[i][0];
546                                             vec2_t p;
547                                             p.x = swingx[i][k]; p.y = swingy[i][k];
548                                             vec2_t p2;
549                                             rotatepoint(pivot, p, swingang[i], &p2);
550                                             wall[swingwall[i][k]].x = p2.x;
551                                             wall[swingwall[i][k]].y = p2.y;
552                                         }
553 
554                                         if (swingang[i] == swingangclosed[i])
555                                         {
556                                              swinganginc[i] = 0;
557                                              break;
558                                         }
559                                         if (swingang[i] == swingangopen[i])
560                                         {
561                                              swinganginc[i] = 0;
562                                              break;
563                                         }
564                                         cnt--;
565                                    }
566                               } while ((good == 0) && (cnt > 0));
567                          }
568                }
569 
570           }
571      }
572 
573      for(i=0;i<revolvecnt;i++)
574      {
575           startwall = sector[revolvesector[i]].wallptr;
576           endwall = startwall + sector[revolvesector[i]].wallnum - 1;
577 
578           revolveang[i] = ((revolveang[i]+2048-(TICSPERFRAME<<2))&2047);
579           for(k=startwall;k<=endwall;k++)
580           {
581               vec2_t pivot;
582               pivot.x = revolvepivotx[i]; pivot.y = revolvepivoty[i];
583               vec2_t p;
584               p.x = revolvex[i][k - startwall];
585               p.y = revolvey[i][k - startwall];
586               vec2_t p2;
587                rotatepoint(pivot,p,revolveang[i],&p2);
588                dax = p2.x; day = p2.y;
589                dragpoint(k,dax,day, 0);
590           }
591      }
592 
593      for(i=0;i<subwaytrackcnt;i++)
594      {
595           if( subwaysound[i] == -1 ) {
596                subwaysound[i]=playsound(S_SUBWAYLOOP,subwayx[i],subwaytracky1[i],-1,ST_VEHUPDATE);
597           }
598           else {
599                updatevehiclesnds(subwaysound[i],subwayx[i],subwaytracky1[i]);
600           }
601 
602           dasector = subwaytracksector[i][0];
603           startwall = sector[dasector].wallptr;
604           endwall = startwall+sector[dasector].wallnum-1;
605           for(k=startwall;k<=endwall;k++)
606           {
607                if (wall[k].x > subwaytrackx1[i])
608                     if (wall[k].y > subwaytracky1[i])
609                          if (wall[k].x < subwaytrackx2[i])
610                               if (wall[k].y < subwaytracky2[i])
611                                    wall[k].x += (subwayvel[i]&0xfffffffc);
612           }
613 
614           for(j=1;j<subwaynumsectors[i];j++)
615           {
616                dasector = subwaytracksector[i][j];
617 
618                startwall = sector[dasector].wallptr;
619                endwall = startwall+sector[dasector].wallnum-1;
620                for(k=startwall;k<=endwall;k++)
621                     wall[k].x += (subwayvel[i]&0xfffffffc);
622 
623                s = headspritesect[dasector];
624                while (s != -1)
625                {
626                     k = nextspritesect[s];
627                     sprite[s].x += (subwayvel[i]&0xfffffffc);
628                     s = k;
629                }
630           }
631 
632           for(p=connecthead;p>=0;p=connectpoint2[p])
633                if (cursectnum[p] != subwaytracksector[i][0])
634                     if (sector[cursectnum[p]].floorz != sector[subwaytracksector[i][0]].floorz)
635                          if (posx[p] > subwaytrackx1[i])
636                               if (posy[p] > subwaytracky1[i])
637                                    if (posx[p] < subwaytrackx2[i])
638                                         if (posy[p] < subwaytracky2[i])
639                                         {
640                                              posx[p] += (subwayvel[i]&0xfffffffc);
641 
642                                                   //Update sprite representation of player
643                                              vec3_t pos;
644                                              pos.x = posx[p]; pos.y = posy[p]; pos.z = posz[p]+(KENSPLAYERHEIGHT << 8);
645                                              setsprite(playersprite[p],&pos);
646                                              sprite[playersprite[p]].ang = ang[p];
647                                              frameinterpolate = 0;
648                                         }
649 
650           subwayx[i] += (subwayvel[i]&0xfffffffc);
651 
652           k = subwaystop[i][subwaygoalstop[i]] - subwayx[i];
653           if( k > 0 ) {
654                if( k > 2048 ) {
655                     if( subwayvel[i] == 12 ) {
656                          playsound(S_SUBWAYSTART,subwayx[0],subwaytracky1[0],0,ST_UNIQUE | ST_NOUPDATE);
657                     }
658                     if (subwayvel[i] < 128) subwayvel[i]++;
659                }
660                else {
661                     if( subwayvel[i] == 32 ) {
662                          playsound(S_SUBWAYSTOP,subwayx[0],subwaytracky1[0],0,ST_UNIQUE | ST_NOUPDATE);
663                     }
664                     subwayvel[i] = (k>>4)+1;
665                }
666           }
667           else if( k < 0 ) {
668                if( k < -2048 ) {
669                     if( subwayvel[i] == -12 ) {
670                          playsound(S_SUBWAYSTART,subwayx[0],subwaytracky1[0],0,ST_UNIQUE | ST_NOUPDATE);
671                     }
672                     if (subwayvel[i] > -128) subwayvel[i]--;
673                }
674                else {
675                     if( subwayvel[i] == -32) {
676                          playsound(S_SUBWAYSTOP,subwayx[0],subwaytracky1[0],0,ST_UNIQUE | ST_NOUPDATE);
677                     }
678                     subwayvel[i] = ((k>>4)-1);
679                }
680           }
681 
682           if (((subwayvel[i]>>2) == 0) && (labs(k) < 2048))
683           {
684                if (subwaypausetime[i] == 720)
685                {
686                     for(j=1;j<subwaynumsectors[i];j++)   //Open all subway doors
687                     {
688                          dasector = subwaytracksector[i][j];
689                          if (sector[dasector].lotag == 17)
690                          {
691                               sector[dasector].lotag = 16;
692                               playsound(S_BIGSWINGCL,subwayx[i],subwaytracky1[i],0,ST_NOUPDATE | ST_UNIQUE);
693                               operatesector(dasector);
694                               sector[dasector].lotag = 17;
695                          }
696                     }
697                }
698                if ((subwaypausetime[i] >= 120) && (subwaypausetime[i]-TICSPERFRAME < 120))
699                {
700                     for(j=1;j<subwaynumsectors[i];j++)   //Close all subway doors
701                     {
702                          dasector = subwaytracksector[i][j];
703                          if (sector[dasector].lotag == 17)
704                          {
705                               sector[dasector].lotag = 16;
706                               playsound(S_BIGSWINGCL,subwayx[i],subwaytracky1[i],0,ST_NOUPDATE | ST_UNIQUE);
707                               operatesector(dasector);
708                               sector[dasector].lotag = 17;
709                          }
710                     }
711                }
712 
713                subwaypausetime[i] -= TICSPERFRAME;
714                if (subwaypausetime[i] < 0)
715                {
716                     subwaypausetime[i] = 720;
717                     if( subwaygoalstop[i] == (subwaystopcnt[i]-1) ) {
718                          subwaystopdir[i]=-1;
719                          subwaygoalstop[i]=subwaystopcnt[i]-2;
720                     }
721                     else if( subwaygoalstop[i] == 0 ) {
722                          subwaygoalstop[i]=1;
723                          subwaystopdir[i]= 1;
724                     }
725                     else {
726                          subwaygoalstop[i]+=subwaystopdir[i];
727                     }
728                }
729           }
730      }
731 
732      tektagcode();
733 }
734 
735 int
testneighborsectors(short sect1,short sect2)736 testneighborsectors(short sect1, short sect2)
737 {
738      short i, startwall, num1, num2;
739 
740      num1 = sector[sect1].wallnum;
741      num2 = sector[sect2].wallnum;
742 
743      // traverse walls of sector with fewest walls (for speed)
744      if( num1 < num2 ) {
745           startwall = sector[sect1].wallptr;
746           for(i=num1-1;i>=0;i--)
747                if (wall[i+startwall].nextsector == sect2)
748                     return(1);
749      }
750      else {
751           startwall = sector[sect2].wallptr;
752           for(i=num2-1;i>=0;i--)
753                if (wall[i+startwall].nextsector == sect1)
754                     return(1);
755      }
756      return(0);
757 }
758 
759 void
tekpreptags()760 tekpreptags()
761 {
762      int       angle,i,j,k,n,s,w1,w2,w3,w4;
763      int      dax,day,endwall,startwall,x1,x2,y1,y2;
764      short     killwcnt;
765      unsigned  int      effect;
766      spritetype *spr;
767 
768      totalmapsndfx=0;
769      secnt=0;
770      memset(sexref,0,sizeof(int)*MAXSECTORS);
771 
772      for (j=0 ; j < MAXSECTORS ; j++) {
773           memset(&sectoreffect[j],0,sizeof(struct sectoreffect));
774           sectoreffect[j].warpto=-1;
775           if (septrlist[j] != NULL) {
776                septrlist[j]=NULL;
777           }
778           if (evptrlist[j] != NULL) {
779                memset(evptrlist[j],0,sizeof(struct elevatortype));
780                evptrlist[j]=NULL;
781           }
782      }
783      for (j=0 ; j < MAXDOORS ; j++) {
784           doorptr[j]=&doortype[j];
785           memset(doorptr[j],0,sizeof(struct doortype));
786      }
787      numfloordoors=0;
788      for (j=0 ; j < MAXSECTORS ; j++) {
789           fdxref[j]=-1;
790      }
791      for (j=0 ; j < MAXFLOORDOORS ; j++) {
792           floordoorptr[j]=&floordoor[j];
793           memset(floordoorptr[j],0,sizeof(struct floordoor));
794      }
795      for (j=0 ; j < MAXSPRITEELEVS ; j++) {
796           sprelevptr[j]=&spriteelev[j];
797           memset(&spriteelev[j],0,sizeof(struct spriteelev));
798      }
799      for (j=0 ; j < MAXMAPSOUNDFX ; j++) {
800           mapsndfxptr[j]=&mapsndfx[j];
801           memset(mapsndfxptr[j], 0, sizeof(struct mapsndfxtype));
802      }
803      numvehicles=0;
804      for (j=0 ; j < MAXSECTORVEHICLES ; j++) {
805           sectvehptr[j]=&sectorvehicle[j];
806           memset(sectvehptr[j],0,sizeof(struct sectorvehicle));
807           sectvehptr[j]->soundindex=-1;
808      }
809 
810      numdoors=0;
811      for (j=0 ; j < numsectors ; j++) {
812           if (sectptr[j]->ceilingpal != 0) {
813                startwall=sectptr[j]->wallptr;
814                endwall=startwall+sectptr[j]->wallnum-1;
815                for (i=startwall ; i <= endwall ; i++) {
816                     wallptr[i]->pal=sectptr[j]->ceilingpal;
817                }
818           }
819           switch (sectptr[j]->lotag) {
820           case DOORUPTAG:
821           case DOORDOWNTAG:
822           case DOORSPLITHOR:
823           case DOORSPLITVER:
824           case PLATFORMELEVTAG:
825           case PLATFORMDELAYTAG:
826           case BOXELEVTAG:
827           case BOXDELAYTAG:
828           case PLATFORMDROPTAG:
829                if (sectptr[j]->lotag == BOXDELAYTAG
830                          || sectptr[j]->lotag == PLATFORMDELAYTAG) {
831                     evptrlist[j]=&elevator[j];
832                     k=nextsectorneighborz(j,sectptr[j]->floorz,1,1);
833                     evptrlist[j]->hilevel=sectptr[j]->floorz;
834                     evptrlist[j]->lolevel=sectptr[k]->floorz;
835                }
836                n=numdoors++;
837                if (numdoors >= MAXDOORS) {
838                     break;
839                }
840                switch (sectptr[j]->lotag) {
841                case DOORUPTAG:
842                case DOORDOWNTAG:
843                case DOORSPLITHOR:
844                     doorptr[n]->step=DOORSPEED;
845                     break;
846                case DOORSPLITVER:
847                     doorptr[n]->step=4L;
848                     break;
849                case PLATFORMELEVTAG:
850                case PLATFORMDELAYTAG:
851                case BOXELEVTAG:
852                case BOXDELAYTAG:
853                case PLATFORMDROPTAG:
854                     doorptr[n]->step=ELEVSPEED;
855                     break;
856                }
857                doorptr[n]->centx=doorptr[n]->centy=0L;
858                startwall=sectptr[j]->wallptr;
859                endwall=startwall+sectptr[j]->wallnum-1;
860                for (k=0,i=startwall ; i <= endwall ; i++) {
861                     if (wallptr[i]->lotag == 6 && k < 8) {
862                          doorptr[n]->walls[k]=i;
863                          doorptr[n]->walls[k+1]=i+1;
864                          doorptr[n]->walls[k+2]=i+2;
865                          doorptr[n]->walls[k+3]=i-1;
866                          dax=wallptr[doorptr[n]->walls[k]]->x;
867                          if (wallptr[doorptr[n]->walls[k+3]]->x == dax) {
868                               day=wallptr[i+2]->y;
869                               doorptr[n]->points[k/2]=day;
870                               day=wallptr[wallptr[i+2]->point2]->y;
871                               doorptr[n]->points[(k/2)+1]=day;
872                          }
873                          else {
874                               dax=wallptr[i+2]->x;
875                               doorptr[n]->points[k/2]=dax;
876                               dax=wallptr[wallptr[i+2]->point2]->x;
877                               doorptr[n]->points[(k/2)+1]=dax;
878                          }
879                          k+=4;
880                     }
881                     doorptr[n]->centx+=wallptr[i]->x;
882                     doorptr[n]->centy+=wallptr[i]->y;
883                }
884                doorptr[n]->centx/=(endwall-startwall+1);
885                doorptr[n]->centy/=(endwall-startwall+1);
886                doorptr[n]->centz=(sectptr[j]->ceilingz+sectptr[j]->floorz)/2;
887                doorptr[n]->type=sectptr[j]->lotag;
888                doorptr[n]->sector=j;
889                doorxref[j]=n;
890                break;
891           case DOORFLOORTAG:
892                k=fdxref[j]=numfloordoors++;
893                floordoorptr[k]->state=DOORCLOSED;
894                floordoorptr[k]->sectnum=i;
895                startwall=sectptr[j]->wallptr;
896                endwall=startwall+sectptr[j]->wallnum-1;
897                for (i=startwall ; i <= endwall ; i++) {
898                     if (wallptr[i]->lotag == 6) {
899                          if (floordoorptr[k]->wall1 == 0) {
900                               w1=floordoorptr[k]->wall1=i;
901                               w2=wallptr[w1]->point2;
902                          }
903                          else {
904                               w3=floordoorptr[k]->wall2=i;
905                               w4=wallptr[w3]->point2;
906                          }
907                     }
908                }
909                x1=wallptr[w1]->x;       // close the doors all the way
910                y1=wallptr[w1]->y;
911                x2=wallptr[w4]->x;
912                y2=wallptr[w4]->y;
913                dragpoint(w1,(x1+x2)/2,(y1+y2)/2, 0);
914                if (x1 != x2) {
915                     if (x1 < x2) {
916                          dragpoint(w4,(x1+x2)/2+1,(y1+y2)/2, 0);
917                          floordoorptr[k]->dir=3;
918                     }
919                     else {
920                          dragpoint(w4,(x1+x2)/2-1,(y1+y2)/2, 0);
921                          floordoorptr[k]->dir=1;
922                     }
923                     x1=wallptr[w1]->x;
924                     w1=wallptr[wallptr[wallptr[w1]->nextwall]->point2]->point2;
925                     floordoorptr[k]->dist1=abs(x1-wallptr[w1]->x)-50;
926                }
927                else if (y1 != y2) {
928                     if (y1 < y2) {
929                          dragpoint(w4,(x1+x2)/2,(y1+y2)/2+1, 0);
930                          floordoorptr[k]->dir=0;
931                     }
932                     else {
933                          dragpoint(w4,(x1+x2)/2,(y1+y2)/2-1, 0);
934                          floordoorptr[k]->dir=2;
935                     }
936                     y1=wallptr[w1]->y;
937                     w1=wallptr[wallptr[wallptr[w1]->nextwall]->point2]->point2;
938                     floordoorptr[k]->dist1=abs(y1-wallptr[w1]->y)-50;
939                }
940                x1=wallptr[w2]->x;
941                y1=wallptr[w2]->y;
942                x2=wallptr[w3]->x;
943                y2=wallptr[w3]->y;
944                dragpoint(w2,(x1+x2)/2,(y1+y2)/2, 0);
945                if (x1 != x2) {
946                     if (x1 < x2) {
947                          dragpoint(w3,(x1+x2)/2+1,(y1+y2)/2, 0);
948                     }
949                     else {
950                          dragpoint(w3,(x1+x2)/2-1,(y1+y2)/2, 0);
951                     }
952                     x1=wallptr[w2]->x;
953                     w2=wallptr[wallptr[wallptr[w2]->nextwall]->point2]->point2;
954                     floordoorptr[k]->dist2=abs(x1-wallptr[w2]->x)-50;
955                }
956                else if (y1 != y2) {
957                     if (y1 < y2) {
958                          dragpoint(w3,(x1+x2)/2,(y1+y2)/2+1, 0);
959                     }
960                     else {
961                          dragpoint(w3,(x1+x2)/2,(y1+y2)/2-1, 0);
962                     }
963                     y1=wallptr[w2]->y;
964                     w2=wallptr[wallptr[wallptr[w2]->nextwall]->point2]->point2;
965                     floordoorptr[k]->dist2=abs(y1-wallptr[w2]->y)-50;
966                }
967                break;
968           default:
969                break;
970           }
971           if (sectptr[j]->hitag >= SECTORVEHICLETAG &&
972              sectptr[j]->hitag < SECTORVEHICLETAG+MAXSECTORVEHICLES) {
973                k=sectptr[j]->hitag-SECTORVEHICLETAG;
974                if (sectvehptr[k]->pivotx == 0 && sectvehptr[k]->pivoty == 0) {
975                     numvehicles++;
976                     for (i=0 ; i < MAXSPRITES ; i++) {
977                          spr=sprptr[i];
978                          if (spr->lotag == sectptr[j]->hitag
979                             && spr->hitag == sectptr[j]->hitag) {
980                               sectvehptr[k]->pivotx=spr->x;
981                               sectvehptr[k]->pivoty=spr->y;
982                               jsdeletesprite(i);
983                               break;
984                          }
985                     }
986                }
987                x1=sectvehptr[k]->pivotx;
988                y1=sectvehptr[k]->pivoty;
989                n=sectvehptr[k]->numpoints;
990                startwall=sectptr[j]->wallptr;
991                endwall=startwall+sectptr[j]->wallnum-1;
992                killwcnt=0;
993                for (i=startwall ; i <= endwall ; i++) {
994                     if (wallptr[i]->lotag == 6) {
995                          sectvehptr[k]->killw[killwcnt++]=i;
996                     }
997                     sectvehptr[k]->point[n]=i;
998                     sectvehptr[k]->pointx[n]=x1-wallptr[i]->x;
999                     sectvehptr[k]->pointy[n]=y1-wallptr[i]->y;
1000                     n++;
1001                     if (n >= MAXVEHICLEPOINTS) {
1002                          crash("tekprepareboard: vehicle #%d has too "
1003                               "many points",sectptr[j]->hitag);
1004                     }
1005                }
1006                sectvehptr[k]->numpoints=n;
1007                n=sectvehptr[k]->numsectors++;
1008                sectvehptr[k]->sector[n]=j;
1009                sectvehptr[k]->soundindex=-1;
1010           }
1011      }
1012 
1013      sprelevcnt=0;
1014      for (i=0 ; i < MAXSPRITES ; i++) {
1015           spr=sprptr[i];
1016           if (spr->statnum < MAXSTATUS) {
1017                switch (spr->picnum) {
1018                case SNDFX_SECTOR:
1019                case SNDFX_AMBIENT:
1020                case SNDFX_TOGGLED:
1021                     if( totalmapsndfx == MAXMAPSOUNDFX ) {
1022                          jsdeletesprite(i);
1023                          break;
1024                     }
1025                     mapsndfxptr[totalmapsndfx]->x=sprite[i].x;
1026                     mapsndfxptr[totalmapsndfx]->y=sprite[i].y;
1027                     mapsndfxptr[totalmapsndfx]->sector=sprite[i].sectnum;
1028                     mapsndfxptr[totalmapsndfx]->snum=sprite[i].lotag;
1029                     mapsndfxptr[totalmapsndfx]->id=-1;
1030                     if( mapsndfxptr[totalmapsndfx]->snum > TOTALSOUNDS ) {
1031                          mapsndfxptr[totalmapsndfx]->snum=(TOTALSOUNDS-1);
1032                     }
1033                     mapsndfxptr[totalmapsndfx]->loops=sprite[i].hitag-1;
1034                     switch( spr->picnum ) {
1035                     case SNDFX_AMBIENT:
1036                          mapsndfxptr[totalmapsndfx]->type=MAP_SFX_AMBIENT;
1037                          break;
1038                     case SNDFX_SECTOR:
1039                          mapsndfxptr[totalmapsndfx]->type=MAP_SFX_SECTOR;
1040                          break;
1041                     case SNDFX_TOGGLED:
1042                          mapsndfxptr[totalmapsndfx]->type=MAP_SFX_TOGGLED;
1043                          break;
1044                     }
1045                     totalmapsndfx++;
1046                     jsdeletesprite(i);
1047                     break;
1048                case SECTOREFFECT:
1049                     if (spr->lotag < 1000) {
1050                          continue;
1051                     }
1052                     s=spr->sectnum;
1053                     septrlist[s]=&sectoreffect[s];
1054                     if (septrlist[s]->sectorflags == 0) {
1055                          s=sexref[secnt++]=spr->sectnum;
1056                          if (secnt == MAXSECTORS) {
1057                               crash("setupboard: Sector Effector limit exceeded");
1058                          }
1059                          septrlist[s]->warpto=-1;
1060                     }
1061                     effect=flags32[spr->lotag-1000];
1062                     septrlist[s]->sectorflags|=effect;
1063                     if( (effect&flags32[QUICKCLOSE]) != 0 ) {
1064                     }
1065                     else if( (effect&flags32[SOUNDON]) != 0 ) {
1066                          // match mapsndfx with same hitag
1067                          septrlist[s]->hi=spr->hitag;
1068                     }
1069                     else if( (effect&flags32[SOUNDOFF]) != 0 ) {
1070                          // match mapsndfx with same hitag
1071                          septrlist[s]->hi=spr->hitag;
1072                     }
1073                     else if ((effect&flags32[PULSELIGHT]) != 0
1074                        || (effect&flags32[FLICKERLIGHT]) != 0
1075                        || (effect&flags32[FLICKERDELAY]) != 0
1076                        || (effect&flags32[BLINKDELAY]) != 0
1077                        || (effect&flags32[STEADYLIGHT]) != 0) {
1078                          septrlist[s]->lo=sectptr[s]->floorshade;
1079                          septrlist[s]->hi=sectptr[s]->ceilingshade;
1080                          septrlist[s]->animate=1;
1081                          if (spr->hitag != 0) {
1082                               septrlist[s]->triggerable=spr->hitag;
1083                          }
1084                          else {
1085                               septrlist[s]->triggerable=0;
1086                          }
1087                          startwall=sectptr[s]->wallptr;
1088                          endwall=startwall+sectptr[s]->wallnum-1;
1089                          for (j=startwall ; j <= endwall ; j++) {
1090                               wallptr[j]->shade=sectptr[s]->floorshade;
1091                          }
1092                          sectptr[s]->ceilingshade=sectptr[s]->floorshade;
1093                     }
1094                     else if ((effect&flags32[DELAYEFFECT]) != 0) {
1095                          septrlist[s]->delay=spr->hitag;
1096                          septrlist[s]->delayreset=septrlist[s]->delay;
1097                     }
1098                     if ((effect&flags32[WPANNING]) != 0) {
1099                          angle=septrlist[s]->ang=spr->ang;
1100                          septrlist[s]->sin=(int)sintable[((angle+2048)&2047)];
1101                          septrlist[s]->cos=(int)sintable[((angle+2560)&2047)];
1102                          startwall=sectptr[s]->wallptr;
1103                          endwall=startwall+sectptr[s]->wallnum-1;
1104                          for (j=startwall ; j <= endwall ; j++) {
1105                               if (wallptr[j]->lotag == 0) {
1106                                    wallptr[j]->lotag=spr->lotag;
1107                               }
1108                          }
1109                     }
1110                     if ((effect&flags32[FPANNING]) != 0 ||
1111                                         (effect&flags32[CPANNING]) != 0) {
1112                          angle=septrlist[s]->ang=spr->ang;
1113                          septrlist[s]->sin=(int)sintable[((angle+2048)&2047)];
1114                          septrlist[s]->cos=(int)sintable[((angle+2560)&2047)];
1115                     }
1116                     if ((effect&flags32[WARPSECTOR]) != 0) {
1117                          for( j=0; j<MAXSECTORS; j++ ) {
1118                               if( sector[j].hitag == spr->hitag ) {
1119                                    septrlist[s]->warpto=j;
1120                                    j=MAXSECTORS;
1121                               }
1122                          }
1123                     }
1124                     if ((effect&flags32[KILLSECTOR]) != 0) {
1125                          if (spr->hitag == 0) {
1126                               septrlist[s]->damage=9999;
1127                          }
1128                          else {
1129                               septrlist[s]->damage=spr->hitag;
1130                          }
1131                     }
1132                     if ((effect&flags32[DOORSPEEDEFFECT]) != 0) {
1133                          doorptr[doorxref[spr->sectnum]]->step=spr->hitag;
1134                     }
1135                     // jeff added 9-20
1136                     if ((effect&flags32[DOORSUBTYPE]) != 0) {
1137                          doorptr[doorxref[spr->sectnum]]->subtype=spr->hitag;
1138                     }
1139                     jsdeletesprite(i);
1140                     break;
1141                default:
1142                     if (spr->lotag >= SECTORVEHICLETAG
1143                        && spr->lotag < SECTORVEHICLETAG+MAXSECTORVEHICLES) {
1144                          k=spr->lotag-SECTORVEHICLETAG;
1145                          n=spr->hitag;
1146                          sectvehptr[k]->trackx[n]=spr->x;
1147                          sectvehptr[k]->tracky[n]=spr->y;
1148                          if (spr->picnum == STOPPIC) {
1149                               sectvehptr[k]->stop[n]=1;
1150                               sectvehptr[k]->waitdelay=CLKIPS*8;
1151                          }
1152                          else {
1153                               sectvehptr[k]->stop[n]=0;
1154                          }
1155                          if (spr->picnum == SPEEDPIC) {
1156                               if (sectvehptr[k]->speedto == 0 && spr->hitag > 0) {
1157                                    sectvehptr[k]->speedto=spr->hitag;
1158                                    sectvehptr[k]->movespeed=sectvehptr[k]->speedto;
1159                               }
1160                               jsdeletesprite(i);
1161                               break;
1162                          }
1163                          sectvehptr[k]->tracknum++;
1164                          jsdeletesprite(i);
1165                     }
1166                     if ((spr->lotag < 2000) && (spr->lotag >= SPRITEELEVATORTAG)) {
1167                          j=spr->lotag-SPRITEELEVATORTAG;
1168                          if (spr->hitag >= 100) {
1169                               k=(spr->hitag-100)+1;
1170                               if (k >= MAXELEVFLOORS) {
1171                                    crash("setupboard: Only %d levels allowed "
1172                                         "for sprite elevators",MAXELEVFLOORS);
1173                               }
1174                               sprelevptr[j]->floorz[k]=spr->z;
1175                               sprelevptr[j]->floors++;
1176                          }
1177                          else {
1178                               k=sprelevptr[j]->parts;
1179                               sprelevptr[j]->sprnum[k]=i;
1180                               if (spr->hitag == 6 || spr->hitag == 7) {
1181                                    if (sprelevptr[j]->floorpos == 0) {
1182                                         sprelevcnt++;
1183                                    }
1184                                    sprelevptr[j]->door[sprelevptr[j]->doors]=i;
1185                                    sprelevptr[j]->floorz[0]=spr->z;
1186                                    sprelevptr[j]->floorpos=spr->z;
1187                                    sprelevptr[j]->doors++;
1188                               }
1189                               sprelevptr[j]->startz[k]=spr->z;
1190                               sprelevptr[j]->parts++;
1191                          }
1192                     }
1193                     break;
1194                }
1195           }
1196 
1197      }
1198 
1199      numanimates=0;
1200      for (j=0 ; j < MAXANIMPICS ; j++) {
1201           animpicptr[j]=&animpic[j];
1202           memset(animpicptr[j],0,sizeof(struct animpic));
1203      }
1204      numdelayfuncs=0;
1205      for (j=0 ; j < MAXDELAYFUNCTIONS ; j++) {
1206           delayfuncptr[j]=&delayfunc[j];
1207           memset(delayfuncptr[j],0,sizeof(struct delayfunc));
1208      }
1209 }
1210 
1211 void
tekoperatesector(short dasector)1212 tekoperatesector(short dasector)
1213 {
1214      short          s;
1215      int            datag,i;
1216 
1217      s=dasector;
1218      datag=sectptr[s]->lotag;
1219 
1220      switch (datag) {
1221      case BOXELEVTAG:
1222      case PLATFORMELEVTAG:
1223      case BOXDELAYTAG:
1224      case PLATFORMDELAYTAG:
1225      case DOORUPTAG:          // a door that opens up
1226      case DOORDOWNTAG:
1227      case DOORSPLITHOR:
1228      case DOORSPLITVER:
1229      case PLATFORMDROPTAG:
1230           i=doorxref[s];
1231           if (i == -1) {
1232                crash("operatesector: invalid door reference for sector %d",s);
1233           }
1234           switch (doorptr[i]->state) {
1235           case D_NOTHING:
1236           case D_CLOSING:
1237           case D_CLOSEDOOR:
1238           case D_SHUTSOUND:
1239                doorptr[i]->state=D_OPENDOOR;
1240                break;
1241           default:
1242                if (datag != PLATFORMDROPTAG) {
1243                     doorptr[i]->state=D_CLOSEDOOR;
1244                }
1245                break;
1246           }
1247           break;
1248      case DOORFLOORTAG:
1249           floordoorptr[fdxref[s]]->state=DOOROPENING;
1250           playsound(S_FLOOROPEN,0,0,0,ST_IMMEDIATE);
1251           break;
1252      }
1253 }
1254 
1255 void
warp(int * x,int * y,int * z,short * UNUSED (daang),short * dasector)1256 warp(int *x, int *y, int *z, short * UNUSED(daang), short *dasector)
1257 {
1258      short          startwall, endwall, s;
1259      int           i, j, dax, day, ox, oy;
1260 
1261      ox = *x; oy = *y;
1262 
1263      for( i=0; i<warpsectorcnt; i++ ) {
1264           if( warpsectorlist[i] == *dasector ) {
1265                j = sector[*dasector].hitag;
1266                do {
1267                     i++;
1268                     if (i >= warpsectorcnt) i = 0;
1269                } while( sector[warpsectorlist[i]].hitag != j );
1270                *dasector = warpsectorlist[i];
1271                break;
1272           }
1273      }
1274 
1275      // find center of sector
1276      startwall = sector[*dasector].wallptr;
1277      endwall = startwall+sector[*dasector].wallnum-1;
1278      dax = 0L, day = 0L;
1279      for( s=startwall; s<=endwall; s++ ) {
1280           dax += wall[s].x, day += wall[s].y;
1281           if( wall[s].nextsector >= 0 ) {
1282                i = s;
1283           }
1284      }
1285      *x = dax / (endwall-startwall+1);
1286      *y = day / (endwall-startwall+1);
1287      *z = sector[*dasector].floorz-(42<<8);
1288 
1289      updatesector(*x,*y,dasector);
1290 }
1291 
1292 void
tekwarp(int * x,int * y,int * z,short * dasector)1293 tekwarp(int *x, int *y, int *z, short *dasector)
1294 {
1295      short          startwall, endwall, s;
1296      int           i, dax, day;
1297 
1298      // find center of sector
1299      startwall = sector[*dasector].wallptr;
1300      endwall = startwall+sector[*dasector].wallnum-1;
1301      dax = 0L, day = 0L;
1302      for( s=startwall; s<=endwall; s++ ) {
1303           dax += wall[s].x, day += wall[s].y;
1304           if( wall[s].nextsector >= 0 ) {
1305                i = s;
1306           }
1307      }
1308      *x = dax / (endwall-startwall+1);
1309      *y = day / (endwall-startwall+1);
1310      *z = sector[*dasector].floorz-(42<<8);
1311 
1312      updatesector(*x,*y,dasector);
1313 }
1314 
1315 void
warpsprite(short spritenum)1316 warpsprite(short spritenum)
1317 {
1318      short dasectnum;
1319 
1320      dasectnum = sprite[spritenum].sectnum;
1321      warp(&sprite[spritenum].x,&sprite[spritenum].y,&sprite[spritenum].z,
1322           &sprite[spritenum].ang,&dasectnum);
1323      copybuf(&sprite[spritenum].x,&osprite[spritenum].x,3);
1324      changespritesect(spritenum,dasectnum);
1325 }
1326 
1327 void
teknewsector(short p)1328 teknewsector(short p)
1329 {
1330      int           i,n,nexti,s;
1331      int           sn;
1332      struct    sectoreffect   *septr;
1333 
1334      s=cursectnum[p];
1335      septr=septrlist[s];
1336 
1337      #define NEWMAPLOTAG 25
1338      if( (sector[s].lotag == NEWMAPLOTAG) && (option[4] == 0) ) {
1339           newmap(sector[s].hitag);
1340           return;
1341      }
1342 
1343      if( sectptr[cursectnum[p]]->lotag == 4 ) {
1344           playsound(S_SPLASH,posx[p],posy[p],0,ST_UPDATE);
1345      }
1346 
1347      if( septr != NULL ) {
1348           if( septr->warpto >= 0 ) {
1349                sn=playersprite[p];
1350                tekwarp(&sprite[sn].x,&sprite[sn].y,&sprite[sn].z,( short *)&(septr->warpto));
1351                copybuf(&sprite[sn].x,&osprite[sn].x,3);
1352                changespritesect(sn,septr->warpto);
1353                posx[p] = sprite[playersprite[p]].x;
1354                posy[p] = sprite[playersprite[p]].y;
1355                posz[p] = sprite[playersprite[p]].z;
1356                ang[p] = sprite[playersprite[p]].ang;
1357                cursectnum[p] = sprite[playersprite[p]].sectnum;
1358                sprite[playersprite[p]].z += (KENSPLAYERHEIGHT<<8);
1359           }
1360      }
1361 
1362      for( n=connecthead; n >= 0; n=connectpoint2[n] ) {
1363           if( (sectptr[cursectnum[n]]->lotag == 1) || (sectptr[cursectnum[n]]->lotag == 2) ) {
1364                for( i=0; i < numsectors; i++ ) {
1365                     if( sectptr[i]->hitag == sectptr[cursectnum[n]]->hitag ) {
1366                          if( (sectptr[i]->lotag != 1) && (sectptr[i]->lotag != 2) ) {
1367                               operatesector(i);
1368                           }
1369                    }
1370                }
1371                i=headspritestat[0];
1372                while( i != -1 ) {
1373                     nexti=nextspritestat[i];
1374                     if( sprptr[i]->hitag == sectptr[cursectnum[n]]->hitag ) {
1375                          operatesprite(i);
1376                     }
1377                i=nexti;
1378                }
1379           }
1380      }
1381 
1382      checkmapsndfx(p);
1383      sectortriggersprites(p);
1384 }
1385 
1386 
1387 void
tektagcode(void)1388 tektagcode(void)
1389 {
1390      int            floorz,hi,i,j,k,lo,oldang,p,r,s,tics;
1391      int           dax,dax2,day,day2,endwall,startwall;
1392      unsigned int  effect;
1393      sectortype     *sect;
1394      struct    sectoreffect   *septr;
1395 
1396      for( p=connecthead; p >= 0; p=connectpoint2[p] ) {
1397           tekanimweap((syncbits[p]>>13)&15,p);
1398           tekhealstun(p);
1399      }
1400 
1401      for( i=0; i < numdoors; i++ ) {
1402           movedoors(i);
1403      }
1404 
1405      if( option[4] == 0 ) {
1406           for( i=0; i < secnt; i++ ) {
1407                s=sexref[i];
1408               if (s < 0 || s >= numsectors) {
1409                    crash("tag1402: Invalid sector effect index (%d,e=%d)",s,i);
1410               }
1411                sect=sectptr[s];
1412                septr=septrlist[s];
1413                if( septr->triggerable != 0 ) {
1414                     continue;
1415                }
1416                effect=septr->sectorflags;
1417                if( (effect&flags32[WPANNING]) != 0 ) {
1418                     oldang=septr->ang;
1419                     tics=TICSPERFRAME;
1420                     startwall=sect->wallptr;
1421                     endwall=startwall+sect->wallnum-1;
1422                     dax=(tics*septr->cos)>>15;
1423                     day=(tics*septr->sin)>>13;
1424                     for( j=startwall; j <= endwall; j++ ) {
1425                          wallptr[j]->xpanning+=(unsigned char)dax;
1426                          wallptr[j]->ypanning-=(unsigned char)day;
1427                     }
1428                }
1429                if( (effect&flags32[FPANNING]) != 0 ) {
1430                     tics=TICSPERFRAME;
1431                     dax=(tics*septr->cos);
1432                     day=(tics*septr->sin);
1433                     j=headspritesect[s];
1434                     while( j != -1 ) {
1435                          k=nextspritesect[j];
1436                          if( sprptr[j]->owner < MAXSPRITES ) {
1437                               dax2=dax>>10;
1438                               day2=day>>10;
1439                               movesprite(j,dax2,day2,0,4<<8,4<<8,0);
1440                          }
1441                          j=k;
1442                     }
1443                     for( p=connecthead; p >= 0; p=connectpoint2[p] ) {
1444                          if( cursectnum[p] == s ) {
1445                               if( posz[p] >= (sect->floorz-(42<<8)) )
1446                               {
1447                                   vec3_t pos;
1448                                   pos.x = posx[p]; pos.y = posy[p]; pos.z = posz[p];
1449 
1450                                   clipmove(&pos, &cursectnum[p],dax<<4,day<<4,128L,4<<8,4<<8,CLIPMASK0);
1451 
1452                                   posx[p] = pos.x; posy[p] = pos.y; posz[p] = pos.z;
1453 
1454                                   pos.z += (42 << 8);
1455 
1456                                   setsprite(playersprite[p], &pos);
1457                                   revolvedoorstat[p]=1;
1458                               }
1459                          }
1460                     }
1461                     dax>>=12;
1462                     day>>=12;
1463                     sect->floorxpanning-=(unsigned char)dax;
1464                     sect->floorypanning+=(unsigned char)day;
1465                }
1466                if( (effect&flags32[CPANNING]) != 0 ) {
1467                     tics=TICSPERFRAME;
1468                     dax=(tics*septr->cos)>>12;
1469                     day=(tics*septr->sin)>>12;
1470                     sect->ceilingxpanning-=(unsigned char)dax;
1471                     sect->ceilingypanning+=(unsigned char)day;
1472                }
1473                if( (septr->delay-=TICSPERFRAME) > 0 ) {
1474                     continue;
1475                }
1476                // negative overflow here without this - jeffy
1477                if( septr->delay < 0 ) {
1478                     septr->delay=0;
1479                }
1480                septr->delay+=septr->delayreset;
1481                if( (effect&flags32[PULSELIGHT]) != 0 ) {
1482                     sect->ceilingshade+=septr->animate;
1483                     if( septr->hi > septr->lo ) {
1484                          hi=septr->hi;
1485                          lo=septr->lo;
1486                     }
1487                     else {
1488                          hi=septr->lo;
1489                          lo=septr->hi;
1490                     }
1491                     if( septr->animate < 0 ) {
1492                          if( sect->ceilingshade <= lo ) {
1493                               septr->animate=abs(septr->animate);
1494                          }
1495                     }
1496                     else {
1497                          if( sect->ceilingshade >= hi ) {
1498                               septr->animate=-septr->animate;
1499                          }
1500                     }
1501                     sect->floorshade=sect->ceilingshade;
1502                     startwall=sect->wallptr;
1503                     endwall=startwall+sect->wallnum-1;
1504                     for( j=startwall; j <= endwall; j++ ) {
1505                          wallptr[j]->shade=sect->ceilingshade;
1506                     }
1507                }
1508                else if( (effect&flags32[FLICKERLIGHT]) != 0 ) {
1509                    r=krand_intercept("TAG 1491");
1510                     if( r < 16384 ) {
1511                          sect->ceilingshade=septr->hi;
1512                     }
1513                     else if( r > 16384 ) {
1514                          sect->ceilingshade=septr->lo;
1515                     }
1516                     sect->floorshade=sect->ceilingshade;
1517                     startwall=sect->wallptr;
1518                     endwall=startwall+sect->wallnum-1;
1519                     for( j=startwall; j <= endwall; j++ ) {
1520                          wallptr[j]->shade=sect->ceilingshade;
1521                     }
1522                }
1523                else if( (effect&flags32[FLICKERDELAY]) != 0 ) {
1524                     if( sect->ceilingshade == septr->lo ) {
1525                          sect->ceilingshade=septr->hi;
1526                     }
1527                     else {
1528                          sect->ceilingshade=septr->lo;
1529                          septr->delay>>=2;
1530                     }
1531                     sect->floorshade=sect->ceilingshade;
1532                     startwall=sect->wallptr;
1533                     endwall=startwall+sect->wallnum-1;
1534                     for( j=startwall; j <= endwall; j++ ) {
1535                          wallptr[j]->shade=sect->ceilingshade;
1536                     }
1537                }
1538                else if( (effect&flags32[BLINKDELAY]) != 0 ) {
1539                     if( sect->ceilingshade == septr->lo ) {
1540                          sect->ceilingshade=septr->hi;
1541                     }
1542                     else {
1543                          sect->ceilingshade=septr->lo;
1544                     }
1545                     sect->floorshade=sect->ceilingshade;
1546                     startwall=sect->wallptr;
1547                     endwall=startwall+sect->wallnum-1;
1548                     for( j=startwall; j <= endwall; j++ ) {
1549                          wallptr[j]->shade=sect->ceilingshade;
1550                     }
1551                }
1552                if( (effect&flags32[KILLSECTOR]) != 0 ) {
1553                     floorz=sectptr[s]->floorz;
1554                     for( p=connecthead ; p >= 0 ; p=connectpoint2[p] ) {
1555                          if( cursectnum[p] == s ) {
1556                               // matrix specific check here
1557                               if( (klabs(posz[p] - floorz) < 10240) || (mission == 7) ) {
1558                                    if( (k=fdxref[s]) != -1 ) {
1559                                         if( floordoorptr[k]->state != DOORCLOSED ) {
1560                                              changehealth(p,-septr->damage);
1561                                              changescore(p,-10);
1562                                         }
1563                                    }
1564                                    else {
1565                                         if( septr->delay == septr->delayreset ) {
1566                                              changehealth(p,-septr->damage);
1567                                              changescore(p,-10);
1568                                         }
1569                                    }
1570                               }
1571                          }
1572                     }
1573                }
1574           }
1575      }
1576 
1577      if( option[4] == 0 ) {
1578           for( i=0; i < sprelevcnt; i++ ) {
1579                movesprelevs(i);
1580           }
1581           for( i=0; i < numfloordoors; i++ ) {
1582                movefloordoor(i);
1583           }
1584           for( i=0; i < numvehicles; i++ ) {
1585                movevehicles(i);
1586           }
1587      }
1588 
1589      tekdoanimpic();
1590      tekdodelayfuncs();
1591      if( (lockclock-ambupdateclock) > 120 ) {
1592           checkmapsndfx(screenpeek);
1593      }
1594 }
1595 
1596 int
stepdoor(int z,int z2,struct doortype * door,int newstate)1597 stepdoor(int z,int z2,struct doortype *door,int newstate)
1598 {
1599      if (z < z2) {
1600        z+=(door->step*TICSPERFRAME);
1601        if (z >= z2) {
1602             door->delay=DOORDELAY;
1603             door->state=newstate;
1604             z=z2;
1605        }
1606      }
1607      else if (z > z2) {
1608        z-=(door->step*TICSPERFRAME);
1609        if (z <= z2) {
1610             door->delay=DOORDELAY;
1611             door->state=newstate;
1612             z=z2;
1613        }
1614      }
1615      return(z);
1616 }
1617 
1618 void
showwall2d(int w,int onoff)1619 showwall2d(int w,int onoff)
1620 {
1621      if (onoff) {
1622           show2dwall[w>>3]|=(1<<(w&7));
1623      }
1624      else {
1625           show2dwall[w>>3]&=~(1<<(w&7));
1626      }
1627 }
1628 
1629 void
showsect2d(int s,int z)1630 showsect2d(int s,int z)
1631 {
1632      int  endwall,i,startwall;
1633 
1634      startwall=sectptr[s]->wallptr;
1635      endwall=startwall+sectptr[s]->wallnum-1;
1636      for (i=startwall ; i <= endwall ; i++) {
1637           if (wallptr[i]->nextwall != -1) {
1638                if (sectptr[wallptr[i]->nextsector]->floorz == z) {
1639                     showwall2d(i,0);
1640                     showwall2d(wallptr[i]->nextwall,0);
1641                }
1642                else {
1643                     showwall2d(i,1);
1644                     showwall2d(wallptr[i]->nextwall,1);
1645                }
1646           }
1647      }
1648 }
1649 
1650 void
showsect2dtoggle(int s,int onoff)1651 showsect2dtoggle(int s,int onoff)
1652 {
1653      int  endwall,i,startwall;
1654 
1655      startwall=sectptr[s]->wallptr;
1656      endwall=startwall+sectptr[s]->wallnum-1;
1657      for (i=startwall ; i <= endwall ; i++) {
1658           if (wallptr[i]->nextwall != -1) {
1659                showwall2d(i,onoff);
1660                showwall2d(wallptr[i]->nextwall,onoff);
1661           }
1662      }
1663 }
1664 
1665 int
sectorblocked(int s)1666 sectorblocked(int   s)
1667 {
1668      int       i,rv;
1669 
1670      rv=0;
1671 
1672      for( i=connecthead ; i >= 0 ; i=connectpoint2[i] ) {
1673           if( cursectnum[i] == s )
1674                rv=1;
1675           if( testneighborsectors(cursectnum[i], s) == 1 )
1676                rv=1;
1677      }
1678      if( headspritesect[s] != -1 )
1679           rv=1;
1680 
1681      return(rv);
1682 }
1683 
1684 void
movedoors(int d)1685 movedoors(int d)
1686 {
1687      int            hitag,i,j,s,sx;
1688      int           size,z;
1689      struct    doortype       *door;
1690      spritetype     *spr;
1691      walltype       *wall;
1692      char           stayopen;
1693 
1694      door=doorptr[d];
1695      s=door->sector;
1696 
1697      switch (door->state) {
1698 
1699      case D_NOTHING:
1700           break;
1701 
1702      case D_WAITING:
1703           stayopen=0;
1704           for( i=0 ; i < secnt ; i++ ) {
1705                sx=sexref[i];
1706                if( sx == door->sector ) {
1707                     if( ((septrlist[sx]->sectorflags)&flags32[QUICKCLOSE]) != 0) {
1708                          if( mission == 7 ) {
1709                               stayopen=1;
1710                          }
1711                          else {
1712                               door->delay=0;
1713                          }
1714                     }
1715                }
1716           }
1717           if( stayopen == 0 ) {
1718                door->delay-=TICSPERFRAME;
1719           }
1720           if( door->delay <= 0 ) {
1721                door->delay=0;
1722                if( door->type < PLATFORMELEVTAG ) {
1723                     for( i=connecthead ; i >= 0 ; i=connectpoint2[i] ) {
1724                          if( cursectnum[i] == s ) {
1725                               door->delay=DOORDELAY;
1726                               break;
1727                          }
1728                     }
1729                }
1730                if( door->delay == 0 ) {
1731                     door->state=D_CLOSEDOOR;
1732                }
1733           }
1734           break;
1735 
1736      case D_OPENDOOR:
1737           switch (door->type) {
1738           case DOORUPTAG:
1739                switch( door->subtype ) {
1740                case DST_BAYDOOR:
1741                     playsound(S_BAYDOOR_OPEN,door->centx,door->centy,0,ST_UPDATE);
1742                     if( baydoorloop == -1 ) {
1743                          baydoorloop=playsound(S_BAYDOORLOOP,door->centx,door->centy,20,ST_UNIQUE);
1744                     }
1745                     break;
1746                case DST_HYDRAULICDOOR:
1747                     playsound(S_AIRDOOR_OPEN,door->centx,door->centy,0,ST_UPDATE);
1748                     playsound(S_AIRDOOR,door->centx,door->centy,0,ST_UPDATE);
1749                     break;
1750 
1751                case DST_ELEVATORDOOR:
1752                     playsound(S_ELEVATOR_DOOR,door->centx,door->centy,0,ST_UPDATE);
1753                     break;
1754 
1755                case DST_MATRIXDOOR1:
1756                     playsound(S_MATRIX1,door->centx,door->centy,0,ST_UPDATE);
1757                     break;
1758 
1759                case DST_MATRIXDOOR2:
1760                     playsound(S_MATRIX2,door->centx,door->centy,0,ST_UPDATE);
1761                     break;
1762                case DST_MATRIXDOOR3:
1763                     playsound(S_MATRIX3,door->centx,door->centy,0,ST_UPDATE);
1764                     break;
1765                case DST_MATRIXDOOR4:
1766                     playsound(S_MATRIX4,door->centx,door->centy,0,ST_UPDATE);
1767                     break;
1768 
1769                default:
1770                     if( mission == 7 ) {
1771                          playsound(S_MATRIXDOOR2,door->centx,door->centy,0,ST_UPDATE);
1772                     }
1773                     else {
1774                          playsound(S_UPDOWNDR2_OP,door->centx,door->centy,0,ST_UPDATE);
1775                     }
1776                     break;
1777                }
1778                door->goalz[0]=sectptr[nextsectorneighborz(s,sectptr[s]->floorz,-1,-1)]->ceilingz;
1779                break;
1780           case DOORDOWNTAG:
1781                playsound(S_BIGSWINGOP,door->centx,door->centy,0,ST_UPDATE);
1782 
1783                door->goalz[0]=sectptr[nextsectorneighborz(s,sectptr[s]->ceilingz,1,1)]->floorz;
1784 
1785                break;
1786 
1787 
1788           case PLATFORMDROPTAG:
1789                door->goalz[0]=sectptr[nextsectorneighborz(s,sectptr[s]->ceilingz,1,1)]->floorz;
1790                break;
1791           case DOORSPLITHOR:
1792                if( mission == 7 ) {
1793                     playsound(S_MATRIXDOOR1,door->centx,door->centy,0,ST_UPDATE);
1794                }
1795                else {
1796                     playsound(S_WH_7,door->centx,door->centy,0,ST_UPDATE);
1797                }
1798                door->goalz[0]=sectptr[nextsectorneighborz(s,sectptr[s]->ceilingz,-1,-1)]->ceilingz;
1799                door->goalz[2]=sectptr[nextsectorneighborz(s,sectptr[s]->floorz,1,1)]->floorz;
1800                break;
1801           case DOORSPLITVER:
1802                playsound(S_SIDEDOOR1,door->centx,door->centy,0,ST_UPDATE);
1803                door->goalz[0]=door->points[0];
1804                door->goalz[1]=door->points[1];
1805                door->goalz[2]=door->points[2];
1806                door->goalz[3]=door->points[3];
1807                break;
1808           case BOXDELAYTAG:
1809           case PLATFORMDELAYTAG:
1810                playsound(S_PLATFORMSTART,door->centx,door->centy,0,ST_UPDATE);
1811                if( loopinsound == -1 ) {
1812                     loopinsound=playsound(S_PLATFORMLOOP,door->centx,door->centy,20,ST_UNIQUE);
1813                }
1814                door->goalz[0]=evptrlist[s]->lolevel;
1815                break;
1816           default:
1817                break;
1818           }
1819           door->state=D_OPENING;
1820           break;
1821 
1822      case D_CLOSEDOOR:
1823           switch (door->type) {
1824           case DOORUPTAG:
1825                switch( door->subtype ) {
1826                case DST_BAYDOOR:
1827                     playsound(S_BAYDOOR_OPEN,door->centx,door->centy,0,ST_UPDATE);
1828                     if( baydoorloop == -1 ) {
1829                          baydoorloop = playsound(S_BAYDOORLOOP,door->centx,door->centy,20,ST_UNIQUE);
1830                     }
1831                     break;
1832 
1833                case DST_HYDRAULICDOOR:
1834                     playsound(S_AIRDOOR_OPEN,door->centx,door->centy,0,ST_UPDATE);
1835                     playsound(S_AIRDOOR,door->centx,door->centy,0,ST_UPDATE);
1836                     break;
1837 
1838                case DST_ELEVATORDOOR:
1839                     playsound(S_ELEVATOR_DOOR,door->centx,door->centy,0,ST_UPDATE);
1840                     break;
1841 
1842                case DST_MATRIXDOOR1:
1843                     playsound(S_MATRIX1,door->centx,door->centy,0,ST_UPDATE);
1844                     break;
1845 
1846                case DST_MATRIXDOOR2:
1847                     playsound(S_MATRIX2,door->centx,door->centy,0,ST_UPDATE);
1848                     break;
1849                case DST_MATRIXDOOR3:
1850                     playsound(S_MATRIX3,door->centx,door->centy,0,ST_UPDATE);
1851                     break;
1852                case DST_MATRIXDOOR4:
1853                     playsound(S_MATRIX4,door->centx,door->centy,0,ST_UPDATE);
1854                     break;
1855 
1856                default:
1857                     if( mission == 7 ) {
1858                          playsound(S_MATRIXDOOR2,door->centx,door->centy,0,ST_UPDATE);
1859                     }
1860                     else {
1861                          playsound(S_UPDOWNDR2_CL,door->centx,door->centy,0,ST_UPDATE);
1862                     }
1863                     break;
1864                }
1865                door->goalz[0]=sectptr[nextsectorneighborz(s,sectptr[s]->ceilingz,1,1)]->floorz;
1866                break;
1867           case DOORDOWNTAG:
1868                playsound(S_BIGSWINGOP,door->centx,door->centy,0,ST_UPDATE);
1869                door->goalz[0]=sectptr[s]->ceilingz;
1870                break;
1871           case DOORSPLITHOR:
1872                if( mission == 7 ) {
1873                     playsound(S_MATRIXDOOR1,door->centx,door->centy,0,ST_UPDATE);
1874                }
1875                else {
1876                     playsound(S_WH_7,door->centx,door->centy,0,ST_UPDATE);
1877                }
1878                door->goalz[0]=door->centz;
1879                door->goalz[2]=door->centz;
1880                break;
1881           case DOORSPLITVER:
1882                playsound(S_SIDEDOOR2,door->centx,door->centy,0,ST_UPDATE);
1883                if( wallptr[door->walls[0]]->x == wallptr[door->walls[3]]->x ) {
1884                     door->goalz[0]=door->centy;
1885                     door->goalz[2]=door->centy;
1886                }
1887                else {
1888                     door->goalz[0]=door->centx;
1889                     door->goalz[2]=door->centx;
1890                }
1891                door->goalz[1]=door->points[0];
1892                door->goalz[3]=door->points[2];
1893                break;
1894           case BOXELEVTAG:
1895           case PLATFORMELEVTAG:
1896                door->state=D_NOTHING;
1897                break;
1898           case BOXDELAYTAG:
1899           case PLATFORMDELAYTAG:
1900                playsound(S_PLATFORMSTART,door->centx,door->centy,0,ST_UPDATE);
1901                if( loopinsound == -1 ) {
1902                     loopinsound=playsound(S_PLATFORMLOOP,door->centx,door->centy,20,ST_UNIQUE);
1903                }
1904                door->goalz[0]=evptrlist[s]->hilevel;
1905                break;
1906           default:
1907                break;
1908           }
1909           door->state=D_CLOSING;
1910           if( (hitag=sectptr[s]->hitag) > 0 ) {
1911                for( i=0 ; i < MAXSPRITES ; i++ ) {
1912                     spr=sprptr[i];
1913                     if( spr->hitag == hitag ) {
1914                          switch (spr->picnum) {
1915                          case SWITCH2ON:
1916                               spr->picnum=SWITCH2OFF;
1917                               break;
1918                          case SWITCH3ON:
1919                               spr->picnum=SWITCH3OFF;
1920                               break;
1921                          }
1922                     }
1923                }
1924                for( i=0 ; i < numwalls ; i++ ) {
1925                     wall=wallptr[i];
1926                     if( wall->hitag == hitag ) {
1927                          switch (wall->picnum) {
1928                          case SWITCH2ON:
1929                               wall->picnum=SWITCH2OFF;
1930                               break;
1931                          case SWITCH3ON:
1932                               wall->picnum=SWITCH3OFF;
1933                               break;
1934                          }
1935                     }
1936                }
1937           }
1938           break;
1939 
1940      case D_OPENING:
1941           switch (door->type) {
1942           case DOORUPTAG:
1943           case DOORDOWNTAG:
1944           case PLATFORMDROPTAG:
1945                if( door->type == DOORUPTAG ) {
1946                     z=sectptr[s]->ceilingz;
1947                }
1948                else {
1949                     z=sectptr[s]->floorz;
1950                }
1951                z=stepdoor(z,door->goalz[0],door,D_OPENSOUND);
1952                if( door->type == DOORUPTAG ) {
1953                     sectptr[s]->ceilingz=z;
1954                }
1955                else {
1956                     sectptr[s]->floorz=z;
1957                }
1958                break;
1959           case DOORSPLITHOR:
1960                z=sectptr[s]->ceilingz;
1961                z=stepdoor(z,door->goalz[0],door,D_OPENSOUND);
1962                sectptr[s]->ceilingz=z;
1963                z=sectptr[s]->floorz;
1964                z=stepdoor(z,door->goalz[2],door,D_OPENSOUND);
1965                sectptr[s]->floorz=z;
1966                break;
1967           case DOORSPLITVER:
1968                if( wallptr[door->walls[0]]->x == wallptr[door->walls[3]]->x ) {
1969                     for( i=0 ; i < 8 ; i++ ) {
1970                          j=door->walls[i];
1971                          z=wallptr[j]->y;
1972                          z=stepdoor(z,door->goalz[i>>1],door,D_OPENSOUND);
1973                          dragpoint(j,wallptr[j]->x,z, 0);
1974                     }
1975                }
1976                else {
1977                     for( i=0 ; i < 8 ; i++ ) {
1978                          j=door->walls[i];
1979                          z=wallptr[j]->x;
1980                          z=stepdoor(z,door->goalz[i>>1],door,D_OPENSOUND);
1981                          dragpoint(j,z,wallptr[j]->y, 0);
1982                     }
1983                }
1984                break;
1985           case BOXELEVTAG:
1986           case PLATFORMELEVTAG:
1987           case BOXDELAYTAG:
1988           case PLATFORMDELAYTAG:
1989                size=sectptr[s]->ceilingz-sectptr[s]->floorz;
1990                z=sectptr[s]->floorz;
1991                z=stepdoor(z,door->goalz[0],door,D_OPENSOUND);
1992                sectptr[s]->floorz=z;
1993                if( door->type == BOXDELAYTAG || door->type == BOXELEVTAG ) {
1994                     sectptr[s]->ceilingz=sectptr[s]->floorz+size;
1995                }
1996                break;
1997           default:
1998                break;
1999           }
2000           break;
2001 
2002      case D_CLOSING:
2003           switch (door->type) {
2004           case DOORUPTAG:
2005           case DOORDOWNTAG:
2006                if( door->type == DOORUPTAG ) {
2007                     z=sectptr[s]->ceilingz;
2008                }
2009                else {
2010                     z=sectptr[s]->floorz;
2011                }
2012                z=stepdoor(z,door->goalz[0],door,D_SHUTSOUND);
2013                if( door->type == DOORUPTAG ) {
2014                     sectptr[s]->ceilingz=z;
2015                }
2016                else {
2017                     sectptr[s]->floorz=z;
2018                }
2019                break;
2020           case DOORSPLITHOR:
2021                z=sectptr[s]->ceilingz;
2022                z=stepdoor(z,door->goalz[0],door,D_SHUTSOUND);
2023                sectptr[s]->ceilingz=z;
2024                z=sectptr[s]->floorz;
2025                z=stepdoor(z,door->goalz[2],door,D_SHUTSOUND);
2026                sectptr[s]->floorz=z;
2027                break;
2028           case DOORSPLITVER:
2029               i=headspritesect[s];
2030               if (i != -1) {
2031                    door->state=D_OPENDOOR;
2032               }
2033               for (i=connecthead ; i >= 0 ; i=connectpoint2[i]) {
2034                    if (inside(posx[i],posy[i],s)) {
2035                        door->state=D_OPENDOOR;
2036                    }
2037               }
2038                if( wallptr[door->walls[0]]->x == wallptr[door->walls[3]]->x ) {
2039                     for( i=0 ; i < 8 ; i++ ) {
2040                          j=door->walls[i];
2041                          z=wallptr[j]->y;
2042                          z=stepdoor(z,door->goalz[i>>1],door,D_SHUTSOUND);
2043                          dragpoint(j,wallptr[j]->x,z, 0);
2044                     }
2045                }
2046                else {
2047                     for( i=0 ; i < 8 ; i++ ) {
2048                          j=door->walls[i];
2049                          z=wallptr[j]->x;
2050                          z=stepdoor(z,door->goalz[i>>1],door,D_SHUTSOUND);
2051                          dragpoint(j,z,wallptr[j]->y, 0);
2052                     }
2053                }
2054                break;
2055           case BOXDELAYTAG:
2056           case PLATFORMDELAYTAG:
2057                size=sectptr[s]->ceilingz-sectptr[s]->floorz;
2058                z=sectptr[s]->floorz;
2059                z=stepdoor(z,door->goalz[0],door,D_SHUTSOUND);
2060                sectptr[s]->floorz=z;
2061                if( door->type == BOXDELAYTAG ) {
2062                     sectptr[s]->ceilingz=sectptr[s]->floorz+size;
2063                }
2064                break;
2065           default:
2066                break;
2067           }
2068           break;
2069 
2070      case D_OPENSOUND:
2071           switch (door->type) {
2072           case DOORUPTAG:
2073                switch( door->subtype ) {
2074                case DST_BAYDOOR:
2075                     playsound(S_BAYDOOR_CLOSE,door->centx,door->centy,0,ST_UPDATE);
2076                     if( baydoorloop>=0 ) {
2077                          stopsound(baydoorloop);
2078                          baydoorloop=-1;
2079                     }
2080                     break;
2081                case DST_HYDRAULICDOOR:
2082                     playsound(S_AIRDOOR_CLOSE,door->centx,door->centy,0,ST_UPDATE);
2083                     break;
2084 
2085 
2086                case DST_ELEVATORDOOR:
2087                case DST_MATRIXDOOR1:
2088                case DST_MATRIXDOOR2:
2089                case DST_MATRIXDOOR3:
2090                case DST_MATRIXDOOR4:
2091                     break;
2092                default:
2093                     if( mission != 7 ) {
2094                          playsound(S_DOORKLUNK,door->centx,door->centy,0,ST_UPDATE);
2095                     }
2096                     break;
2097                }
2098                door->state=D_WAITING;
2099                showsect2d(door->sector,door->goalz[0]);
2100                break;
2101 
2102           case DOORDOWNTAG:
2103                playsound(S_WH_6,door->centx,door->centy,0,ST_UPDATE);
2104                showsect2dtoggle(door->sector,0);
2105                door->state=D_WAITING;
2106                break;
2107 
2108           case BOXELEVTAG:
2109           case PLATFORMELEVTAG:
2110           case PLATFORMDROPTAG:
2111                door->state=D_WAITING;
2112                showsect2d(door->sector,door->goalz[0]);
2113                break;
2114           case PLATFORMDELAYTAG:
2115           default:
2116                if( door->type == BOXDELAYTAG || door->type == PLATFORMDELAYTAG ) {
2117                     playsound(S_PLATFORMSTOP,door->centx,door->centy,0,ST_UPDATE);
2118                     if( loopinsound >= 0 ) {
2119                          stopsound(loopinsound);
2120                          loopinsound=-1;
2121                     }
2122                     showsect2d(door->sector,door->goalz[0]);
2123                }
2124                else {
2125                     showsect2dtoggle(door->sector,0);
2126                }
2127                door->state=D_WAITING;
2128                break;
2129           }
2130           break;
2131 
2132      case D_SHUTSOUND:
2133           switch (door->type) {
2134           case DOORUPTAG:
2135                switch( door->subtype ) {
2136                case DST_BAYDOOR:
2137                     playsound(S_BAYDOOR_CLOSE,door->centx,door->centy,0,ST_UPDATE);
2138                     if( baydoorloop>=0 ) {
2139                          stopsound(baydoorloop);
2140                          baydoorloop=-1;
2141                     }
2142                     break;
2143 
2144                case DST_HYDRAULICDOOR:
2145                     playsound(S_AIRDOOR_CLOSE,door->centx,door->centy,0,ST_UPDATE);
2146                     break;
2147 
2148                case DST_ELEVATORDOOR:
2149                case DST_MATRIXDOOR1:
2150                case DST_MATRIXDOOR2:
2151                case DST_MATRIXDOOR3:
2152                case DST_MATRIXDOOR4:
2153                     break;
2154                default:
2155                     if( mission != 7 ) {
2156                          playsound(S_DOORKLUNK,door->centx,door->centy,0,ST_UPDATE);
2157                     }
2158                     break;
2159                }
2160                door->state=D_NOTHING;
2161                showsect2d(door->sector,door->goalz[0]);
2162                break;
2163 
2164           case DOORDOWNTAG:
2165                showsect2dtoggle(door->sector,1);
2166                playsound(S_WH_6,door->centx,door->centy,0,ST_UPDATE);
2167                break;
2168 
2169           case BOXELEVTAG:
2170           case PLATFORMELEVTAG:
2171           case BOXDELAYTAG:
2172           case PLATFORMDELAYTAG:
2173                playsound(S_PLATFORMSTOP,door->centx,door->centy,0,ST_UPDATE);
2174                if( loopinsound>=0 ) {
2175                     stopsound(loopinsound);
2176                     loopinsound=-1;
2177                }
2178                showsect2d(door->sector,door->goalz[0]);
2179                break;
2180           default:
2181                showsect2dtoggle(door->sector,1);
2182                break;
2183           }
2184           door->state=D_NOTHING;
2185           break;
2186      }
2187 
2188 }
2189 
2190 void
movesprelevs(int e)2191 movesprelevs(int e)
2192 {
2193      int            i,j,n,tics;
2194      int           goalz;
2195      struct    spriteelev     *s;
2196      spritetype     *spr;
2197 
2198      s=sprelevptr[e];
2199      tics=TICSPERFRAME<<6;
2200      switch (s->state) {
2201      case E_WAITING:
2202           s->delay-=TICSPERFRAME;
2203           if (s->delay <= 0) {
2204                s->state=E_CLOSINGDOOR;
2205           }
2206           return;
2207      case E_CLOSINGDOOR:
2208           s->doorpos-=tics;
2209           if (s->doorpos <= 0) {
2210                s->doorpos=0;
2211                s->state=E_NEXTFLOOR;
2212           }
2213           break;
2214      case E_OPENINGDOOR:
2215           s->doorpos+=tics;
2216           if (s->doorpos >= E_DOOROPENPOS) {
2217                s->doorpos=E_DOOROPENPOS;
2218                s->state=E_WAITING;
2219                s->delay=E_WAITDELAY;
2220           }
2221        break;
2222      case E_MOVING:
2223           goalz=s->floorz[s->curfloor];
2224           if (s->curdir == E_GOINGUP) {
2225                s->floorpos-=tics;
2226                if (s->floorpos <= goalz) {
2227                     s->floorpos+=labs(s->floorpos-goalz);
2228                     s->state=E_OPENINGDOOR;
2229                }
2230           }
2231           else {
2232                s->floorpos+=tics;
2233                if (s->floorpos >= goalz) {
2234                     s->floorpos-=labs(s->floorpos-goalz);
2235                     s->state=E_OPENINGDOOR;
2236                }
2237           }
2238           break;
2239      case E_NEXTFLOOR:
2240           if (s->curdir == E_GOINGUP) {
2241                s->curfloor++;
2242                if (s->curfloor > s->floors) {
2243                     s->curfloor-=2;
2244                     s->curdir=E_GOINGDOWN;
2245                     //playsound(S_COPSEE1,sprptr[s->sprnum[0]]->x,sprptr[s->sprnum[0]]->y,0,ST_UNIQUE);
2246                }
2247           }
2248           else if (s->curdir == E_GOINGDOWN) {
2249                s->curfloor--;
2250                if (s->curfloor < 0) {
2251                     s->curfloor+=2;
2252                     s->curdir=E_GOINGUP;
2253                     //playsound(S_COPSEE2,sprptr[s->sprnum[0]]->x,sprptr[s->sprnum[0]]->y,0,ST_UNIQUE);
2254                }
2255           }
2256           s->state=E_MOVING;
2257           break;
2258      }
2259      for (i=0 ; i < s->parts ; i++) {
2260           j=s->sprnum[i];
2261           spr=sprptr[j];
2262           spr->z=s->startz[i]+s->floorpos-s->floorz[0];
2263           for (n=0 ; n < s->doors ; n++) {
2264                if (j == s->door[n]) {
2265                     spr->z-=s->doorpos;
2266                }
2267           }
2268      }
2269 }
2270 
2271 void
movefloordoor(int d)2272 movefloordoor(int d)
2273 {
2274      int  j,s,tics;
2275      struct floordoor *dptr;
2276 
2277      tics=TICSPERFRAME<<2;
2278      dptr=floordoorptr[d];
2279      switch (dptr->state) {
2280      case DOOROPENING:
2281           if (dptr->dist1 > 0) {
2282                s=tics;
2283                dptr->dist1-=s;
2284                if (dptr->dist1 < 0) {
2285                     s+=dptr->dist1;
2286                     dptr->dist1=0;
2287                }
2288                switch (dptr->dir) {
2289                case 0:
2290                     j=dptr->wall1;
2291                     dragpoint(j,wallptr[j]->x,wallptr[j]->y-s, 0);
2292                     j=wallptr[j]->point2;
2293                     dragpoint(j,wallptr[j]->x,wallptr[j]->y-s,0 );
2294                     break;
2295                case 1:
2296                     j=dptr->wall1;
2297                     dragpoint(j,wallptr[j]->x+s,wallptr[j]->y, 0);
2298                     j=wallptr[j]->point2;
2299                     dragpoint(j,wallptr[j]->x+s,wallptr[j]->y, 0);
2300                     break;
2301                case 2:
2302                     j=dptr->wall1;
2303                     dragpoint(j,wallptr[j]->x,wallptr[j]->y+s, 0);
2304                     j=wallptr[j]->point2;
2305                     dragpoint(j,wallptr[j]->x,wallptr[j]->y+s, 0);
2306                     break;
2307                case 3:
2308                     j=dptr->wall1;
2309                     dragpoint(j,wallptr[j]->x-s,wallptr[j]->y, 0);
2310                     j=wallptr[j]->point2;
2311                     dragpoint(j,wallptr[j]->x-s,wallptr[j]->y, 0);
2312                     break;
2313                }
2314           }
2315           if (dptr->dist2 > 0) {
2316                s=tics;
2317                dptr->dist2-=s;
2318                if (dptr->dist2 < 0) {
2319                     s+=dptr->dist2;
2320                     dptr->dist2=0;
2321                }
2322                switch (dptr->dir) {
2323                case 0:
2324                     j=dptr->wall2;
2325                     dragpoint(j,wallptr[j]->x,wallptr[j]->y+s, 0);
2326                     j=wallptr[j]->point2;
2327                     dragpoint(j,wallptr[j]->x,wallptr[j]->y+s, 0);
2328                     break;
2329                case 1:
2330                     j=dptr->wall2;
2331                     dragpoint(j,wallptr[j]->x-s,wallptr[j]->y, 0);
2332                     j=wallptr[j]->point2;
2333                     dragpoint(j,wallptr[j]->x-s,wallptr[j]->y, 0);
2334                     break;
2335                case 2:
2336                     j=dptr->wall2;
2337                     dragpoint(j,wallptr[j]->x,wallptr[j]->y-s, 0);
2338                     j=wallptr[j]->point2;
2339                     dragpoint(j,wallptr[j]->x,wallptr[j]->y-s, 0);
2340                     break;
2341                case 3:
2342                     j=dptr->wall2;
2343                     dragpoint(j,wallptr[j]->x+s,wallptr[j]->y, 0);
2344                     j=wallptr[j]->point2;
2345                     dragpoint(j,wallptr[j]->x+s,wallptr[j]->y, 0);
2346                     break;
2347                }
2348           }
2349           if (dptr->dist1 <= 0 && dptr->dist2 <= 0) {
2350                dptr->state=DOOROPENED;
2351           }
2352           break;
2353      case DOORCLOSING:
2354      case DOOROPENED:
2355      case DOORCLOSED:
2356           break;
2357      }
2358 }
2359 
2360 void
clearvehiclesoundindexes()2361 clearvehiclesoundindexes()
2362 {
2363      int       i;
2364 
2365      for( i=0; i < MAXSECTORVEHICLES; i++ ) {
2366           sectvehptr[i]->soundindex=-1;
2367      }
2368 }
2369 
2370 void
movevehicles(int v)2371 movevehicles(int v)
2372 {
2373      short     a,angv,ato,angto,curang,i,n,p,rotang,s,sto,stoptrack,track;
2374      int      distx,disty,px,py,x,y;
2375      int      xvect,xvect2,yvect,yvect2;
2376      int      lox,loy,hix,hiy;
2377      short     onveh[MAXPLAYERS];
2378      struct    sectorvehicle  *vptr;
2379 
2380      vptr=sectvehptr[v];
2381 
2382      if( vptr->soundindex == -1 ) {
2383 
2384           for( i=0; i<32; i++) {        //find mapno using names array
2385                if( !(Bstrcasecmp(boardfilename,mapnames[i]) ) )
2386                     break;
2387           }
2388           switch( v ) {
2389           case 0:
2390                switch( i ) {
2391                     case 4:   //level1.map
2392                          vptr->soundindex=playsound(S_TRAMBUSLOOP,vptr->pivotx,vptr->pivoty,-1,ST_VEHUPDATE);
2393                          break;
2394                     case 8:   //city1.map
2395                          vptr->soundindex=playsound(S_TRUCKLOOP,vptr->pivotx,vptr->pivoty,-1,ST_VEHUPDATE);
2396                          break;
2397                     case 11:  //beach1.map
2398                          vptr->soundindex=playsound(S_FORKLIFTLOOP,vptr->pivotx,vptr->pivoty,-1,ST_VEHUPDATE);
2399                          break;
2400                     case 17:  //mid3.map
2401                          vptr->soundindex=playsound(S_TRAMBUSLOOP,vptr->pivotx,vptr->pivoty,-1,ST_VEHUPDATE);
2402                          break;
2403                     case 19:  //sewer2.map
2404                          vptr->soundindex=playsound(S_FORKLIFTLOOP,vptr->pivotx,vptr->pivoty,-1,ST_VEHUPDATE);
2405                          break;
2406                     case 20:   //inds1.map
2407                          vptr->soundindex=playsound(S_FORKLIFTLOOP,vptr->pivotx,vptr->pivoty,-1,ST_VEHUPDATE);
2408                          break;
2409                     case 25:  //ware1.map
2410                          vptr->soundindex=playsound(S_FORKLIFTLOOP,vptr->pivotx,vptr->pivoty,-1,ST_VEHUPDATE);
2411                          break;
2412                     case 26:   //ware2.map
2413                          vptr->soundindex=playsound(S_TRUCKLOOP,vptr->pivotx,vptr->pivoty,-1,ST_VEHUPDATE);
2414                          break;
2415                     default:
2416                          break;
2417                }
2418                break;
2419           case 1:
2420                switch( i ) {
2421                     case 4:   //level1.map
2422                          vptr->soundindex=playsound(S_TRAMBUSLOOP,vptr->pivotx,vptr->pivoty,-1,ST_VEHUPDATE);
2423                          break;
2424                     case 11:   //beach1.map
2425                          vptr->soundindex=playsound(S_BOATLOOP,vptr->pivotx,vptr->pivoty,-1,ST_VEHUPDATE);
2426                          break;
2427                     case 26:   //ware2.map
2428                          vptr->soundindex=playsound(S_CARTLOOP,vptr->pivotx,vptr->pivoty,-1,ST_VEHUPDATE);
2429                          break;
2430                     default:
2431                          break;
2432                }
2433                break;
2434           default:
2435                break;
2436           }
2437      }
2438 
2439      if( vptr->waittics > 0 ) {
2440           vptr->waittics-=TICSPERFRAME;
2441           if( vptr->soundindex != -1 ) {
2442                updatevehiclesnds(vptr->soundindex, vptr->pivotx, vptr->pivoty);
2443           }
2444           return;
2445      }
2446 
2447      px=vptr->pivotx;
2448      py=vptr->pivoty;
2449 
2450      track=vptr->track;
2451      distx=vptr->distx;
2452      disty=vptr->disty;
2453      stoptrack=vptr->stoptrack;
2454      if( vptr->stop[track] && (x=distx+disty) > 0L && x < 8192L ) {
2455           vptr->accelto=2;
2456           vptr->speedto=32;
2457      }
2458      else if( vptr->accelto != 8 ) {
2459           vptr->accelto=8;
2460           vptr->speedto=vptr->movespeed;
2461      }
2462      if( distx == 0L && disty == 0L ) {
2463           if( vptr->stop[stoptrack] ) {
2464                for( i=0 ; i < vptr->numsectors ; i++ ) {
2465                     s=vptr->sector[i];
2466                     if( sectptr[s]->lotag != 0 ) {
2467                          operatesector(s);
2468                     }
2469                }
2470                vptr->waittics=vptr->waitdelay;
2471                vptr->acceleration=0;
2472                vptr->speed=0;
2473 
2474           }
2475           distx=vptr->trackx[track]-px;
2476           disty=vptr->tracky[track]-py;
2477           vptr->angleto=getangle(distx,disty);
2478           vptr->accelto=8;
2479           vptr->distx=labs(distx);
2480           vptr->disty=labs(disty);
2481           distx=vptr->distx;
2482           disty=vptr->disty;
2483      }
2484      a=vptr->acceleration;
2485      ato=vptr->accelto;
2486      if( a < ato ) {
2487           a+=TICSPERFRAME;
2488           if( a > ato ) {
2489                a=ato;
2490           }
2491           vptr->acceleration=a;
2492      }
2493      else if( a > ato ) {
2494           a-=TICSPERFRAME;
2495           if( a < ato ) {
2496                a=ato;
2497           }
2498           vptr->acceleration=a;
2499      }
2500      s=vptr->speed;
2501      sto=vptr->speedto;
2502      if( s > sto ) {
2503           s-=a;
2504           if( s <= sto ) {
2505                s=sto;
2506           }
2507           vptr->speed=s;
2508      }
2509      else if( s < sto ) {
2510           s+=a;
2511           if( s > sto ) {
2512                s=sto;
2513           }
2514           vptr->speed=s;
2515      }
2516      rotang=curang=vptr->angle;
2517      if( curang != vptr->angleto ) {
2518           vptr->angle=vptr->angleto;
2519           curang=vptr->angle;
2520      }
2521      xvect=(s*(int)TICSPERFRAME*(int)sintable[((curang+2560)&2047)])>>3;
2522      xvect2=xvect>>13;
2523      yvect=(s*(int)TICSPERFRAME*(int)sintable[((curang+2048)&2047)])>>3;
2524      yvect2=yvect>>13;
2525      distx-=labs(xvect2);
2526      if( distx < 0L ) {
2527           if( xvect2 < 0L ) {
2528                xvect2-=distx;
2529           }
2530           else {
2531                xvect2+=distx;
2532           }
2533           distx=0L;
2534           vptr->angleto=getangle(vptr->trackx[track]-px,vptr->tracky[track]-py);
2535      }
2536      disty-=labs(yvect2);
2537      if( disty < 0L ) {
2538           if( yvect2 < 0L ) {
2539                yvect2-=disty;
2540           }
2541           else {
2542                yvect2+=disty;
2543           }
2544           disty=0L;
2545           vptr->angleto=getangle(vptr->trackx[track]-px,vptr->tracky[track]-py);
2546      }
2547      if( distx == 0L && disty == 0L ) {
2548           vptr->stoptrack=track;
2549           track=(track+1)%vptr->tracknum;
2550           vptr->track=track;
2551           switch( v ) {
2552           //jsa vehicles
2553           case 0:
2554                if( !(Bstrcasecmp(boardfilename,"CITY1.MAP")) || !(Bstrcasecmp(boardfilename,"WARE2.MAP")))
2555                     playsound(S_TRUCKSTOP,vptr->pivotx,vptr->pivoty,0,ST_AMBUPDATE);
2556                break;
2557           default:
2558                break;
2559           }
2560      }
2561      vptr->distx=distx;
2562      vptr->disty=disty;
2563      px+=xvect2;
2564      py+=yvect2;
2565      n=vptr->numpoints;
2566      for( i=0 ; i < n ; i++ )
2567      {
2568           p=vptr->point[i];
2569           x=vptr->pointx[i];
2570           y=vptr->pointy[i];
2571 
2572           vec2_t pivot;
2573           pivot.x = px;
2574           pivot.y = py;
2575           vec2_t p1;
2576           p1.x = px - x;
2577           p1.y = py - y;
2578           vec2_t p2;
2579 
2580           rotatepoint(pivot,p1,curang,&p2);
2581           x = p2.x; y = p2.y;
2582           dragpoint(p,x,y, 0);
2583      }
2584      vptr->pivotx=px;
2585      vptr->pivoty=py;
2586      rotang=((curang-rotang)+2048)&2047;
2587      n=vptr->numsectors;
2588      lox=loy=0x7FFFFFFF;
2589      hix=hiy=-(0x7FFFFFFF);
2590      for( i=0 ; i < 4 ; i++ ) {
2591           a=vptr->killw[i];
2592           if( wallptr[a]->x < lox ) {
2593                lox=wallptr[a]->x;
2594           }
2595           else if( wallptr[a]->x > hix ) {
2596                hix=wallptr[a]->x;
2597           }
2598           if( wallptr[a]->y < loy ) {
2599                loy=wallptr[a]->y;
2600           }
2601           else if (wallptr[a]->y > hiy) {
2602                hiy=wallptr[a]->y;
2603           }
2604      }
2605      memset(onveh,0,sizeof(short)*MAXPLAYERS);
2606      for( i=0 ; i < n ; i++ ) {
2607           p=headspritesect[vptr->sector[i]];
2608           while (p >= 0)
2609           {
2610                s=nextspritesect[p];
2611                x=sprptr[p]->x;
2612                y=sprptr[p]->y;
2613                x+=xvect2;
2614                y+=yvect2;
2615 
2616                vec2_t pivot;
2617                pivot.x = px; pivot.y = py;
2618                vec2_t p1;
2619                p1.x = x; p1.y = y;
2620                vec2_t p2;
2621                rotatepoint(pivot,p1,rotang,&p2);
2622                sprptr[p]->x = p2.x;
2623                sprptr[p]->y = p2.y;
2624 
2625                sprptr[p]->ang+=rotang;
2626                p=s;
2627           }
2628           for( p=connecthead ; p >= 0 ; p=connectpoint2[p] ) {
2629                x=posx[p];
2630                y=posy[p];
2631                if( cursectnum[p] == vptr->sector[i] ) {
2632                     x+=xvect2;
2633                     y+=yvect2;
2634                     vec2_t pivot;
2635                     pivot.x = px; pivot.y = py;
2636                     vec2_t p2;
2637                     p2.x = x; p2.y = y;
2638                     vec2_t pos;
2639                     rotatepoint(pivot,p2,rotang,&pos);
2640                     posx[p] = pos.x; posy[p] = pos.y;
2641                     ang[p]+=rotang;
2642                     onveh[p]=1;
2643                }
2644           }
2645      }
2646      for( p=connecthead ; p >= 0 ; p=connectpoint2[p] ) {
2647           if( onveh[p] ) {
2648                continue;
2649           }
2650           x=posx[p];
2651           y=posy[p];
2652           if( x > lox && x < hix && y > loy && y < hiy ) {
2653                if( (health[p] > 0) &&  (posz[p] > VEHICLEHEIGHT) ) {
2654                     changehealth(p,-9999);
2655                     changescore(p,-100);
2656                     if( goreflag ) {
2657                          tekexplodebody(playersprite[p]);
2658                     }
2659                }
2660           }
2661      }
2662      if( vptr->soundindex != -1 ) {
2663           updatevehiclesnds(vptr->soundindex, vptr->pivotx, vptr->pivoty);
2664      }
2665 }
2666 
2667 void                          // kick off function after specified tics elapse
teksetdelayfunc(void (* delayfunc)(short),int tics,short parm)2668 teksetdelayfunc(void (*delayfunc)(short),int tics,short parm)
2669 {
2670      int  i,n;
2671 
2672      if (delayfunc == NULL) {
2673        return;
2674      }
2675      n=numdelayfuncs;
2676      for (i=0 ; i < n ; i++) {
2677        if (delayfuncptr[i]->func == delayfunc) {
2678             if (tics == 0) {
2679               memmove(delayfuncptr[i],delayfuncptr[numdelayfuncs-1],
2680                 sizeof(struct delayfunc));
2681               memset(delayfuncptr[numdelayfuncs-1],0,
2682                 sizeof(struct delayfunc));
2683               numdelayfuncs--;
2684               return;
2685             }
2686             else {
2687               delayfuncptr[i]->tics=tics;
2688               delayfuncptr[i]->parm=parm;
2689               return;
2690             }
2691        }
2692      }
2693      delayfuncptr[numdelayfuncs]->func=delayfunc;
2694      delayfuncptr[numdelayfuncs]->tics=tics;
2695      delayfuncptr[numdelayfuncs]->parm=parm;
2696      numdelayfuncs++;
2697 }
2698 
2699 void
tekdodelayfuncs(void)2700 tekdodelayfuncs(void)
2701 {
2702      int  i,n,p;
2703 
2704      n=numdelayfuncs;
2705      for (i=0 ; i < n ; i++) {
2706           if (delayfuncptr[i]->func == NULL) {
2707                continue;
2708           }
2709           delayfuncptr[i]->tics-=TICSPERFRAME;
2710           if (delayfuncptr[i]->tics <= 0) {
2711                p=delayfuncptr[i]->parm;
2712                (*delayfuncptr[i]->func)(p);
2713                memmove(delayfuncptr[i],delayfuncptr[numdelayfuncs-1],
2714                     sizeof(struct delayfunc));
2715                     memset(delayfuncptr[numdelayfuncs-1],0,
2716                     sizeof(struct delayfunc));
2717                numdelayfuncs--;
2718           }
2719      }
2720 }
2721 
2722 void
setanimpic(short * pic,short tics,short frames)2723 setanimpic(short *pic,short tics,short frames)
2724 {
2725      int  i;
2726 
2727      for (i=0 ; i < numanimates ; i++) {
2728           if (animpicptr[i]->pic == pic) {
2729                return;
2730           }
2731      }
2732      if (numanimates+1 < MAXANIMPICS) {
2733           animpicptr[numanimates]->pic=pic;
2734           animpicptr[numanimates]->tics=tics;
2735           animpicptr[numanimates]->frames=frames;
2736           animpicptr[numanimates]->nextclock=lockclock+tics;
2737           numanimates++;
2738      }
2739 }
2740 
2741 void
tekdoanimpic(void)2742 tekdoanimpic(void)
2743 {
2744      short pic;
2745      int  i,n;
2746 
2747      n=numanimates;
2748      for (i=0 ; i < n ; i++) {
2749           if (lockclock < animpicptr[i]->nextclock) {
2750                continue;
2751           }
2752           if (animpicptr[i]->frames > 0) {
2753                if (--animpicptr[i]->frames > 0) {
2754                     pic=*animpicptr[i]->pic;
2755                     pic++;
2756                     *animpicptr[i]->pic=pic;
2757                     animpicptr[i]->nextclock=lockclock+animpicptr[i]->tics;
2758                }
2759           }
2760           else if (animpicptr[i]->frames < 0) {
2761                if (++animpicptr[i]->frames < 0) {
2762                     pic=*animpicptr[i]->pic;
2763                     pic--;
2764                     *animpicptr[i]->pic=pic;
2765                     animpicptr[i]->nextclock=lockclock+animpicptr[i]->tics;
2766                }
2767           }
2768           else {
2769                numanimates--;
2770                if (numanimates > 0) {
2771                     memmove(animpicptr[i],animpicptr[numanimates],
2772                          sizeof(struct animpic));
2773                     memset(animpicptr[numanimates],0,sizeof(struct animpic));
2774                }
2775           }
2776      }
2777 }
2778 
2779 void
checkmapsndfx(short p)2780 checkmapsndfx(short p)
2781 {
2782 
2783      int       i,s;
2784      int       dist;
2785      unsigned  int      effect;
2786      struct    sectoreffect   *septr;
2787 
2788      s=cursectnum[p];
2789      septr=septrlist[s];
2790 
2791      for( i=0; i<totalmapsndfx; i++ ) {
2792           switch(mapsndfxptr[i]->type) {
2793           case MAP_SFX_AMBIENT:
2794                dist=labs(posx[p]-mapsndfxptr[i]->x)+labs(posy[p]-mapsndfxptr[i]->y);
2795                if( (dist > AMBUPDATEDIST) && (mapsndfxptr[i]->id!=-1) ) {
2796                     stopsound(mapsndfxptr[i]->id);
2797                     mapsndfxptr[i]->id=-1;
2798                }
2799                else if( (dist < AMBUPDATEDIST) && (mapsndfxptr[i]->id==-1) )  {
2800                     mapsndfxptr[i]->id=playsound(mapsndfxptr[i]->snum, mapsndfxptr[i]->x,mapsndfxptr[i]->y, mapsndfxptr[i]->loops, ST_AMBUPDATE);
2801                }
2802                break;
2803           case MAP_SFX_SECTOR:
2804                if((cursectnum[p] != ocursectnum[p]) && (cursectnum[p] == mapsndfxptr[i]->sector) ) {
2805                    mapsndfxptr[i]->id=playsound(mapsndfxptr[i]->snum, mapsndfxptr[i]->x,mapsndfxptr[i]->y, mapsndfxptr[i]->loops, ST_UNIQUE);
2806                }
2807                break;
2808           default:
2809                break;
2810           }
2811      }
2812 
2813      if( !Bstrncasecmp("SUBWAY",boardfilename,6) ) {
2814           if( ambsubloop == -1 ) {
2815                ambsubloop=playsound(S_SUBSTATIONLOOP, 0, 0, -1, ST_IMMEDIATE);
2816           }
2817      }
2818      else {
2819           if( ambsubloop != -1 ) {
2820                stopsound(ambsubloop);
2821                ambsubloop=-1;
2822           }
2823      }
2824 
2825      if( septr != NULL ) {
2826           effect=septr->sectorflags;
2827           if( (effect&flags32[SOUNDON]) != 0 ) {
2828                for( i=0; i<totalmapsndfx; i++ ) {
2829                     if( mapsndfxptr[i]->type == MAP_SFX_TOGGLED ) {
2830                          if( sectptr[mapsndfxptr[i]->sector]->hitag == septr->hi ) {
2831                               if( mapsndfxptr[i]->id == -1 ) {
2832                                    mapsndfxptr[i]->id=playsound(mapsndfxptr[i]->snum, mapsndfxptr[i]->x,mapsndfxptr[i]->y, mapsndfxptr[i]->loops,ST_UNIQUE | ST_IMMEDIATE);;
2833                               }
2834                          }
2835                     }
2836                }
2837           }
2838           if( (effect&flags32[SOUNDOFF]) != 0 ) {
2839                for( i=0; i<totalmapsndfx; i++ ) {
2840                     if( mapsndfxptr[i]->type == MAP_SFX_TOGGLED ) {
2841                          if( sectptr[mapsndfxptr[i]->sector]->hitag == septr->hi ) {
2842                               if( mapsndfxptr[i]->id != -1 ) {
2843                                    stopsound(mapsndfxptr[i]->id);
2844                                    mapsndfxptr[i]->id=-1;
2845                               }
2846                          }
2847                     }
2848                }
2849           }
2850      }
2851 
2852 //     ambupdateclock=totalclock;
2853      ambupdateclock=lockclock;
2854 }
2855 
2856 void
tektagsave(int fil)2857 tektagsave(int fil)
2858 {
2859      int  i,rv;
2860 
2861      rv=write(fil,&numanimates,sizeof(int));
2862      for (i=0 ; i < numanimates ; i++) {
2863           write(fil,&animpic[i],sizeof(struct animpic));
2864      }
2865      rv=write(fil,&numdelayfuncs,sizeof(short));
2866      for (i=0 ; i < numdelayfuncs ; i++) {
2867           write(fil,&delayfunc[i],sizeof(struct delayfunc));
2868      }
2869      rv=write(fil,onelev,MAXPLAYERS);
2870      rv=write(fil,&secnt,sizeof(int));
2871      for (i=0 ; i < secnt ; i++) {
2872           write(fil,&sectoreffect[i],sizeof(struct sectoreffect));
2873      }
2874      rv=write(fil,sexref,MAXSECTORS*sizeof(int));
2875      rv=write(fil,&numdoors,sizeof(int));
2876      for (i=0 ; i < numdoors ; i++) {
2877           write(fil,&doortype[i],sizeof(struct doortype));
2878      }
2879      write(fil,&numfloordoors,sizeof(int));
2880      for (i=0 ; i < numfloordoors ; i++) {
2881           write(fil,&floordoor[i],sizeof(struct floordoor));
2882      }
2883      write(fil,fdxref,MAXSECTORS*sizeof(int));
2884      write(fil,&numvehicles,sizeof(int));
2885      for (i=0 ; i < numvehicles ; i++) {
2886           write(fil,&sectorvehicle[i],sizeof(struct sectorvehicle));
2887      }
2888      write(fil,elevator,MAXSECTORS*sizeof(struct elevatortype));
2889      write(fil,&sprelevcnt,sizeof(int));
2890      for (i=0 ; i < sprelevcnt ; i++) {
2891           write(fil,&spriteelev[i],sizeof(struct spriteelev));
2892      }
2893      write(fil,&totalmapsndfx,sizeof(int));
2894      for (i=0 ; i < totalmapsndfx ; i++) {
2895           write(fil,&mapsndfx[i],sizeof(struct mapsndfxtype));
2896      }
2897 }
2898 
2899 void
tektagload(int fil)2900 tektagload(int fil)
2901 {
2902      int  i,rv;
2903 
2904      rv=read(fil,&numanimates,sizeof(int));
2905      for (i=0 ; i < numanimates ; i++) {
2906           read(fil,&animpic[i],sizeof(struct animpic));
2907      }
2908      rv=read(fil,&numdelayfuncs,sizeof(short));
2909      for (i=0 ; i < numdelayfuncs ; i++) {
2910           read(fil,&delayfunc[i],sizeof(struct delayfunc));
2911      }
2912      rv=read(fil,onelev,MAXPLAYERS);
2913      rv=read(fil,&secnt,sizeof(int));
2914      for (i=0 ; i < secnt ; i++) {
2915           read(fil,&sectoreffect[i],sizeof(struct sectoreffect));
2916      }
2917      rv=read(fil,sexref,MAXSECTORS*sizeof(int));
2918      rv=read(fil,&numdoors,sizeof(int));
2919      for (i=0 ; i < numdoors ; i++) {
2920           read(fil,&doortype[i],sizeof(struct doortype));
2921      }
2922      read(fil,&numfloordoors,sizeof(int));
2923      for (i=0 ; i < numfloordoors ; i++) {
2924           read(fil,&floordoor[i],sizeof(struct floordoor));
2925      }
2926      read(fil,fdxref,MAXSECTORS*sizeof(int));
2927      read(fil,&numvehicles,sizeof(int));
2928      for (i=0 ; i < numvehicles ; i++) {
2929           read(fil,&sectorvehicle[i],sizeof(struct sectorvehicle));
2930      }
2931 
2932      // must reinvoke vehicle sounds since all sounds were stopped
2933      // else updatevehiclesounds will update whatever is using
2934      // dsoundptr[vptr->soundindex]
2935      clearvehiclesoundindexes();
2936 
2937      read(fil,elevator,MAXSECTORS*sizeof(struct elevatortype));
2938      read(fil,&sprelevcnt,sizeof(int));
2939      for (i=0 ; i < sprelevcnt ; i++) {
2940           read(fil,&spriteelev[i],sizeof(struct spriteelev));
2941      }
2942      read(fil,&totalmapsndfx,sizeof(int));
2943      for (i=0 ; i < totalmapsndfx ; i++) {
2944           read(fil,&mapsndfx[i],sizeof(struct mapsndfxtype));
2945           // did we leave with a TOGGLED sound playong ?
2946           if( (mapsndfx[i].type == MAP_SFX_TOGGLED) && (mapsndfx[i].id != -1) ) {
2947                mapsndfxptr[i]->id=playsound(mapsndfxptr[i]->snum, mapsndfxptr[i]->x,mapsndfxptr[i]->y, mapsndfxptr[i]->loops, ST_UNIQUE);
2948           }
2949      }
2950 }
2951 
2952 void
tekheadbob(void)2953 tekheadbob(void)
2954 {
2955      if( headbobon && (activemenu == 0) ) {
2956           headbob+=bobstep;
2957           if( headbob < -BOBBMAX || headbob > BOBBMAX ) {
2958                bobstep=-bobstep;
2959           }
2960      }
2961 }
2962 
2963 void
tekswitchtrigger(short snum)2964 tekswitchtrigger(short snum)
2965 {
2966      int       i,j;
2967      int      nexti;
2968      int      dax,day;
2969 
2970      j=sprite[neartagsprite].picnum;
2971 
2972      switch( j ) {
2973      case SWITCH2OFF:
2974           if( invredcards[snum] == 0 ) {
2975                showmessage("PASSAGE REQUIRES RED KEYCARD");
2976                return;
2977           }
2978           break;
2979      case SWITCH4OFF:
2980           if( invbluecards[snum] == 0 ) {
2981                showmessage("PASSAGE REQUIRES BLUE KEYCARD");
2982                return;
2983           }
2984           break;
2985      }
2986 
2987      switch( j ) {
2988      case SWITCH2ON:
2989      case SWITCH2OFF:
2990      case SWITCH3ON:
2991      case SWITCH3OFF:
2992      case SWITCH4ON:
2993      case SWITCH4OFF:
2994           dax = sprite[neartagsprite].x;
2995           day = sprite[neartagsprite].y;
2996           playsound(S_KEYCARDBLIP, dax,day,0, ST_UPDATE);
2997           break;
2998      default:
2999           break;
3000      }
3001 
3002      if (j == SWITCH2ON) sprite[neartagsprite].picnum = SWITCH2OFF;
3003      if (j == SWITCH2OFF) sprite[neartagsprite].picnum = SWITCH2ON;
3004      if (j == SWITCH3ON) sprite[neartagsprite].picnum = SWITCH3OFF;
3005      if (j == SWITCH3OFF) sprite[neartagsprite].picnum = SWITCH3ON;
3006      if (j == SWITCH4ON) sprite[neartagsprite].picnum = SWITCH4OFF;
3007      if (j == SWITCH4OFF) sprite[neartagsprite].picnum = SWITCH4ON;
3008 
3009      if (j == 3708) sprite[neartagsprite].picnum = 3709;
3010      if (j == 3709) sprite[neartagsprite].picnum = 3708;
3011 
3012      for(i=0;i<numsectors;i++)
3013           if (sector[i].hitag == sprite[neartagsprite].hitag)
3014                if (sector[i].lotag != 1)
3015                     operatesector(i);
3016 
3017      i = headspritestat[0];
3018      while (i != -1)
3019      {
3020           nexti = nextspritestat[i];
3021           if (sprite[i].hitag == sprite[neartagsprite].hitag)
3022                operatesprite(i);
3023           i = nexti;
3024      }
3025 
3026 
3027 }
3028 
3029 int
krand_intercept(const char * stg)3030 krand_intercept(const char *stg)
3031 {
3032      if (dbgflag) {
3033           if (dbgcolumn > 80) {
3034                fprintf(dbgfp,"\n");
3035                dbgcolumn=0;
3036           }
3037           else {
3038                fprintf(dbgfp,"%s(%-9d) ",stg,randomseed);
3039                dbgcolumn+=20;
3040           }
3041      }
3042      return(krand());
3043 }
3044 
3045