1 //-------------------------------------------------------------------------
2 /*
3 Copyright (C) 1996, 2003 - 3D Realms Entertainment
4 Copyright (C) 2017-2019 Nuke.YKT
5 
6 This file is part of Duke Nukem 3D version 1.5 - Atomic Edition
7 
8 Duke Nukem 3D is free software; you can redistribute it and/or
9 modify it under the terms of the GNU General Public License
10 as published by the Free Software Foundation; either version 2
11 of the License, or (at your option) any later version.
12 
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
16 
17 See the GNU General Public License for more details.
18 
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
22 
23 Original Source: 1996 - Todd Replogle
24 Prepared for public release: 03/21/2003 - Charlie Wiederhold, 3D Realms
25 */
26 //-------------------------------------------------------------------------
27 
28 #include "types.h"
29 #include "develop.h"
30 #include "scriplib.h"
31 #include "file_lib.h"
32 #include "gamedefs.h"
33 #include "keyboard.h"
34 #include "util_lib.h"
35 #include "function.h"
36 #include "control.h"
37 #include "fx_man.h"
38 #include "sounds.h"
39 #include "config.h"
40 #include "sndcards.h"
41 
42 #include "duke3d.h"
43 
44 #include "warpfx.h"
45 
46 extern int sendmessagecommand;
47 extern char recbuf[];
48 extern long lastvisinc;
49 
50 int crashcnt;
51 
typemode(void)52 void typemode(void)
53 {
54      short ch, hitstate, i, j;
55 
56      if( ps[myconnectindex].gm&MODE_SENDTOWHOM )
57      {
58           if(sendmessagecommand != -1 || ud.multimode < 3)
59           {
60                 tempbuf[0] = 4;
61                 tempbuf[1] = 0;
62                 recbuf[0]  = 0;
63 
64                 if(ud.multimode < 3)
65                      sendmessagecommand = 2;
66 
67                 strcat(recbuf,ud.user_name[myconnectindex]);
68                 strcat(recbuf,": ");
69                 strcat(recbuf,typebuf);
70                 j = strlen(recbuf);
71                 recbuf[j] = 0;
72                 strcat(tempbuf+1,recbuf);
73 
74                 if(sendmessagecommand >= ud.multimode)
75                 {
76                      for(ch=connecthead;ch >= 0;ch=connectpoint2[ch])
77                           if (ch != myconnectindex)
78                                 sendpacket(ch,tempbuf,j+1);
79                      user_quote = recbuf;
80                      user_quote_time = 160;
81                 }
82                 else if(sendmessagecommand >= 0)
83                      sendpacket(sendmessagecommand,tempbuf,j+1);
84 
85                 sendmessagecommand = -1;
86                 ps[myconnectindex].gm &= ~(MODE_TYPE|MODE_SENDTOWHOM);
87           }
88           else if(sendmessagecommand == -1)
89           {
90                 sprintf(buf,"\"%s\"",typebuf);
91                 gametext(320>>1,36,buf,0);
92                 gametext(320>>1,50,"SEND MESSAGE TO...",0);
93                 for(i=0;i<ud.multimode;i++)
94                 {
95                      if (i == myconnectindex)
96                      {
97                          sprintf(buf,"A.      ALL");
98                      }
99                      else
100                      {
101                          sprintf(buf,"%ld.      %s",i+1,ud.user_name[i]);
102                      }
103                      gametext((320>>1)-40,60+i*8,buf,0);
104                 }
105 
106                 sprintf(buf,"PRESS 1-%ld FOR INDIVIDUAL PLAYER.",ud.multimode);
107                 gametext(320>>1,60+ud.multimode*8,buf,0);
108                 gametext(320>>1,68+ud.multimode*8,"'A' OR 'ENTER' FOR ALL PLAYERS",0);
109                 gametext(320>>1,76+ud.multimode*8,"ESC ABORTS",0);
110 
111                 if( KB_KeyWaiting() )
112                 {
113                      i = KB_GetCh();
114 
115                      if(i == 'A' || i == 'a' || i == 13)
116                           sendmessagecommand = ud.multimode;
117                      else if(i >= '1' || i <= (ud.multimode + '1') )
118                           sendmessagecommand = i - '1';
119                      else
120                      {
121                           ps[myconnectindex].gm &= ~(MODE_TYPE|MODE_SENDTOWHOM);
122                           sendmessagecommand = -1;
123                           typebuf[0] = 0;
124                      }
125 
126                      KB_ClearKeyDown(sc_1);
127                      KB_ClearKeyDown(sc_2);
128                      KB_ClearKeyDown(sc_3);
129                      KB_ClearKeyDown(sc_4);
130                      KB_ClearKeyDown(sc_5);
131                      KB_ClearKeyDown(sc_6);
132                      KB_ClearKeyDown(sc_7);
133                      KB_ClearKeyDown(sc_8);
134                      KB_ClearKeyDown(sc_A);
135                      KB_ClearKeyDown(sc_Escape);
136                      KB_ClearKeyDown(sc_Enter);
137                 }
138           }
139      }
140      else
141      {
142           if(ud.screen_size > 0)
143               hitstate = strget(320>>1,200-59,typebuf,30,1);
144           else
145               hitstate = strget(320>>1,200-29,typebuf,30,1);
146 
147           if(hitstate == 1)
148           {
149                 KB_ClearKeyDown(sc_Enter);
150                 ps[myconnectindex].gm |= MODE_SENDTOWHOM;
151           }
152           else if(hitstate == -1)
153                 ps[myconnectindex].gm &= ~(MODE_TYPE|MODE_SENDTOWHOM);
154           else pub = NUMPAGES;
155      }
156 }
157 
158 
displayrest(long smoothratio)159 void displayrest(long smoothratio)
160 {
161     long a, i, j;
162 
163     struct player_struct *pp;
164     walltype *wal;
165     long cposx,cposy,cang;
166 
167     pp = &ps[screenpeek];
168 
169     if( pp->pals_time > 0 && pp->loogcnt == 0)
170     {
171         palto( pp->pals[0],
172                pp->pals[1],
173                pp->pals[2],
174                pp->pals_time|128);
175 
176         restorepalette = 1;
177     }
178     else if( restorepalette )
179     {
180         setbrightness(ud.brightness>>2,&pp->palette[0]);
181         restorepalette = 0;
182     }
183     else if (pp->loogcnt)
184     {
185     }
186 
187     if(ud.show_help)
188     {
189         switch(ud.show_help)
190         {
191             case 1:
192                 rotatesprite(0,0,65536L,0,TEXTSTORY,0,0,10+16+64, 0,0,xdim-1,ydim-1);
193                 break;
194             case 2:
195                 rotatesprite(0,0,65536L,0,F1HELP,0,0,10+16+64, 0,0,xdim-1,ydim-1);
196                 break;
197 #ifdef RRRA
198             case 3:
199                 rotatesprite(0,0,65536L,0,RRTILE1636,0,0,10+16+64, 0,0,xdim-1,ydim-1);
200                 break;
201 #endif
202         }
203 
204         if ( KB_KeyPressed(sc_Escape ) )
205         {
206             KB_ClearKeyDown(sc_Escape);
207             ud.show_help = 0;
208             if(ud.multimode < 2 && ud.recstat != 2)
209             {
210                 ready2send = 1;
211                 totalclock = ototalclock;
212             }
213             vscrn();
214         }
215         return;
216     }
217 
218     i = pp->cursectnum;
219 
220     show2dsector[i>>3] |= (1<<(i&7));
221     wal = &wall[sector[i].wallptr];
222     for(j=sector[i].wallnum;j>0;j--,wal++)
223     {
224         i = wal->nextsector;
225         if (i < 0) continue;
226         if (wal->cstat&0x0071) continue;
227         if (wall[wal->nextwall].cstat&0x0071) continue;
228         if (sector[i].lotag == 32767) continue;
229         if (sector[i].ceilingz >= sector[i].floorz) continue;
230         show2dsector[i>>3] |= (1<<(i&7));
231     }
232 
233     if(ud.camerasprite == -1)
234     {
235         if( ud.overhead_on != 2 )
236         {
237             if(pp->newowner < 0)
238             {
239                 displayweapon(screenpeek);
240                 if(pp->over_shoulder_on == 0 )
241                     displaymasks(screenpeek);
242             }
243         }
244 
245         if( ud.overhead_on > 0 )
246         {
247                 smoothratio = min(max(smoothratio,0),65536);
248                 dointerpolations(smoothratio);
249                 if( ud.scrollmode == 0 )
250                 {
251                      if(pp->newowner == -1)
252                      {
253                          if (screenpeek == myconnectindex && numplayers > 1)
254                          {
255                              cposx = omyx+mulscale16((long)(myx-omyx),smoothratio);
256                              cposy = omyy+mulscale16((long)(myy-omyy),smoothratio);
257                              cang = omyang+mulscale16((long)(((myang+1024-omyang)&2047)-1024),smoothratio);
258                          }
259                          else
260                          {
261                               cposx = pp->oposx+mulscale16((long)(pp->posx-pp->oposx),smoothratio);
262                               cposy = pp->oposy+mulscale16((long)(pp->posy-pp->oposy),smoothratio);
263                               cang = pp->oang+mulscale16((long)(((pp->ang+1024-pp->oang)&2047)-1024),smoothratio);
264                          }
265                     }
266                     else
267                     {
268                         cposx = pp->oposx;
269                         cposy = pp->oposy;
270                         cang = pp->oang;
271                     }
272                 }
273                 else
274                 {
275 
276                      ud.fola += ud.folavel>>3;
277                      ud.folx += (ud.folfvel*sintable[(512+2048-ud.fola)&2047])>>14;
278                      ud.foly += (ud.folfvel*sintable[(512+1024-512-ud.fola)&2047])>>14;
279 
280                      cposx = ud.folx;
281                      cposy = ud.foly;
282                      cang = ud.fola;
283                 }
284 
285                 if(ud.overhead_on == 2)
286                 {
287                     clearview(0L);
288                     drawmapview(cposx,cposy,pp->zoom,cang);
289                 }
290                 drawoverheadmap( cposx,cposy,pp->zoom,cang);
291 
292                 restoreinterpolations();
293 
294                 if(ud.overhead_on == 2)
295                 {
296                     a = 0;
297                     if (lastlevel)
298                         minitext(1,a+6,"CLOSE ENCOUNTERS",0,2+8+16);
299                     else
300                     {
301                         minitext(1,a+6,volume_names[ud.volume_number],0,2+8+16);
302                         minitext(1,a+12,level_names[ud.volume_number*7 + ud.level_number],0,2+8+16);
303                     }
304                 }
305         }
306     }
307 
308     coolgaugetext(screenpeek);
309     gutmeter(screenpeek);
310     operatefta();
311 
312     if( KB_KeyPressed(sc_Escape) && ud.overhead_on == 0
313         && ud.show_help == 0
314         && ps[myconnectindex].newowner == -1)
315     {
316         if( (ps[myconnectindex].gm&MODE_MENU) == MODE_MENU && current_menu < 51)
317         {
318             KB_ClearKeyDown(sc_Escape);
319             ps[myconnectindex].gm &= ~MODE_MENU;
320             if(ud.multimode < 2 && ud.recstat != 2)
321             {
322                 ready2send = 1;
323                 totalclock = ototalclock;
324                 cameraclock = totalclock;
325                 cameradist = 65536L;
326             }
327             walock[MAXTILES-1] = 199;
328             vscrn();
329         }
330         else if( (ps[myconnectindex].gm&MODE_MENU) != MODE_MENU &&
331             ps[myconnectindex].newowner == -1 &&
332             (ps[myconnectindex].gm&MODE_TYPE) != MODE_TYPE)
333         {
334             KB_ClearKeyDown(sc_Escape);
335             FX_StopAllSounds();
336             clearsoundlocks();
337 
338             intomenusounds();
339 
340             ps[myconnectindex].gm |= MODE_MENU;
341 
342             if(ud.multimode < 2 && ud.recstat != 2) ready2send = 0;
343 
344             if(ps[myconnectindex].gm&MODE_GAME) cmenu(50);
345             else cmenu(0);
346             screenpeek = myconnectindex;
347         }
348     }
349 
350     if(ps[myconnectindex].newowner == -1 && ud.overhead_on == 0 && ud.crosshair && ud.camerasprite == -1)
351         rotatesprite((160L-(ps[myconnectindex].look_ang>>1))<<16,100L<<16,32768L,0,CROSSHAIR,0,0,2+1,windowx1,windowy1,windowx2,windowy2);
352 
353     if(ps[myconnectindex].gm&MODE_TYPE)
354         typemode();
355     else
356         menus();
357 
358     if( ud.pause_on==1 && (ps[myconnectindex].gm&MODE_MENU) == 0 )
359         menutext(160,100,0,0,"GAME PAUSED");
360 
361     if(ud.coords)
362         coords(screenpeek);
363     if(ud.tickrate)
364         tics();
365 }
366 
367 
updatesectorz(long x,long y,long z,short * sectnum)368 void updatesectorz(long x, long y, long z, short *sectnum)
369 {
370     walltype *wal;
371     long i, j, cz, fz;
372 
373     getzsofslope(*sectnum,x,y,&cz,&fz);
374     if ((z >= cz) && (z <= fz))
375         if (inside(x,y,*sectnum) != 0) return;
376 
377     if ((*sectnum >= 0) && (*sectnum < numsectors))
378     {
379         wal = &wall[sector[*sectnum].wallptr];
380         j = sector[*sectnum].wallnum;
381         do
382         {
383             i = wal->nextsector;
384             if (i >= 0)
385             {
386                 getzsofslope(i,x,y,&cz,&fz);
387                 if ((z >= cz) && (z <= fz))
388                     if (inside(x,y,(short)i) == 1)
389                         { *sectnum = i; return; }
390             }
391             wal++; j--;
392         } while (j != 0);
393     }
394 
395     for(i=numsectors-1;i>=0;i--)
396     {
397         getzsofslope(i,x,y,&cz,&fz);
398         if ((z >= cz) && (z <= fz))
399             if (inside(x,y,(short)i) == 1)
400                 { *sectnum = i; return; }
401     }
402 
403     *sectnum = -1;
404 }
405 
view(struct player_struct * pp,long * vx,long * vy,long * vz,short * vsectnum,short ang,short horiz)406 void view(struct player_struct *pp, long *vx, long *vy,long *vz,short *vsectnum, short ang, short horiz)
407 {
408      spritetype *sp;
409      long i, nx, ny, nz, hx, hy, hz, hitx, hity, hitz;
410      short bakcstat, hitsect, hitwall, hitsprite, daang;
411 
412      nx = (sintable[(ang+1536)&2047]>>4);
413      ny = (sintable[(ang+1024)&2047]>>4);
414      nz = (horiz-100)*128;
415 
416      sp = &sprite[pp->i];
417 
418      bakcstat = sp->cstat;
419      sp->cstat &= (short)~0x101;
420 
421      updatesectorz(*vx,*vy,*vz,vsectnum);
422      hitscan(*vx,*vy,*vz,*vsectnum,nx,ny,nz,&hitsect,&hitwall,&hitsprite,&hitx,&hity,&hitz,CLIPMASK1);
423 
424      if(*vsectnum < 0)
425      {
426         sp->cstat = bakcstat;
427         return;
428      }
429 
430      hx = hitx-(*vx); hy = hity-(*vy);
431      if (klabs(nx)+klabs(ny) > klabs(hx)+klabs(hy))
432      {
433          *vsectnum = hitsect;
434          if (hitwall >= 0)
435          {
436              daang = getangle(wall[wall[hitwall].point2].x-wall[hitwall].x,
437                                     wall[wall[hitwall].point2].y-wall[hitwall].y);
438 
439              i = nx*sintable[daang]+ny*sintable[(daang+1536)&2047];
440              if (klabs(nx) > klabs(ny)) hx -= mulscale28(nx,i);
441                                           else hy -= mulscale28(ny,i);
442          }
443          else if (hitsprite < 0)
444          {
445              if (klabs(nx) > klabs(ny)) hx -= (nx>>5);
446                                           else hy -= (ny>>5);
447          }
448          if (klabs(nx) > klabs(ny)) i = divscale16(hx,nx);
449                                       else i = divscale16(hy,ny);
450          if (i < cameradist) cameradist = i;
451      }
452      *vx = (*vx)+mulscale16(nx,cameradist);
453      *vy = (*vy)+mulscale16(ny,cameradist);
454      *vz = (*vz)+mulscale16(nz,cameradist);
455 
456      cameradist = min(cameradist+((totalclock-cameraclock)<<10),65536);
457      cameraclock = totalclock;
458 
459      updatesectorz(*vx,*vy,*vz,vsectnum);
460 
461      sp->cstat = bakcstat;
462 }
463 
464     //REPLACE FULLY
drawbackground(void)465 void drawbackground(void)
466 {
467      short dapicnum;
468      long x,y,x1,y1,x2,y2,topy;
469 
470      flushperms();
471 
472      switch(ud.m_volume_number)
473      {
474 #ifdef RRRA
475           default:dapicnum = RRTILE7629;break;
476           case 1:dapicnum = RRTILE7629;break;
477           case 2:dapicnum = RRTILE7629;break;
478 #else
479           default:dapicnum = BIGHOLE;break;
480           case 1:dapicnum = BIGHOLE;break;
481           case 2:dapicnum = BIGHOLE;break;
482 #endif
483      }
484 
485      y1 = 0; y2 = ydim;
486      if( ready2send || ud.recstat == 2 )
487      {
488         if(ud.coop != 1)
489         {
490             if (ud.multimode > 1) y1 += scale(ydim,8,200);
491             if (ud.multimode > 4) y1 += scale(ydim,8,200);
492         }
493         if (ud.screen_size >= 8) y2 = scale(ydim,200-34,200);
494      }
495 
496      for(y=y1;y<y2;y+=128)
497           for(x=0;x<xdim;x+=128)
498                 rotatesprite(x<<16,y<<16,32768L,0,dapicnum,18,0,8+16+64+128,0,y1,xdim-1,y2-1);
499 
500      if(ud.screen_size > 12)
501      {
502           y = 0;
503           if(ud.coop != 1)
504           {
505              if (ud.multimode > 1) y += 8;
506              if (ud.multimode > 4) y += 8;
507           }
508 
509           x1 = max(windowx1-4,0);
510           y1 = max(windowy1-4,y);
511           x2 = min(windowx2+4,xdim-1);
512           y2 = min(windowy2+4,scale(ydim,200-34,200)-1);
513 
514           for(y=y1+4;y<y2-4;y+=64)
515           {
516                 rotatesprite(x1<<16,y<<16,65536L,0,VIEWBORDER,0,0,8+16+64+128,x1,y1,x2,y2);
517                 rotatesprite((x2+1)<<16,(y+64)<<16,65536L,1024,VIEWBORDER,0,0,8+16+64+128,x1,y1,x2,y2);
518           }
519 
520           for(x=x1+4;x<x2-4;x+=64)
521           {
522                 rotatesprite((x+64)<<16,y1<<16,65536L,512,VIEWBORDER,0,0,8+16+64+128,x1,y1,x2,y2);
523                 rotatesprite(x<<16,(y2+1)<<16,65536L,1536,VIEWBORDER,0,0,8+16+64+128,x1,y1,x2,y2);
524           }
525 
526           rotatesprite(x1<<16,y1<<16,65536L,0,VIEWBORDER+1,0,0,8+16+64+128,x1,y1,x2,y2);
527           rotatesprite((x2+1)<<16,y1<<16,65536L,512,VIEWBORDER+1,0,0,8+16+64+128,x1,y1,x2,y2);
528           rotatesprite((x2+1)<<16,(y2+1)<<16,65536L,1024,VIEWBORDER+1,0,0,8+16+64+128,x1,y1,x2,y2);
529           rotatesprite(x1<<16,(y2+1)<<16,65536L,1536,VIEWBORDER+1,0,0,8+16+64+128,x1,y1,x2,y2);
530      }
531 }
532 
533 #ifdef RRRA
534 // Floor Over Floor
535 
536 // If standing in sector with SE42
537 // then draw viewing to SE41 and raise all =hi SE43 cielings.
538 
539 // If standing in sector with SE43
540 // then draw viewing to SE40 and lower all =hi SE42 floors.
541 
542 // If standing in sector with SE44
543 // then draw viewing to SE40.
544 
545 // If standing in sector with SE45
546 // then draw viewing to SE41.
547 
548 #define FOFTILE FOF
549 #define FOFTILEX 32
550 #define FOFTILEY 32
551 long tempsectorz[MAXSECTORS];
552 long tempsectorpicnum[MAXSECTORS];
553 //short tempcursectnum;
554 
SE_150_Draw(int spnum,long x,long y,long z,short a,short h,long smoothratio)555 SE_150_Draw(int spnum,long x,long y,long z,short a,short h,long smoothratio)
556 {
557  int i=FOFTILE,j,k=0;
558  int floor1=spnum,floor2=0,ok=0,fofmode;
559  long offx,offy;
560 
561  if(sprite[spnum].ang!=512) return;
562 
563  tilesizx[FOFTILE] = 0;
564  tilesizy[FOFTILE] = 0;
565  if (!(gotpic[i>>3]&(1<<(i&7)))) return;
566  gotpic[i>>3] &= ~(1<<(i&7));
567 
568  floor1=spnum;
569 
570  if(sprite[spnum].lotag==152) fofmode=150;
571  if(sprite[spnum].lotag==153) fofmode=151;
572  if(sprite[spnum].lotag==154) fofmode=150;
573  if(sprite[spnum].lotag==155) fofmode=151;
574 
575 // fofmode=sprite[spnum].lotag-2;
576 
577 // sectnum=sprite[j].sectnum;
578 // sectnum=cursectnum;
579  ok++;
580 
581 /*  recursive?
582  for(j=0;j<MAXSPRITES;j++)
583  {
584   if(
585      sprite[j].sectnum==sectnum &&
586      sprite[j].picnum==1 &&
587      sprite[j].lotag==110
588     ) { DrawFloorOverFloor(j); break;}
589  }
590 */
591 
592 // if(ok==0) { Message("no fof",RED); return; }
593 
594  for(j=0;j<MAXSPRITES;j++)
595  {
596   if(
597      sprite[j].picnum==1 &&
598      sprite[j].lotag==fofmode &&
599      sprite[j].hitag==sprite[floor1].hitag
600     ) { floor1=j; fofmode=sprite[j].lotag; ok++; break;}
601  }
602 // if(ok==1) { Message("no floor1",RED); return; }
603 
604  if(fofmode==150) k=151; else k=150;
605 
606  for(j=0;j<MAXSPRITES;j++)
607  {
608   if(
609      sprite[j].picnum==1 &&
610      sprite[j].lotag==k &&
611      sprite[j].hitag==sprite[floor1].hitag
612     ) {floor2=j; ok++; break;}
613  }
614 
615 // if(ok==2) { Message("no floor2",RED); return; }
616 
617  for(j=0;j<MAXSPRITES;j++)  // raise ceiling or floor
618  {
619   if(sprite[j].picnum==1 &&
620      sprite[j].lotag==k+2 &&
621      sprite[j].hitag==sprite[floor1].hitag
622     )
623     {
624      if(k==150)
625      {tempsectorz[sprite[j].sectnum]=sector[sprite[j].sectnum].floorz;
626       sector[sprite[j].sectnum].floorz+=(((z-sector[sprite[j].sectnum].floorz)/32768)+1)*32768;
627       tempsectorpicnum[sprite[j].sectnum]=sector[sprite[j].sectnum].floorpicnum;
628       sector[sprite[j].sectnum].floorpicnum=13;
629      }
630      else if(k==151)
631      {tempsectorz[sprite[j].sectnum]=sector[sprite[j].sectnum].ceilingz;
632       sector[sprite[j].sectnum].ceilingz+=(((z-sector[sprite[j].sectnum].ceilingz)/32768)-1)*32768;
633       tempsectorpicnum[sprite[j].sectnum]=sector[sprite[j].sectnum].ceilingpicnum;
634       sector[sprite[j].sectnum].ceilingpicnum=13;
635      }
636     }
637  }
638 
639  i=floor1;
640  offx=x-sprite[i].x;
641  offy=y-sprite[i].y;
642  i=floor2;
643  drawrooms(offx+sprite[i].x,offy+sprite[i].y,z,a,h,sprite[i].sectnum);
644  animatesprites(offx+sprite[i].x,offy+sprite[i].y,a,smoothratio);
645  drawmasks();
646 
647  for(j=0;j<MAXSPRITES;j++)  // restore ceiling or floor
648  {
649   if(sprite[j].picnum==1 &&
650      sprite[j].lotag==k+2 &&
651      sprite[j].hitag==sprite[floor1].hitag
652     )
653     {
654      if(k==150)
655      {sector[sprite[j].sectnum].floorz=tempsectorz[sprite[j].sectnum];
656       sector[sprite[j].sectnum].floorpicnum=tempsectorpicnum[sprite[j].sectnum];
657      }
658      else if(k==151)
659      {sector[sprite[j].sectnum].ceilingz=tempsectorz[sprite[j].sectnum];
660       sector[sprite[j].sectnum].ceilingpicnum=tempsectorpicnum[sprite[j].sectnum];
661      }
662     }// end if
663  }// end for
664 
665 } // end SE40
666 
667 
668 
669 
SE_150(long x,long y,long z,long a,long h,long smoothratio)670 void SE_150(long x,long y,long z,long a,long h, long smoothratio)
671 {
672     int i;
673 
674     for (i = headspritestat[15]; i >= 0; i = nextspritestat[i])
675     {
676         switch(sprite[i].lotag)
677         {
678 //            case 40:
679 //            case 41:
680 //                SE40_Draw(i,x,y,a,smoothratio);
681 //                break;
682             case 152:
683             case 153:
684             case 154:
685             case 155:
686                 if(ps[screenpeek].cursectnum == sprite[i].sectnum)
687                     SE_150_Draw(i,x,y,z,a,h,smoothratio);
688                 break;
689         }
690     }
691 }
692 #endif
693 
694 static long oyrepeat=-1;
695 long tempoyrepeat;
696 
displayrooms(short snum,long smoothratio)697 void displayrooms(short snum,long smoothratio)
698 {
699     long cposx,cposy,cposz,dst,j,fz,cz,hz,lz;
700     short sect, cang, k, choriz,tsect;
701     struct player_struct *p;
702     long tposx,tposy,tposz,dx,dy,thoriz,i;
703     short tang;
704 
705     p = &ps[snum];
706 
707     if(screencapt == 0 && (p->gm&MODE_MENU) && ( (current_menu/100) == 3 ) )
708         return;
709 
710     if(pub > 0)
711     {
712         if(ud.screen_size > 8) drawbackground();
713         pub = 0;
714     }
715 
716     if( ud.overhead_on == 2 || ud.show_help || p->cursectnum == -1)
717         return;
718 
719     smoothratio = min(max(smoothratio,0),65536);
720 
721 #ifdef RRRA
722     if (p->fogtype)
723         p->visibility = ud.const_visibility;
724 #endif
725 
726     visibility = p->visibility;
727 
728     if(ud.pause_on || ps[snum].on_crane > -1) smoothratio = 65536;
729 
730     sect = p->cursectnum;
731     if(sect < 0 || sect >= MAXSECTORS) return;
732 
733     dointerpolations(smoothratio);
734 
735     animatecamsprite();
736 
737     if(ud.camerasprite >= 0)
738     {
739         spritetype *s;
740 
741         s = &sprite[ud.camerasprite];
742 
743         if(s->yvel < 0) s->yvel = -100;
744         else if(s->yvel > 199) s->yvel = 300;
745 
746         cang = hittype[ud.camerasprite].tempang+mulscale16((long)(((s->ang+1024-hittype[ud.camerasprite].tempang)&2047)-1024),smoothratio);
747 
748         drawrooms(s->x,s->y,s->z-(4<<8),cang,s->yvel,s->sectnum);
749         animatesprites(s->x,s->y,cang,smoothratio);
750         drawmasks();
751     }
752     else
753     {
754         i = divscale22(1,64);
755 #ifdef RRRA
756         if (i != oyrepeat && !p->DrugMode)
757 #else
758         if (i != oyrepeat)
759 #endif
760         {
761             oyrepeat = i;
762             setaspect(oyrepeat,yxaspect);
763         }
764 
765         if(screencapt)
766         {
767             walock[MAXTILES-1] = 199;
768             if (waloff[MAXTILES-1] == 0)
769                 allocache((long *)&waloff[MAXTILES-1],100*160,&walock[MAXTILES-1]);
770             setviewtotile(MAXTILES-1,100L,160L);
771         }
772         else if( ( ud.screen_tilting && p->rotscrnang ) || ud.detail==0 || p->drink_amt > 89)
773         {
774                 if (ud.screen_tilting) tang = p->rotscrnang; else tang = 0;
775 
776 #ifdef RRRA
777                 walock[MAXTILES-2] = 199;
778                 if (p->drink_amt > 89)
779                 {
780                     if (waloff[MAXTILES-2] == 0)
781                         allocache(&waloff[MAXTILES-2],320L*320L,&walock[MAXTILES-2]);
782                     if ((tang&1023) == 0)
783                         setviewtotile(MAXTILES-2,200L>>(1-ud.detail),320L>>(1-ud.detail));
784                     else
785                         setviewtotile(MAXTILES-2,320L>>(1-ud.detail),320L>>(1-ud.detail));
786                 }
787                 else
788                 {
789                     if (waloff[MAXTILES-2] == 0)
790                         allocache(&waloff[MAXTILES-2],640L*640L,&walock[MAXTILES-2]);
791                     if ((tang&1023) == 0)
792                         setviewtotile(MAXTILES-2,480L>>(1-ud.detail),640L>>(1-ud.detail));
793                     else
794                         setviewtotile(MAXTILES-2,640L>>(1-ud.detail),640L>>(1-ud.detail));
795                 }
796 #else
797                 walock[MAXTILES-2] = 255;
798                 if (waloff[MAXTILES-2] == 0)
799                     allocache(&waloff[MAXTILES-2],320L*320L,&walock[MAXTILES-2]);
800                 if ((tang&1023) == 0)
801                     setviewtotile(MAXTILES-2,200L>>(1-ud.detail),320L>>(1-ud.detail));
802                 else
803                     setviewtotile(MAXTILES-2,320L>>(1-ud.detail),320L>>(1-ud.detail));
804 #endif
805                 if ((tang&1023) == 512)
806                 {     //Block off unscreen section of 90� tilted screen
807                     j = ((320-60)>>(1-ud.detail));
808                     for(i=(60>>(1-ud.detail))-1;i>=0;i--)
809                     {
810                         startumost[i] = 1; startumost[i+j] = 1;
811                         startdmost[i] = 0; startdmost[i+j] = 0;
812                     }
813                 }
814 
815                 i = (tang&511); if (i > 256) i = 512-i;
816                 i = sintable[i+512]*8 + sintable[i]*5L;
817                 setaspect(i>>1,yxaspect);
818           }
819 
820 #ifdef RRRA
821         if (!(p->gm & MODE_MENU))
822         {
823             if (p->DrugMode > 0 && !(p->gm&MODE_TYPE) && !ud.pause_on)
824             {
825                 int var_8c;
826                 if (p->raat5f1 == 0)
827                 {
828                     p->raat5f3++;
829                     var_8c = oyrepeat + p->raat5f3 * 5000;
830                     if (oyrepeat * 3 < var_8c)
831                     {
832                         setaspect(oyrepeat * 3, yxaspect);
833                         p->raat5f7 = oyrepeat * 3;
834                         p->raat5f1 = 2;
835                     }
836                     else
837                     {
838                         setaspect(var_8c, yxaspect);
839                         p->raat5f7 = var_8c;
840                     }
841                     setpal(p);
842                 }
843                 else if (p->raat5f1 == 3)
844                 {
845                     p->raat5f3--;
846                     var_8c = oyrepeat + p->raat5f3 * 5000;
847                     if (var_8c < oyrepeat)
848                     {
849                         setaspect(oyrepeat, yxaspect);
850                         p->DrugMode = 0;
851                         p->raat5f1 = 0;
852                         p->raat5f5 = 0;
853                         p->raat5f3 = 0;
854                     }
855                     else
856                     {
857                         setaspect(var_8c, yxaspect);
858                         p->raat5f7 = var_8c;
859                     }
860                     setpal(p);
861                 }
862                 else if (p->raat5f1 == 2)
863                 {
864                     if (p->raat5f5 > 30)
865                     {
866                         p->raat5f1 = 1;
867                     }
868                     else
869                     {
870                         p->raat5f5++;
871                         setaspect(p->raat5f5 * 500 + oyrepeat * 3, yxaspect);
872                         p->raat5f7 = oyrepeat * 3 + p->raat5f5 * 500;
873                         setpal(p);
874                     }
875                 }
876                 else
877                 {
878                     if (p->raat5f5 < 1)
879                     {
880                         p->raat5f1 = 2;
881                         p->DrugMode--;
882                         if (p->DrugMode == 1)
883                             p->raat5f1 = 3;
884                     }
885                     else
886                     {
887                         p->raat5f5--;
888                         setaspect(p->raat5f5 * 500 + oyrepeat * 3, yxaspect);
889                         p->raat5f7 = oyrepeat * 3 + p->raat5f5 * 500;
890                         setpal(p);
891                     }
892                 }
893             }
894         }
895         else if (p->DrugMode > 0)
896         {
897             setaspect(p->raat5f7, yxaspect);
898             setpal(p);
899         }
900 #endif
901 
902           if ( (snum == myconnectindex) && (numplayers > 1) )
903 		  {
904 				cposx = omyx+mulscale16((long)(myx-omyx),smoothratio);
905 				cposy = omyy+mulscale16((long)(myy-omyy),smoothratio);
906 				cposz = omyz+mulscale16((long)(myz-omyz),smoothratio);
907 				cang = omyang+mulscale16((long)(((myang+1024-omyang)&2047)-1024),smoothratio);
908 				choriz = omyhoriz+omyhorizoff+mulscale16((long)(myhoriz+myhorizoff-omyhoriz-omyhorizoff),smoothratio);
909 				sect = mycursectnum;
910 		  }
911 		  else
912 		  {
913 				cposx = p->oposx+mulscale16((long)(p->posx-p->oposx),smoothratio);
914 				cposy = p->oposy+mulscale16((long)(p->posy-p->oposy),smoothratio);
915 				cposz = p->oposz+mulscale16((long)(p->posz-p->oposz),smoothratio);
916 				cang = p->oang+mulscale16((long)(((p->ang+1024-p->oang)&2047)-1024),smoothratio);
917 				choriz = p->ohoriz+p->ohorizoff+mulscale16((long)(p->horiz+p->horizoff-p->ohoriz-p->ohorizoff),smoothratio);
918 		  }
919 		  cang += p->look_ang;
920 
921 		  if (p->newowner >= 0)
922 		  {
923 				cang = p->ang+p->look_ang;
924 				choriz = p->horiz+p->horizoff;
925 				cposx = p->posx;
926 				cposy = p->posy;
927 				cposz = p->posz;
928 				sect = sprite[p->newowner].sectnum;
929 				smoothratio = 65536L;
930 		  }
931 
932 		  else if( p->over_shoulder_on == 0 )
933 				cposz += p->opyoff+mulscale16((long)(p->pyoff-p->opyoff),smoothratio);
934 		  else view(p,&cposx,&cposy,&cposz,&sect,cang,choriz);
935 
936         cz = hittype[p->i].ceilingz;
937         fz = hittype[p->i].floorz;
938 
939         if(earthquaketime > 0 && p->on_ground == 1)
940         {
941             cposz += 256-(((earthquaketime)&1)<<9);
942             cang += (2-((earthquaketime)&2))<<2;
943         }
944 
945         if(sprite[p->i].pal == 1) cposz -= (18<<8);
946 
947         if(p->newowner >= 0)
948             choriz = 100+sprite[p->newowner].shade;
949         else if(p->spritebridge == 0)
950         {
951             if( cposz < ( p->truecz + (4<<8) ) ) cposz = cz + (4<<8);
952             else if( cposz > ( p->truefz - (4<<8) ) ) cposz = fz - (4<<8);
953         }
954 
955         if (sect >= 0)
956         {
957             getzsofslope(sect,cposx,cposy,&cz,&fz);
958             if (cposz < cz+(4<<8)) cposz = cz+(4<<8);
959             if (cposz > fz-(4<<8)) cposz = fz-(4<<8);
960         }
961 
962         if(choriz > 299) choriz = 299;
963         else if(choriz < -99) choriz = -99;
964 
965 #ifdef RRRA
966         SE_150(cposx,cposy,cposz,cang,choriz,smoothratio);
967 #endif
968 
969         if ((gotpic[MIRROR>>3]&(1<<(MIRROR&7))) > 0)
970         {
971             dst = 0x7fffffff; i = 0;
972             for(k=0;k<mirrorcnt;k++)
973             {
974                 j = klabs(wall[mirrorwall[k]].x-cposx);
975                 j += klabs(wall[mirrorwall[k]].y-cposy);
976                 if (j < dst) dst = j, i = k;
977             }
978 
979             if( wall[mirrorwall[i]].overpicnum == MIRROR )
980             {
981                 preparemirror(cposx,cposy,cposz,cang,choriz,mirrorwall[i],mirrorsector[i],&tposx,&tposy,&tang);
982 
983                 j = visibility;
984                 visibility = (j>>1) + (j>>2);
985 
986                 drawrooms(tposx,tposy,cposz,tang,choriz,mirrorsector[i]+MAXSECTORS);
987 
988                 display_mirror = 1;
989                 animatesprites(tposx,tposy,tang,smoothratio);
990                 display_mirror = 0;
991 
992                 drawmasks();
993                 completemirror();   //Reverse screen x-wise in this function
994                 visibility = j;
995             }
996             gotpic[MIRROR>>3] &= ~(1<<(MIRROR&7));
997         }
998 
999         if (sector[sect].lotag == 848)
1000         {
1001             short gs, tgsect, nextspr, geosect, geoid;
1002             int spr;
1003             drawrooms(cposx, cposy, cposz, cang, choriz, sect);
1004             animatesprites(cposx,cposy,cang,smoothratio);
1005             drawmasks();
1006             for (gs = 0; gs < geocnt; gs++)
1007             {
1008                 tgsect = geosector[gs];
1009                 spr = headspritesect[tgsect];
1010                 while (spr != -1)
1011                 {
1012                     nextspr = nextspritesect[spr];
1013                     changespritesect((short)spr, geosectorwarp[gs]);
1014                     setsprite((short)spr,sprite[spr].x -= geox[gs],sprite[spr].y -= geoy[gs],sprite[spr].z);
1015                     spr = nextspr;
1016                 }
1017                 if (geosector[gs] == sect)
1018                 {
1019                     geosect = geosectorwarp[gs];
1020                     geoid = gs;
1021                 }
1022             }
1023             cposx -= geox[geoid];
1024             cposy -= geoy[geoid];
1025             drawrooms(cposx, cposy, cposz, cang, choriz, sect);
1026             cposx += geox[geoid];
1027             cposy += geoy[geoid];
1028             for (gs = 0; gs < geocnt; gs++)
1029             {
1030                 tgsect = geosectorwarp[gs];
1031                 spr = headspritesect[tgsect];
1032                 while (spr != -1)
1033                 {
1034                     nextspr = nextspritesect[spr];
1035                     changespritesect((short)spr, geosector[gs]);
1036                     setsprite((short)spr,sprite[spr].x += geox[gs],sprite[spr].y += geoy[gs],sprite[spr].z);
1037                     spr = nextspr;
1038                 }
1039             }
1040             animatesprites(cposx,cposy,cang,smoothratio);
1041             drawmasks();
1042             for (gs = 0; gs < geocnt; gs++)
1043             {
1044                 tgsect = geosector[gs];
1045                 spr = headspritesect[tgsect];
1046                 while (spr != -1)
1047                 {
1048                     nextspr = nextspritesect[spr];
1049                     changespritesect((short)spr, geosectorwarp2[gs]);
1050                     setsprite((short)spr,sprite[spr].x -= geox2[gs],sprite[spr].y -= geoy2[gs],sprite[spr].z);
1051                     spr = nextspr;
1052                 }
1053                 if (geosector[gs] == sect)
1054                 {
1055                     geosect = geosectorwarp2[gs];
1056                     geoid = gs;
1057                 }
1058             }
1059             cposx -= geox2[geoid];
1060             cposy -= geoy2[geoid];
1061             drawrooms(cposx, cposy, cposz, cang, choriz, sect);
1062             cposx += geox2[geoid];
1063             cposy += geoy2[geoid];
1064             for (gs = 0; gs < geocnt; gs++)
1065             {
1066                 tgsect = geosectorwarp2[gs];
1067                 spr = headspritesect[tgsect];
1068                 while (spr != -1)
1069                 {
1070                     nextspr = nextspritesect[spr];
1071                     changespritesect((short)spr, geosector[gs]);
1072                     setsprite((short)spr,sprite[spr].x += geox2[gs],sprite[spr].y += geoy2[gs],sprite[spr].z);
1073                     spr = nextspr;
1074                 }
1075             }
1076             animatesprites(cposx,cposy,cang,smoothratio);
1077             drawmasks();
1078         }
1079         else
1080         {
1081             drawrooms(cposx, cposy, cposz, cang, choriz, sect);
1082             animatesprites(cposx, cposy, cang, smoothratio);
1083             drawmasks();
1084         }
1085 
1086         if(screencapt == 1)
1087         {
1088             setviewback();
1089             walock[MAXTILES-1] = 190;
1090             screencapt = 0;
1091         }
1092         else if( ( ud.screen_tilting && p->rotscrnang) || ud.detail==0 || p->drink_amt > 89)
1093         {
1094             if (ud.screen_tilting) tang = p->rotscrnang; else tang = 0;
1095             setviewback();
1096             picanm[MAXTILES-2] &= 0xff0000ff;
1097             i = (tang&511); if (i > 256) i = 512-i;
1098             i = sintable[i+512]*8 + sintable[i]*5L;
1099 #ifdef RRRA
1100             if (p->drink_amt > 89)
1101             {
1102                 if ((1-ud.detail) == 0) i >>= 1;
1103             }
1104             else
1105             {
1106                 if ((1-ud.detail) == 0) i >>= 2;
1107             }
1108 #else
1109             if ((1-ud.detail) == 0) i >>= 1;
1110 #endif
1111             rotatesprite(160<<16,100<<16,i,tang+512,MAXTILES-2,0,0,4+2+64,windowx1,windowy1,windowx2,windowy2);
1112             walock[MAXTILES-2] = 199;
1113         }
1114     }
1115 
1116     restoreinterpolations();
1117 
1118 #ifdef RRRA
1119     if (p->fogtype) return;
1120 #endif
1121 
1122     if (totalclock < lastvisinc)
1123     {
1124         if (klabs(p->visibility-ud.const_visibility) > 8)
1125             p->visibility += (ud.const_visibility-p->visibility)>>2;
1126     }
1127     else p->visibility = ud.const_visibility;
1128 }
1129 
1130 
1131 
1132 
1133 
LocateTheLocator(short n,short sn)1134 short LocateTheLocator(short n,short sn)
1135 {
1136     short i;
1137 
1138     i = headspritestat[7];
1139     while(i >= 0)
1140     {
1141         if( (sn == -1 || sn == SECT) && n == SLT )
1142             return i;
1143         i = nextspritestat[i];
1144     }
1145     return -1;
1146 }
1147 
EGS(short whatsect,long s_x,long s_y,long s_z,short s_pn,signed char s_s,signed char s_xr,signed char s_yr,short s_a,short s_ve,long s_zv,short s_ow,signed char s_ss)1148 short EGS(short whatsect,long s_x,long s_y,long s_z,short s_pn,signed char s_s,signed char s_xr,signed char s_yr,short s_a,short s_ve,long s_zv,short s_ow,signed char s_ss)
1149 {
1150     short i;
1151     spritetype *s;
1152 
1153     if (s_ow < 0)
1154         return 0;
1155 
1156     i = insertsprite(whatsect,s_ss);
1157 
1158     if( i < 0 )
1159         gameexit(" Too many sprites spawned.");
1160 
1161     hittype[i].bposx = s_x;
1162     hittype[i].bposy = s_y;
1163     hittype[i].bposz = s_z;
1164 
1165     s = &sprite[i];
1166 
1167     s->x = s_x;
1168     s->y = s_y;
1169     s->z = s_z;
1170     s->cstat = 0;
1171     s->picnum = s_pn;
1172     s->shade = s_s;
1173     s->xrepeat = s_xr;
1174     s->yrepeat = s_yr;
1175     s->pal = 0;
1176 
1177     s->ang = s_a;
1178     s->xvel = s_ve;
1179     s->zvel = s_zv;
1180     s->owner = s_ow;
1181     s->xoffset = 0;
1182     s->yoffset = 0;
1183     s->yvel = 0;
1184     s->clipdist = 0;
1185     s->pal = 0;
1186     s->lotag = 0;
1187 
1188     hittype[i].picnum = sprite[s_ow].picnum;
1189 
1190     hittype[i].lastvx = 0;
1191     hittype[i].lastvy = 0;
1192 
1193     hittype[i].timetosleep = 0;
1194     hittype[i].actorstayput = -1;
1195     hittype[i].extra = -1;
1196     hittype[i].owner = s_ow;
1197     hittype[i].cgg = 0;
1198     hittype[i].movflag = 0;
1199     hittype[i].tempang = 0;
1200     hittype[i].dispicnum = 0;
1201     hittype[i].floorz = hittype[s_ow].floorz;
1202     hittype[i].ceilingz = hittype[s_ow].ceilingz;
1203 
1204     T1=T3=T4=T6=0;
1205     if( actorscrptr[s_pn] )
1206     {
1207         s->extra = *actorscrptr[s_pn];
1208         T5 = *(actorscrptr[s_pn]+1);
1209         T2 = *(actorscrptr[s_pn]+2);
1210         s->hitag = *(actorscrptr[s_pn]+3);
1211     }
1212     else
1213     {
1214         T2=T5=0;
1215         s->extra = 0;
1216         s->hitag = 0;
1217     }
1218 
1219     if (show2dsector[SECT>>3]&(1<<(SECT&7))) show2dsprite[i>>3] |= (1<<(i&7));
1220     else show2dsprite[i>>3] &= ~(1<<(i&7));
1221 /*
1222     if(s->sectnum < 0)
1223     {
1224         s->xrepeat = s->yrepeat = 0;
1225         changespritestat(i,5);
1226     }
1227 */
1228     return(i);
1229 }
1230 
wallswitchcheck(short i)1231 char wallswitchcheck(short i)
1232 {
1233     switch(PN)
1234     {
1235         case HANDPRINTSWITCH:
1236         case HANDPRINTSWITCH+1:
1237         case ALIENSWITCH:
1238         case ALIENSWITCH+1:
1239         case MULTISWITCH:
1240         case MULTISWITCH+1:
1241         case MULTISWITCH+2:
1242         case MULTISWITCH+3:
1243         case ACCESSSWITCH:
1244         case ACCESSSWITCH2:
1245         case PULLSWITCH:
1246         case PULLSWITCH+1:
1247         case HANDSWITCH:
1248         case HANDSWITCH+1:
1249         case SLOTDOOR:
1250         case SLOTDOOR+1:
1251         case LIGHTSWITCH:
1252         case LIGHTSWITCH+1:
1253         case SPACELIGHTSWITCH:
1254         case SPACELIGHTSWITCH+1:
1255         case SPACEDOORSWITCH:
1256         case SPACEDOORSWITCH+1:
1257         case FRANKENSTINESWITCH:
1258         case FRANKENSTINESWITCH+1:
1259         case LIGHTSWITCH2:
1260         case LIGHTSWITCH2+1:
1261         case POWERSWITCH1:
1262         case POWERSWITCH1+1:
1263         case LOCKSWITCH1:
1264         case LOCKSWITCH1+1:
1265         case POWERSWITCH2:
1266         case POWERSWITCH2+1:
1267         case DIPSWITCH:
1268         case DIPSWITCH+1:
1269         case DIPSWITCH2:
1270         case DIPSWITCH2+1:
1271         case TECHSWITCH:
1272         case TECHSWITCH+1:
1273         case DIPSWITCH3:
1274         case DIPSWITCH3+1:
1275         case NUKEBUTTON:
1276         case NUKEBUTTON+1:
1277 #ifdef RRRA
1278         case MULTISWITCH2:
1279         case MULTISWITCH2+1:
1280         case MULTISWITCH2+2:
1281         case MULTISWITCH2+3:
1282         case RRTILE8464:
1283         case RRTILE8464+1:
1284 #endif
1285             return 1;
1286     }
1287     return 0;
1288 }