Annotation of src/game.c, revision 1.1.1.1

1.1       root        1: #include <fcntl.h>
                      2: #include <io.h>
                      3: #include <sys\types.h>
                      4: #include <sys\stat.h>
                      5: #include <string.h>
                      6: #include <stdlib.h>
                      7: #include <stdio.h>
                      8: #include <dos.h>
                      9: #include "build.h"
                     10: #include "names.h"
                     11: #include "pragmas.h"
                     12: 
                     13: #define TICSPERFRAME 3
                     14: #define MOVEFIFOSIZ 256
                     15: 
                     16: /***************************************************************************
                     17:        KEN'S TAG DEFINITIONS:      (Please define your own tags for your games)
                     18: 
                     19:  sector[?].lotag = 0   Normal sector
                     20:  sector[?].lotag = 1   If you are on a sector with this tag, then all sectors
                     21:                                                                  with same hi tag as this are operated.  Once.
                     22:  sector[?].lotag = 2   Same as sector[?].tag = 1 but this is retriggable.
                     23:  sector[?].lotag = 3   A really stupid sector that really does nothing now.
                     24:  sector[?].lotag = 4   A sector where you are put closer to the floor
                     25:                                                                  (such as the slime in DOOM1.DAT)
                     26:  sector[?].lotag = 5   A really stupid sector that really does nothing now.
                     27:  sector[?].lotag = 6   A normal door - instead of pressing D, you tag the
                     28:                                                                  sector with a 6.  The reason I make you edit doors
                     29:                                                                  this way is so that can program the doors
                     30:                                                                  yourself.
                     31:  sector[?].lotag = 7   A door the goes down to open.
                     32:  sector[?].lotag = 8   A door that opens horizontally in the middle.
                     33:  sector[?].lotag = 9   A sliding door that opens vertically in the middle.
                     34:                                                                  -Example of the advantages of not using BSP tree.
                     35:  sector[?].lotag = 10  A warping sector with floor and walls that shade.
                     36:  sector[?].lotag = 11  A sector with all walls that do X-panning.
                     37:  sector[?].lotag = 12  A sector with walls using the dragging function.
                     38:  sector[?].lotag = 13  A sector with some swinging doors in it.
                     39:  sector[?].lotag = 14  A revolving door sector.
                     40:  sector[?].lotag = 15  A subway track.
                     41:  sector[?].lotag = 16  A true double-sliding door.
                     42: 
                     43:        wall[?].lotag = 0   Normal wall
                     44:        wall[?].lotag = 1   Y-panning wall
                     45:        wall[?].lotag = 2   Switch - If you flip it, then all sectors with same hi
                     46:                                                                  tag as this are operated.
                     47:        wall[?].lotag = 3   Marked wall to detemine starting dir. (sector tag 12)
                     48:        wall[?].lotag = 4   Mark on the shorter wall closest to the pivot point
                     49:                                                                  of a swinging door. (sector tag 13)
                     50:        wall[?].lotag = 5   Mark where a subway should stop. (sector tag 15)
                     51:        wall[?].lotag = 6   Mark for true double-sliding doors (sector tag 16)
                     52:        wall[?].lotag = 7   Water fountain
                     53:        wall[?].lotag = 8   Bouncy wall!
                     54: 
                     55:  sprite[?].lotag = 0   Normal sprite
                     56:  sprite[?].lotag = 1   If you press space bar on an AL, and the AL is tagged
                     57:                                                                  with a 1, he will turn evil.
                     58:  sprite[?].lotag = 2   When this sprite is operated, a bomb is shot at its
                     59:                                                                  position.
                     60:  sprite[?].lotag = 3   Rotating sprite.
                     61:  sprite[?].lotag = 4   Sprite switch.
                     62:  sprite[?].lotag = 5   Basketball hoop score.
                     63: 
                     64: KEN'S STATUS DEFINITIONS:  (Please define your own statuses for your games)
                     65:  status = 0            Inactive sprite
                     66:  status = 1            Active monster sprite
                     67:  status = 2            Monster that becomes active only when it sees you
                     68:  status = 3            Smoke on the wall for chainguns
                     69:  status = 4            Splashing sprites (When you shoot slime)
                     70:  status = 5            Explosion!
                     71:  status = 6            Travelling bullet
                     72:  status = 7            Bomb sprial-out explosion
                     73:  status = 8            Player!
                     74:  status = 9            EVILALGRAVE shrinking list
                     75:  status = 10           EVILAL list
                     76:  status = 11           Sprite respawning list
                     77:  status = MAXSTATUS    Non-existent sprite (this will be true for your
                     78:                                                                                                                  code also)
                     79: **************************************************************************/
                     80: 
                     81: typedef struct
                     82: {
                     83:        long x, y, z;
                     84: } point3d;
                     85: 
                     86: typedef struct
                     87: {
                     88:        signed char fvel, svel, avel;
                     89:        short bits;
                     90: } input;
                     91: 
                     92: static long screentilt = 0;
                     93: 
                     94: void (__interrupt __far *oldtimerhandler)();
                     95: void __interrupt __far timerhandler(void);
                     96: 
                     97: #define KEYFIFOSIZ 64
                     98: void (__interrupt __far *oldkeyhandler)();
                     99: void __interrupt __far keyhandler(void);
                    100: volatile char keystatus[256], keyfifo[KEYFIFOSIZ], keyfifoplc, keyfifoend;
                    101: volatile char readch, oldreadch, extended, keytemp;
                    102: 
                    103: static long fvel, svel, avel;
                    104: static long fvel2, svel2, avel2;
                    105: 
                    106: extern volatile long recsnddone, recsndoffs;
                    107: static long recording = -2;
                    108: 
                    109: #define NUMOPTIONS 8
                    110: #define NUMKEYS 19
                    111: static long chainxres[4] = {256,320,360,400};
                    112: static long chainyres[11] = {200,240,256,270,300,350,360,400,480,512,540};
                    113: static long vesares[13][2] = {320,200,360,200,320,240,360,240,320,400,
                    114:                                                                        360,400,640,350,640,400,640,480,800,600,
                    115:                                                                        1024,768,1280,1024,1600,1200};
                    116: static char option[NUMOPTIONS] = {0,0,0,0,0,0,1,0};
                    117: static char keys[NUMKEYS] =
                    118: {
                    119:        0xc8,0xd0,0xcb,0xcd,0x2a,0x9d,0x1d,0x39,
                    120:        0x1e,0x2c,0xd1,0xc9,0x33,0x34,
                    121:        0x9c,0x1c,0xd,0xc,0xf,
                    122: };
                    123: 
                    124: static long digihz[7] = {6000,8000,11025,16000,22050,32000,44100};
                    125: 
                    126: static char frame2draw[MAXPLAYERS];
                    127: static long frameskipcnt[MAXPLAYERS];
                    128: 
                    129: static char gundmost[320];
                    130: 
                    131: #define LAVASIZ 128
                    132: #define LAVALOGSIZ 7
                    133: #define LAVAMAXDROPS 32
                    134: static char lavabakpic[(LAVASIZ+4)*(LAVASIZ+4)], lavainc[LAVASIZ];
                    135: static long lavanumdrops, lavanumframes;
                    136: static long lavadropx[LAVAMAXDROPS], lavadropy[LAVAMAXDROPS];
                    137: static long lavadropsiz[LAVAMAXDROPS], lavadropsizlookup[LAVAMAXDROPS];
                    138: static long lavaradx[32][128], lavarady[32][128], lavaradcnt[32];
                    139: 
                    140:        //Shared player variables
                    141: static long posx[MAXPLAYERS], posy[MAXPLAYERS], posz[MAXPLAYERS];
                    142: static long horiz[MAXPLAYERS], zoom[MAXPLAYERS], hvel[MAXPLAYERS];
                    143: static short ang[MAXPLAYERS], cursectnum[MAXPLAYERS], ocursectnum[MAXPLAYERS];
                    144: static short playersprite[MAXPLAYERS], deaths[MAXPLAYERS];
                    145: static long lastchaingun[MAXPLAYERS];
                    146: static long health[MAXPLAYERS], flytime[MAXPLAYERS];
                    147: static short numbombs[MAXPLAYERS], oflags[MAXPLAYERS];
                    148: static char dimensionmode[MAXPLAYERS];
                    149: static char revolvedoorstat[MAXPLAYERS];
                    150: static short revolvedoorang[MAXPLAYERS], revolvedoorrotang[MAXPLAYERS];
                    151: static long revolvedoorx[MAXPLAYERS], revolvedoory[MAXPLAYERS];
                    152: 
                    153:        //ENGINE CONTROLLED MULTIPLAYER VARIABLES:
                    154: extern short numplayers, myconnectindex;
                    155: extern short connecthead, connectpoint2[MAXPLAYERS];   //Player linked list variables (indeces, not connection numbers)
                    156: 
                    157: static long nummoves;
                    158: #define NUMSTATS 11
                    159: static signed char statrate[NUMSTATS] = {-1,0,-1,0,0,0,1,3,0,3,15};
                    160: 
                    161:        //Input structures
                    162: static long locselectedgun, locselectedgun2;
                    163: static input loc, oloc, loc2;
                    164: static input fsync[MAXPLAYERS], osync[MAXPLAYERS], sync[MAXPLAYERS];
                    165:        //Input faketimerhandler -> movethings fifo
                    166: static long movefifoplc, movefifoend;
                    167: static input baksync[MOVEFIFOSIZ][MAXPLAYERS];
                    168:        //Game recording variables
                    169: static long reccnt, recstat = 1;
                    170: static input recsync[16384][2];
                    171: 
                    172:        //MULTI.OBJ sync state variables
                    173: extern char syncstate;
                    174:        //GAME.C sync state variables
                    175: static short syncstat = 0;
                    176: static long syncvalhead = 0, othersyncvalhead = 0, syncvaltail = 0;
                    177: static short syncval[MOVEFIFOSIZ], othersyncval[MOVEFIFOSIZ];
                    178: 
                    179: extern long crctable[256];
                    180: #define updatecrc16(crc,dat) (crc = (crc<<8)^crctable[(crc>>8)^(dat&255)])
                    181: 
                    182: static char detailmode = 0, ready2send = 0;
                    183: static long ototalclock = 0, gotlastpacketclock = 0, smoothratio;
                    184: static long oposx[MAXPLAYERS], oposy[MAXPLAYERS], oposz[MAXPLAYERS];
                    185: static long ohoriz[MAXPLAYERS], ozoom[MAXPLAYERS];
                    186: static short oang[MAXPLAYERS];
                    187: 
                    188: static point3d osprite[MAXSPRITES];
                    189: 
                    190: #define MAXINTERPOLATIONS 1024
                    191: static long numinterpolations = 0, startofdynamicinterpolations = 0;
                    192: static long oldipos[MAXINTERPOLATIONS];
                    193: static long bakipos[MAXINTERPOLATIONS];
                    194: static long *curipos[MAXINTERPOLATIONS];
                    195: 
                    196: extern long cachecount, transarea;
                    197: 
                    198: static char playerreadyflag[MAXPLAYERS];
                    199: 
                    200:        //Miscellaneous variables
                    201: static char packbuf[MAXXDIM];
                    202: static char tempbuf[MAXXDIM], boardfilename[80];
                    203: static short tempshort[MAXSECTORS];
                    204: static short screenpeek = 0, oldmousebstatus = 0, brightness = 0;
                    205: static short screensize, screensizeflag = 0;
                    206: static short neartagsector, neartagwall, neartagsprite;
                    207: static long lockclock, neartagdist, neartaghitdist;
                    208: extern char chainstat;
                    209: extern long frameplace, pageoffset, ydim16;
                    210: static long globhiz, globloz, globhihit, globlohit;
                    211: extern long stereofps, stereowidth, stereopixelwidth;
                    212: 
                    213:        //Board animation variables
                    214: #define MAXMIRRORS 64
                    215: static short mirrorwall[MAXMIRRORS], mirrorsector[MAXMIRRORS], mirrorcnt;
                    216: static short floormirrorsector[64], floormirrorcnt;
                    217: static short turnspritelist[16], turnspritecnt;
                    218: static short warpsectorlist[64], warpsectorcnt;
                    219: static short xpanningsectorlist[16], xpanningsectorcnt;
                    220: static short ypanningwalllist[64], ypanningwallcnt;
                    221: static short floorpanninglist[64], floorpanningcnt;
                    222: static short dragsectorlist[16], dragxdir[16], dragydir[16], dragsectorcnt;
                    223: static long dragx1[16], dragy1[16], dragx2[16], dragy2[16], dragfloorz[16];
                    224: static short swingcnt, swingwall[32][5], swingsector[32];
                    225: static short swingangopen[32], swingangclosed[32], swingangopendir[32];
                    226: static short swingang[32], swinganginc[32];
                    227: static long swingx[32][8], swingy[32][8];
                    228: static short revolvesector[4], revolveang[4], revolvecnt;
                    229: static long revolvex[4][16], revolvey[4][16];
                    230: static long revolvepivotx[4], revolvepivoty[4];
                    231: static short subwaytracksector[4][128], subwaynumsectors[4], subwaytrackcnt;
                    232: static long subwaystop[4][8], subwaystopcnt[4];
                    233: static long subwaytrackx1[4], subwaytracky1[4];
                    234: static long subwaytrackx2[4], subwaytracky2[4];
                    235: static long subwayx[4], subwaygoalstop[4], subwayvel[4], subwaypausetime[4];
                    236: static short waterfountainwall[MAXPLAYERS], waterfountaincnt[MAXPLAYERS];
                    237: static short slimesoundcnt[MAXPLAYERS];
                    238: 
                    239:        //Variables that let you type messages to other player
                    240: static char getmessage[162], getmessageleng;
                    241: static long getmessagetimeoff;
                    242: static char typemessage[162], typemessageleng = 0, typemode = 0;
                    243: static char scantoasc[128] =
                    244: {
                    245:        0,0,'1','2','3','4','5','6','7','8','9','0','-','=',0,0,
                    246:        'q','w','e','r','t','y','u','i','o','p','[',']',0,0,'a','s',
                    247:        'd','f','g','h','j','k','l',';',39,'`',0,92,'z','x','c','v',
                    248:        'b','n','m',',','.','/',0,'*',0,32,0,0,0,0,0,0,
                    249:        0,0,0,0,0,0,0,'7','8','9','-','4','5','6','+','1',
                    250:        '2','3','0','.',0,0,0,0,0,0,0,0,0,0,0,0,
                    251:        0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
                    252:        0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
                    253: };
                    254: static char scantoascwithshift[128] =
                    255: {
                    256:        0,0,'!','@','#','$','%','^','&','*','(',')','_','+',0,0,
                    257:        'Q','W','E','R','T','Y','U','I','O','P','{','}',0,0,'A','S',
                    258:        'D','F','G','H','J','K','L',':',34,'~',0,'|','Z','X','C','V',
                    259:        'B','N','M','<','>','?',0,'*',0,32,0,0,0,0,0,0,
                    260:        0,0,0,0,0,0,0,'7','8','9','-','4','5','6','+','1',
                    261:        '2','3','0','.',0,0,0,0,0,0,0,0,0,0,0,0,
                    262:        0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
                    263:        0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
                    264: };
                    265: 
                    266:        //These variables are for animating x, y, or z-coordinates of sectors,
                    267:        //walls, or sprites (They are NOT to be used for changing the [].picnum's)
                    268:        //See the setanimation(), and getanimategoal() functions for more details.
                    269: #define MAXANIMATES 512
                    270: static long *animateptr[MAXANIMATES], animategoal[MAXANIMATES];
                    271: static long animatevel[MAXANIMATES], animateacc[MAXANIMATES], animatecnt = 0;
                    272: 
                    273:        //These parameters are in exact order of sprite structure in BUILD.H
                    274: #define spawnsprite(newspriteindex2,x2,y2,z2,cstat2,shade2,pal2,       \
                    275:                clipdist2,xrepeat2,yrepeat2,xoffset2,yoffset2,picnum2,ang2,      \
                    276:                xvel2,yvel2,zvel2,owner2,sectnum2,statnum2,lotag2,hitag2,extra2) \
                    277: {                                                                      \
                    278:        spritetype *spr2;                                                   \
                    279:        newspriteindex2 = insertsprite(sectnum2,statnum2);                  \
                    280:        spr2 = &sprite[newspriteindex2];                                    \
                    281:        spr2->x = x2; spr2->y = y2; spr2->z = z2;                           \
                    282:        spr2->cstat = cstat2; spr2->shade = shade2;                         \
                    283:        spr2->pal = pal2; spr2->clipdist = clipdist2;                       \
                    284:        spr2->xrepeat = xrepeat2; spr2->yrepeat = yrepeat2;                 \
                    285:        spr2->xoffset = xoffset2; spr2->yoffset = yoffset2;                 \
                    286:        spr2->picnum = picnum2; spr2->ang = ang2;                           \
                    287:        spr2->xvel = xvel2; spr2->yvel = yvel2; spr2->zvel = zvel2;         \
                    288:        spr2->owner = owner2;                                               \
                    289:        spr2->lotag = lotag2; spr2->hitag = hitag2; spr2->extra = extra2;   \
                    290:        copybuf(&spr2->x,&osprite[newspriteindex2].x,3);                    \
                    291:        show2dsprite[newspriteindex2>>3] &= ~(1<<(newspriteindex2&7));      \
                    292:        if (show2dsector[sectnum2>>3]&(1<<(sectnum2&7)))                    \
                    293:                show2dsprite[newspriteindex2>>3] |= (1<<(newspriteindex2&7));    \
                    294: }                                                                      \
                    295: 
                    296: main(short int argc,char **argv)
                    297: {
                    298:        long i, j, k, l, fil, waitplayers, x1, y1, x2, y2;
                    299:        short other, packleng;
                    300:        char *ptr;
                    301: 
                    302:        initgroupfile("stuff.dat");
                    303: 
                    304:        if ((argc >= 2) && (stricmp("-net",argv[1]) != 0) && (stricmp("/net",argv[1]) != 0))
                    305:        {
                    306:                strcpy(&boardfilename,argv[1]);
                    307:                if(strchr(boardfilename,'.') == 0)
                    308:                        strcat(boardfilename,".map");
                    309:        }
                    310:        else
                    311:                strcpy(&boardfilename,"nukeland.map");
                    312: 
                    313:        if ((fil = open("setup.dat",O_BINARY|O_RDWR,S_IREAD)) != -1)
                    314:        {
                    315:                read(fil,&option[0],NUMOPTIONS);
                    316:                read(fil,&keys[0],NUMKEYS);
                    317:                close(fil);
                    318:        }
                    319:        if (option[3] != 0) initmouse();
                    320: 
                    321:        switch(option[0])
                    322:        {
                    323:                case 0: initengine(0,chainxres[option[6]&15],chainyres[option[6]>>4]); break;
                    324:                case 1: initengine(1,vesares[option[6]&15][0],vesares[option[6]&15][1]); break;
                    325:                default: initengine(option[0],320L,200L); break;
                    326:        }
                    327:        initkeys();
                    328:        inittimer();
                    329:        initmultiplayers(option[4],option[5],0);
                    330: 
                    331:        pskyoff[0] = 0; pskyoff[1] = 0; pskybits = 1;
                    332: 
                    333:        initsb(option[1],option[2],digihz[option[7]>>4],((option[7]&4)>0)+1,((option[7]&2)>0)+1,60,option[7]&1);
                    334:        if (strcmp(boardfilename,"klab.map") == 0)
                    335:                loadsong("klabsong.kdm");
                    336:        else
                    337:                loadsong("neatsong.kdm");
                    338:        musicon();
                    339: 
                    340:        loadpics("tiles000.art");                      //Load artwork
                    341: 
                    342:                //Here's an example of TRUE ornamented walls
                    343:                //The allocatepermanenttile should be called right after loadpics
                    344:                //Since it resets the tile cache for each call.
                    345:        if (allocatepermanenttile(SLIME,128,128) == 0)    //If enough memory
                    346:        {
                    347:                printf("Not enough memory for slime!\n");
                    348:                exit(0);
                    349:        }
                    350:        if (allocatepermanenttile(4095,64,64) != 0)    //If enough memory
                    351:        {
                    352:                        //My face with an explosion written over it
                    353:                copytilepiece(KENPICTURE,0,0,64,64,4095,0,0);
                    354:                copytilepiece(EXPLOSION,0,0,64,64,4095,0,0);
                    355:        }
                    356: 
                    357:        initlava();
                    358: 
                    359:                //Get dmost table for canon
                    360:        if (waloff[GUNONBOTTOM] == 0) loadtile(GUNONBOTTOM);
                    361:        x1 = tilesizx[GUNONBOTTOM]; y1 = tilesizy[GUNONBOTTOM];
                    362:        ptr = (char *)(waloff[GUNONBOTTOM]);
                    363:        for(i=0;i<x1;i++)
                    364:        {
                    365:                y2 = y1-1; while ((ptr[y2] != 255) && (y2 >= 0)) y2--;
                    366:                gundmost[i] = y2+1;
                    367:                ptr += y1;
                    368:        }
                    369: 
                    370:        for(j=0;j<256;j++)
                    371:                tempbuf[j] = ((j+32)&255);  //remap colors for screwy palette sectors
                    372:        makepalookup(16,tempbuf,0,0,0,1);
                    373: 
                    374:        for(j=0;j<256;j++) tempbuf[j] = j;
                    375:        makepalookup(17,tempbuf,24,24,24,1);
                    376: 
                    377:        for(j=0;j<256;j++) tempbuf[j] = j; //(j&31)+32;
                    378:        makepalookup(18,tempbuf,8,8,48,1);
                    379: 
                    380:        prepareboard(boardfilename);                   //Load board
                    381: 
                    382:        if (option[4] > 0)
                    383:        {
                    384:                x1 = ((xdim-screensize)>>1);
                    385:                x2 = x1+screensize-1;
                    386:                y1 = (((ydim-32)-scale(screensize,ydim-32,xdim))>>1);
                    387:                y2 = y1 + scale(screensize,ydim-32,xdim)-1;
                    388:                drawtilebackground(0L,0L,BACKGROUND,8,x1,y1,x2,y2,0);
                    389: 
                    390:                sendlogon();
                    391:                if (option[4] < 5) waitplayers = 2; else waitplayers = option[4]-3;
                    392:                while (numplayers < waitplayers)
                    393:                {
                    394:                        sprintf(tempbuf,"%ld of %ld players in...",numplayers,waitplayers);
                    395:                        printext256(68L,84L,31,0,tempbuf,0);
                    396:                        nextpage();
                    397: 
                    398:                        if (getpacket(&other,packbuf) > 0)
                    399:                                if (packbuf[0] == 255)
                    400:                                        keystatus[1] = 1;
                    401: 
                    402:                        if (keystatus[1] > 0)
                    403:                        {
                    404:                                sendlogoff();         //Signing off
                    405:                                musicoff();
                    406:                                uninitmultiplayers();
                    407:                                uninittimer();
                    408:                                uninitkeys();
                    409:                                uninitengine();
                    410:                                uninitsb();
                    411:                                uninitgroupfile();
                    412:                                setvmode(0x3);        //Set back to text mode
                    413:                                exit(0);
                    414:                        }
                    415:                }
                    416:                screenpeek = myconnectindex;
                    417: 
                    418:                j = 1;
                    419:                for(i=connecthead;i>=0;i=connectpoint2[i])
                    420:                {
                    421:                        if (myconnectindex == i) break;
                    422:                        j++;
                    423:                }
                    424:                if (j == 1)
                    425:                        strcpy(getmessage,"Player 1 (Master)");
                    426:                else
                    427:                        sprintf(getmessage,"Player %ld (Slave)",j);
                    428:                getmessageleng = strlen(getmessage);
                    429:                getmessagetimeoff = totalclock+120;
                    430:        }
                    431: 
                    432:        reccnt = 0;
                    433:        for(i=connecthead;i>=0;i=connectpoint2[i]) initplayersprite((short)i);
                    434: 
                    435:        //waitforeverybody();
                    436:        resettiming(); ototalclock = 0; gotlastpacketclock = 0; nummoves = 0;
                    437: 
                    438:        ready2send = 1;
                    439:        while (keystatus[1] == 0)       //Main loop starts here
                    440:        {
                    441:                        // backslash (useful only with KDM)
                    442:                if (keystatus[0x2b] > 0) { keystatus[0x2b] = 0; preparesndbuf(); }
                    443: 
                    444:                getpackets();
                    445:                while (movefifoplc != movefifoend) domovethings();
                    446:                drawscreen(screenpeek,(totalclock-gotlastpacketclock)*(65536/TICSPERFRAME));
                    447: 
                    448:        }
                    449:        ready2send = 0;
                    450: 
                    451:        sendlogoff();         //Signing off
                    452:        musicoff();
                    453:        uninitmultiplayers();
                    454:        uninittimer();
                    455:        uninitkeys();
                    456:        uninitengine();
                    457:        uninitsb();
                    458:        uninitgroupfile();
                    459:        setvmode(0x3);        //Set back to text mode
                    460:        showengineinfo();     //Show speed statistics
                    461: 
                    462:        return(0);
                    463: }
                    464: 
                    465: operatesector(short dasector)
                    466: {     //Door code
                    467:        long i, j, k, s, nexti, good, cnt, datag;
                    468:        long dax, day, daz, dax2, day2, daz2, centx, centy;
                    469:        short startwall, endwall, wallfind[2];
                    470: 
                    471:        datag = sector[dasector].lotag;
                    472: 
                    473:        startwall = sector[dasector].wallptr;
                    474:        endwall = startwall + sector[dasector].wallnum;
                    475:        centx = 0L, centy = 0L;
                    476:        for(i=startwall;i<endwall;i++)
                    477:        {
                    478:                centx += wall[i].x;
                    479:                centy += wall[i].y;
                    480:        }
                    481:        centx /= (endwall-startwall);
                    482:        centy /= (endwall-startwall);
                    483: 
                    484:                //Simple door that moves up  (tag 8 is a combination of tags 6 & 7)
                    485:        if ((datag == 6) || (datag == 8))    //If the sector in front is a door
                    486:        {
                    487:                i = getanimationgoal((long)&sector[dasector].ceilingz);
                    488:                if (i >= 0)      //If door already moving, reverse its direction
                    489:                {
                    490:                        if (datag == 8)
                    491:                                daz = ((sector[dasector].ceilingz+sector[dasector].floorz)>>1);
                    492:                        else
                    493:                                daz = sector[dasector].floorz;
                    494: 
                    495:                        if (animategoal[i] == daz)
                    496:                                animategoal[i] = sector[nextsectorneighborz(dasector,sector[dasector].floorz,-1,-1)].ceilingz;
                    497:                        else
                    498:                                animategoal[i] = daz;
                    499:                        animatevel[i] = 0;
                    500:                }
                    501:                else      //else insert the door's ceiling on the animation list
                    502:                {
                    503:                        if (sector[dasector].ceilingz == sector[dasector].floorz)
                    504:                                daz = sector[nextsectorneighborz(dasector,sector[dasector].floorz,-1,-1)].ceilingz;
                    505:                        else
                    506:                        {
                    507:                                if (datag == 8)
                    508:                                        daz = ((sector[dasector].ceilingz+sector[dasector].floorz)>>1);
                    509:                                else
                    510:                                        daz = sector[dasector].floorz;
                    511:                        }
                    512:                        if ((j = setanimation(&sector[dasector].ceilingz,daz,6L,6L)) >= 0)
                    513:                                wsayfollow("updowndr.wav",4096L+(krand()&255)-128,256L,&centx,&centy,0);
                    514:                }
                    515:        }
                    516:                //Simple door that moves down
                    517:        if ((datag == 7) || (datag == 8)) //If the sector in front's elevator
                    518:        {
                    519:                i = getanimationgoal((long)&sector[dasector].floorz);
                    520:                if (i >= 0)      //If elevator already moving, reverse its direction
                    521:                {
                    522:                        if (datag == 8)
                    523:                                daz = ((sector[dasector].ceilingz+sector[dasector].floorz)>>1);
                    524:                        else
                    525:                                daz = sector[dasector].ceilingz;
                    526: 
                    527:                        if (animategoal[i] == daz)
                    528:                                animategoal[i] = sector[nextsectorneighborz(dasector,sector[dasector].ceilingz,1,1)].floorz;
                    529:                        else
                    530:                                animategoal[i] = daz;
                    531:                        animatevel[i] = 0;
                    532:                }
                    533:                else      //else insert the elevator's ceiling on the animation list
                    534:                {
                    535:                        if (sector[dasector].floorz == sector[dasector].ceilingz)
                    536:                                daz = sector[nextsectorneighborz(dasector,sector[dasector].ceilingz,1,1)].floorz;
                    537:                        else
                    538:                        {
                    539:                                if (datag == 8)
                    540:                                        daz = ((sector[dasector].ceilingz+sector[dasector].floorz)>>1);
                    541:                                else
                    542:                                        daz = sector[dasector].ceilingz;
                    543:                        }
                    544:                        if ((j = setanimation(&sector[dasector].floorz,daz,6L,6L)) >= 0)
                    545:                                wsayfollow("updowndr.wav",4096L+(krand()&255)-128,256L,&centx,&centy,0);
                    546:                }
                    547:        }
                    548: 
                    549:        if (datag == 9)   //Smooshy-wall sideways double-door
                    550:        {
                    551:                //find any points with either same x or same y coordinate
                    552:                //  as center (centx, centy) - should be 2 points found.
                    553:                wallfind[0] = -1;
                    554:                wallfind[1] = -1;
                    555:                for(i=startwall;i<endwall;i++)
                    556:                        if ((wall[i].x == centx) || (wall[i].y == centy))
                    557:                        {
                    558:                                if (wallfind[0] == -1)
                    559:                                        wallfind[0] = i;
                    560:                                else
                    561:                                        wallfind[1] = i;
                    562:                        }
                    563: 
                    564:                for(j=0;j<2;j++)
                    565:                {
                    566:                        if ((wall[wallfind[j]].x == centx) && (wall[wallfind[j]].y == centy))
                    567:                        {
                    568:                                //find what direction door should open by averaging the
                    569:                                //  2 neighboring points of wallfind[0] & wallfind[1].
                    570:                                i = wallfind[j]-1; if (i < startwall) i = endwall-1;
                    571:                                dax2 = ((wall[i].x+wall[wall[wallfind[j]].point2].x)>>1)-wall[wallfind[j]].x;
                    572:                                day2 = ((wall[i].y+wall[wall[wallfind[j]].point2].y)>>1)-wall[wallfind[j]].y;
                    573:                                if (dax2 != 0)
                    574:                                {
                    575:                                        dax2 = wall[wall[wall[wallfind[j]].point2].point2].x;
                    576:                                        dax2 -= wall[wall[wallfind[j]].point2].x;
                    577:                                        setanimation(&wall[wallfind[j]].x,wall[wallfind[j]].x+dax2,4L,0L);
                    578:                                        setanimation(&wall[i].x,wall[i].x+dax2,4L,0L);
                    579:                                        setanimation(&wall[wall[wallfind[j]].point2].x,wall[wall[wallfind[j]].point2].x+dax2,4L,0L);
                    580:                                }
                    581:                                else if (day2 != 0)
                    582:                                {
                    583:                                        day2 = wall[wall[wall[wallfind[j]].point2].point2].y;
                    584:                                        day2 -= wall[wall[wallfind[j]].point2].y;
                    585:                                        setanimation(&wall[wallfind[j]].y,wall[wallfind[j]].y+day2,4L,0L);
                    586:                                        setanimation(&wall[i].y,wall[i].y+day2,4L,0L);
                    587:                                        setanimation(&wall[wall[wallfind[j]].point2].y,wall[wall[wallfind[j]].point2].y+day2,4L,0L);
                    588:                                }
                    589:                        }
                    590:                        else
                    591:                        {
                    592:                                i = wallfind[j]-1; if (i < startwall) i = endwall-1;
                    593:                                dax2 = ((wall[i].x+wall[wall[wallfind[j]].point2].x)>>1)-wall[wallfind[j]].x;
                    594:                                day2 = ((wall[i].y+wall[wall[wallfind[j]].point2].y)>>1)-wall[wallfind[j]].y;
                    595:                                if (dax2 != 0)
                    596:                                {
                    597:                                        setanimation(&wall[wallfind[j]].x,centx,4L,0L);
                    598:                                        setanimation(&wall[i].x,centx+dax2,4L,0L);
                    599:                                        setanimation(&wall[wall[wallfind[j]].point2].x,centx+dax2,4L,0L);
                    600:                                }
                    601:                                else if (day2 != 0)
                    602:                                {
                    603:                                        setanimation(&wall[wallfind[j]].y,centy,4L,0L);
                    604:                                        setanimation(&wall[i].y,centy+day2,4L,0L);
                    605:                                        setanimation(&wall[wall[wallfind[j]].point2].y,centy+day2,4L,0L);
                    606:                                }
                    607:                        }
                    608:                }
                    609:                wsayfollow("updowndr.wav",4096L-256L,256L,&centx,&centy,0);
                    610:                wsayfollow("updowndr.wav",4096L+256L,256L,&centx,&centy,0);
                    611:        }
                    612: 
                    613:        if (datag == 13)  //Swinging door
                    614:        {
                    615:                for(i=0;i<swingcnt;i++)
                    616:                {
                    617:                        if (swingsector[i] == dasector)
                    618:                        {
                    619:                                if (swinganginc[i] == 0)
                    620:                                {
                    621:                                        if (swingang[i] == swingangclosed[i])
                    622:                                        {
                    623:                                                swinganginc[i] = swingangopendir[i];
                    624:                                                wsayfollow("opendoor.wav",4096L+(krand()&511)-256,256L,&centx,&centy,0);
                    625:                                        }
                    626:                                        else
                    627:                                                swinganginc[i] = -swingangopendir[i];
                    628:                                }
                    629:                                else
                    630:                                        swinganginc[i] = -swinganginc[i];
                    631: 
                    632:                                for(j=1;j<=3;j++)
                    633:                                {
                    634:                                        setinterpolation(&wall[swingwall[i][j]].x);
                    635:                                        setinterpolation(&wall[swingwall[i][j]].y);
                    636:                                }
                    637:                        }
                    638:                }
                    639:        }
                    640: 
                    641:        if (datag == 16)  //True sideways double-sliding door
                    642:        {
                    643:                 //get 2 closest line segments to center (dax, day)
                    644:                wallfind[0] = -1;
                    645:                wallfind[1] = -1;
                    646:                for(i=startwall;i<endwall;i++)
                    647:                        if (wall[i].lotag == 6)
                    648:                        {
                    649:                                if (wallfind[0] == -1)
                    650:                                        wallfind[0] = i;
                    651:                                else
                    652:                                        wallfind[1] = i;
                    653:                        }
                    654: 
                    655:                for(j=0;j<2;j++)
                    656:                {
                    657:                        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))
                    658:                        {     //door was closed
                    659:                                        //find what direction door should open
                    660:                                i = wallfind[j]-1; if (i < startwall) i = endwall-1;
                    661:                                dax2 = wall[i].x-wall[wallfind[j]].x;
                    662:                                day2 = wall[i].y-wall[wallfind[j]].y;
                    663:                                if (dax2 != 0)
                    664:                                {
                    665:                                        dax2 = wall[wall[wall[wall[wallfind[j]].point2].point2].point2].x;
                    666:                                        dax2 -= wall[wall[wall[wallfind[j]].point2].point2].x;
                    667:                                        setanimation(&wall[wallfind[j]].x,wall[wallfind[j]].x+dax2,4L,0L);
                    668:                                        setanimation(&wall[i].x,wall[i].x+dax2,4L,0L);
                    669:                                        setanimation(&wall[wall[wallfind[j]].point2].x,wall[wall[wallfind[j]].point2].x+dax2,4L,0L);
                    670:                                        setanimation(&wall[wall[wall[wallfind[j]].point2].point2].x,wall[wall[wall[wallfind[j]].point2].point2].x+dax2,4L,0L);
                    671:                                }
                    672:                                else if (day2 != 0)
                    673:                                {
                    674:                                        day2 = wall[wall[wall[wall[wallfind[j]].point2].point2].point2].y;
                    675:                                        day2 -= wall[wall[wall[wallfind[j]].point2].point2].y;
                    676:                                        setanimation(&wall[wallfind[j]].y,wall[wallfind[j]].y+day2,4L,0L);
                    677:                                        setanimation(&wall[i].y,wall[i].y+day2,4L,0L);
                    678:                                        setanimation(&wall[wall[wallfind[j]].point2].y,wall[wall[wallfind[j]].point2].y+day2,4L,0L);
                    679:                                        setanimation(&wall[wall[wall[wallfind[j]].point2].point2].y,wall[wall[wall[wallfind[j]].point2].point2].y+day2,4L,0L);
                    680:                                }
                    681:                        }
                    682:                        else
                    683:                        {    //door was not closed
                    684:                                i = wallfind[j]-1; if (i < startwall) i = endwall-1;
                    685:                                dax2 = wall[i].x-wall[wallfind[j]].x;
                    686:                                day2 = wall[i].y-wall[wallfind[j]].y;
                    687:                                if (dax2 != 0)
                    688:                                {
                    689:                                        setanimation(&wall[wallfind[j]].x,centx,4L,0L);
                    690:                                        setanimation(&wall[i].x,centx+dax2,4L,0L);
                    691:                                        setanimation(&wall[wall[wallfind[j]].point2].x,centx,4L,0L);
                    692:                                        setanimation(&wall[wall[wall[wallfind[j]].point2].point2].x,centx+dax2,4L,0L);
                    693:                                }
                    694:                                else if (day2 != 0)
                    695:                                {
                    696:                                        setanimation(&wall[wallfind[j]].y,centy,4L,0L);
                    697:                                        setanimation(&wall[i].y,centy+day2,4L,0L);
                    698:                                        setanimation(&wall[wall[wallfind[j]].point2].y,centy,4L,0L);
                    699:                                        setanimation(&wall[wall[wall[wallfind[j]].point2].point2].y,centy+day2,4L,0L);
                    700:                                }
                    701:                        }
                    702:                }
                    703:                wsayfollow("updowndr.wav",4096L-64L,256L,&centx,&centy,0);
                    704:                wsayfollow("updowndr.wav",4096L+64L,256L,&centx,&centy,0);
                    705:        }
                    706: }
                    707: 
                    708: operatesprite(short dasprite)
                    709: {
                    710:        long datag;
                    711: 
                    712:        datag = sprite[dasprite].lotag;
                    713: 
                    714:        if (datag == 2)    //A sprite that shoots a bomb
                    715:        {
                    716:                shootgun(dasprite,
                    717:                                        sprite[dasprite].x,sprite[dasprite].y,sprite[dasprite].z,
                    718:                                        sprite[dasprite].ang,100L,sprite[dasprite].sectnum,2);
                    719:        }
                    720: }
                    721: 
                    722: changehealth(short snum, short deltahealth)
                    723: {
                    724:        long dax, day;
                    725:        short good, k, startwall, endwall, s;
                    726: 
                    727:        if (health[snum] > 0)
                    728:        {
                    729:                health[snum] += deltahealth;
                    730:                if (health[snum] > 999) health[snum] = 999;
                    731: 
                    732:                if (health[snum] <= 0)
                    733:                {
                    734:                        health[snum] = -1;
                    735:                        wsayfollow("death.wav",4096L+(krand()&127)-64,256L,&posx[snum],&posy[snum],1);
                    736:                        sprite[playersprite[snum]].picnum = SKELETON;
                    737:                }
                    738: 
                    739:                if ((snum == screenpeek) && (screensize <= xdim))
                    740:                {
                    741:                        if (health[snum] > 0)
                    742:                                sprintf(&tempbuf,"Health: %3d",health[snum]);
                    743:                        else
                    744:                                sprintf(&tempbuf,"YOU STINK!!");
                    745: 
                    746:                        printext((xdim>>1)-(strlen(tempbuf)<<2),ydim-24,tempbuf,ALPHABET,80);
                    747:                }
                    748:        }
                    749:        return(health[snum] <= 0);      //You were just injured
                    750: }
                    751: 
                    752: prepareboard(char *daboardfilename)
                    753: {
                    754:        short startwall, endwall, dasector;
                    755:        long i, j, k, s, dax, day, daz, dax2, day2;
                    756: 
                    757:        getmessageleng = 0;
                    758:        typemessageleng = 0;
                    759: 
                    760:        randomseed = 17L;
                    761: 
                    762:                //Clear (do)animation's list
                    763:        animatecnt = 0;
                    764:        typemode = 0;
                    765:        locselectedgun = 0;
                    766:        locselectedgun2 = 0;
                    767: 
                    768:        if (loadboard(daboardfilename,&posx[0],&posy[0],&posz[0],&ang[0],&cursectnum[0]) == -1)
                    769:        {
                    770:                musicoff();
                    771:                uninitmultiplayers();
                    772:                uninittimer();
                    773:                uninitkeys();
                    774:                uninitengine();
                    775:                uninitsb();
                    776:                uninitgroupfile();
                    777:                setvmode(0x3);        //Set back to text mode
                    778:                printf("Board not found\n");
                    779:                exit(0);
                    780:        }
                    781: 
                    782:        for(i=0;i<MAXPLAYERS;i++)
                    783:        {
                    784:                posx[i] = posx[0];
                    785:                posy[i] = posy[0];
                    786:                posz[i] = posz[0];
                    787:                ang[i] = ang[0];
                    788:                cursectnum[i] = cursectnum[0];
                    789:                ocursectnum[i] = cursectnum[0];
                    790:                horiz[i] = 100;
                    791:                lastchaingun[i] = 0;
                    792:                health[i] = 100;
                    793:                dimensionmode[i] = 3;
                    794:                numbombs[i] = 0;
                    795:                zoom[i] = 768L;
                    796:                deaths[i] = 0L;
                    797:                playersprite[i] = -1;
                    798:                screensize = xdim;
                    799:                flytime[i] = 0L;
                    800: 
                    801:                oposx[i] = posx[0];
                    802:                oposy[i] = posy[0];
                    803:                oposz[i] = posz[0];
                    804:                ohoriz[i] = horiz[0];
                    805:                ozoom[i] = zoom[0];
                    806:                oang[i] = ang[0];
                    807:        }
                    808: 
                    809:        movefifoplc = 0; movefifoend = 0;
                    810:        syncvalhead = 0L; othersyncvalhead = 0L; syncvaltail = 0L;
                    811:        numinterpolations = 0;
                    812: 
                    813:        setup3dscreen();
                    814: 
                    815:        oloc.fvel = oloc.svel = oloc.avel = oloc.bits = 0;
                    816:        for(i=0;i<MAXPLAYERS;i++)
                    817:        {
                    818:                fsync[i].fvel = sync[i].fvel = osync[i].fvel = 0;
                    819:                fsync[i].svel = sync[i].svel = osync[i].svel = 0;
                    820:                fsync[i].avel = sync[i].avel = osync[i].avel = 0;
                    821:                fsync[i].bits = sync[i].bits = osync[i].bits = 0;
                    822:        }
                    823: 
                    824:                //Scan sector tags
                    825: 
                    826:        for(i=0;i<MAXPLAYERS;i++)
                    827:        {
                    828:                waterfountainwall[i] = -1;
                    829:                waterfountaincnt[i] = 0;
                    830:        }
                    831:        slimesoundcnt[i] = 0;
                    832:        warpsectorcnt = 0;      //Make a list of warping sectors
                    833:        xpanningsectorcnt = 0;  //Make a list of wall x-panning sectors
                    834:        floorpanningcnt = 0;    //Make a list of slime sectors
                    835:        dragsectorcnt = 0;      //Make a list of moving platforms
                    836:        swingcnt = 0;           //Make a list of swinging doors
                    837:        revolvecnt = 0;         //Make a list of revolving doors
                    838:        subwaytrackcnt = 0;     //Make a list of subways
                    839: 
                    840:        floormirrorcnt = 0;
                    841:        tilesizx[FLOORMIRROR] = 0;
                    842:        tilesizy[FLOORMIRROR] = 0;
                    843: 
                    844:        for(i=0;i<numsectors;i++)
                    845:        {
                    846:                switch(sector[i].lotag)
                    847:                {
                    848:                        case 4:
                    849:                                floorpanninglist[floorpanningcnt++] = i;
                    850:                                break;
                    851:                        case 10:
                    852:                                warpsectorlist[warpsectorcnt++] = i;
                    853:                                break;
                    854:                        case 11:
                    855:                                xpanningsectorlist[xpanningsectorcnt++] = i;
                    856:                                break;
                    857:                        case 12:
                    858:                                dasector = i;
                    859:                                dax = 0x7fffffff;
                    860:                                day = 0x7fffffff;
                    861:                                dax2 = 0x80000000;
                    862:                                day2 = 0x80000000;
                    863:                                startwall = sector[i].wallptr;
                    864:                                endwall = startwall+sector[i].wallnum;
                    865:                                for(j=startwall;j<endwall;j++)
                    866:                                {
                    867:                                        if (wall[j].x < dax) dax = wall[j].x;
                    868:                                        if (wall[j].y < day) day = wall[j].y;
                    869:                                        if (wall[j].x > dax2) dax2 = wall[j].x;
                    870:                                        if (wall[j].y > day2) day2 = wall[j].y;
                    871:                                        if (wall[j].lotag == 3) k = j;
                    872:                                }
                    873:                                if (wall[k].x == dax) dragxdir[dragsectorcnt] = -16;
                    874:                                if (wall[k].y == day) dragydir[dragsectorcnt] = -16;
                    875:                                if (wall[k].x == dax2) dragxdir[dragsectorcnt] = 16;
                    876:                                if (wall[k].y == day2) dragydir[dragsectorcnt] = 16;
                    877: 
                    878:                                dasector = wall[startwall].nextsector;
                    879:                                dragx1[dragsectorcnt] = 0x7fffffff;
                    880:                                dragy1[dragsectorcnt] = 0x7fffffff;
                    881:                                dragx2[dragsectorcnt] = 0x80000000;
                    882:                                dragy2[dragsectorcnt] = 0x80000000;
                    883:                                startwall = sector[dasector].wallptr;
                    884:                                endwall = startwall+sector[dasector].wallnum;
                    885:                                for(j=startwall;j<endwall;j++)
                    886:                                {
                    887:                                        if (wall[j].x < dragx1[dragsectorcnt]) dragx1[dragsectorcnt] = wall[j].x;
                    888:                                        if (wall[j].y < dragy1[dragsectorcnt]) dragy1[dragsectorcnt] = wall[j].y;
                    889:                                        if (wall[j].x > dragx2[dragsectorcnt]) dragx2[dragsectorcnt] = wall[j].x;
                    890:                                        if (wall[j].y > dragy2[dragsectorcnt]) dragy2[dragsectorcnt] = wall[j].y;
                    891: 
                    892:                                        setinterpolation(&sector[dasector].floorz);
                    893:                                        setinterpolation(&wall[j].x);
                    894:                                        setinterpolation(&wall[j].y);
                    895:                                        setinterpolation(&wall[wall[j].nextwall].x);
                    896:                                        setinterpolation(&wall[wall[j].nextwall].y);
                    897:                                }
                    898: 
                    899:                                dragx1[dragsectorcnt] += (wall[sector[i].wallptr].x-dax);
                    900:                                dragy1[dragsectorcnt] += (wall[sector[i].wallptr].y-day);
                    901:                                dragx2[dragsectorcnt] -= (dax2-wall[sector[i].wallptr].x);
                    902:                                dragy2[dragsectorcnt] -= (day2-wall[sector[i].wallptr].y);
                    903: 
                    904:                                dragfloorz[dragsectorcnt] = sector[i].floorz;
                    905: 
                    906:                                dragsectorlist[dragsectorcnt++] = i;
                    907:                                break;
                    908:                        case 13:
                    909:                                startwall = sector[i].wallptr;
                    910:                                endwall = startwall+sector[i].wallnum;
                    911:                                for(j=startwall;j<endwall;j++)
                    912:                                {
                    913:                                        if (wall[j].lotag == 4)
                    914:                                        {
                    915:                                                k = wall[wall[wall[wall[j].point2].point2].point2].point2;
                    916:                                                if ((wall[j].x == wall[k].x) && (wall[j].y == wall[k].y))
                    917:                                                {     //Door opens counterclockwise
                    918:                                                        swingwall[swingcnt][0] = j;
                    919:                                                        swingwall[swingcnt][1] = wall[j].point2;
                    920:                                                        swingwall[swingcnt][2] = wall[wall[j].point2].point2;
                    921:                                                        swingwall[swingcnt][3] = wall[wall[wall[j].point2].point2].point2;
                    922:                                                        swingangopen[swingcnt] = 1536;
                    923:                                                        swingangclosed[swingcnt] = 0;
                    924:                                                        swingangopendir[swingcnt] = -1;
                    925:                                                }
                    926:                                                else
                    927:                                                {     //Door opens clockwise
                    928:                                                        swingwall[swingcnt][0] = wall[j].point2;
                    929:                                                        swingwall[swingcnt][1] = j;
                    930:                                                        swingwall[swingcnt][2] = lastwall(j);
                    931:                                                        swingwall[swingcnt][3] = lastwall(swingwall[swingcnt][2]);
                    932:                                                        swingwall[swingcnt][4] = lastwall(swingwall[swingcnt][3]);
                    933:                                                        swingangopen[swingcnt] = 512;
                    934:                                                        swingangclosed[swingcnt] = 0;
                    935:                                                        swingangopendir[swingcnt] = 1;
                    936:                                                }
                    937:                                                for(k=0;k<4;k++)
                    938:                                                {
                    939:                                                        swingx[swingcnt][k] = wall[swingwall[swingcnt][k]].x;
                    940:                                                        swingy[swingcnt][k] = wall[swingwall[swingcnt][k]].y;
                    941:                                                }
                    942: 
                    943:                                                swingsector[swingcnt] = i;
                    944:                                                swingang[swingcnt] = swingangclosed[swingcnt];
                    945:                                                swinganginc[swingcnt] = 0;
                    946:                                                swingcnt++;
                    947:                                        }
                    948:                                }
                    949:                                break;
                    950:                        case 14:
                    951:                                startwall = sector[i].wallptr;
                    952:                                endwall = startwall+sector[i].wallnum;
                    953:                                dax = 0L;
                    954:                                day = 0L;
                    955:                                for(j=startwall;j<endwall;j++)
                    956:                                {
                    957:                                        dax += wall[j].x;
                    958:                                        day += wall[j].y;
                    959:                                }
                    960:                                revolvepivotx[revolvecnt] = dax / (endwall-startwall);
                    961:                                revolvepivoty[revolvecnt] = day / (endwall-startwall);
                    962: 
                    963:                                k = 0;
                    964:                                for(j=startwall;j<endwall;j++)
                    965:                                {
                    966:                                        revolvex[revolvecnt][k] = wall[j].x;
                    967:                                        revolvey[revolvecnt][k] = wall[j].y;
                    968: 
                    969:                                        setinterpolation(&wall[j].x);
                    970:                                        setinterpolation(&wall[j].y);
                    971:                                        setinterpolation(&wall[wall[j].nextwall].x);
                    972:                                        setinterpolation(&wall[wall[j].nextwall].y);
                    973: 
                    974:                                        k++;
                    975:                                }
                    976:                                revolvesector[revolvecnt] = i;
                    977:                                revolveang[revolvecnt] = 0;
                    978: 
                    979:                                revolvecnt++;
                    980:                                break;
                    981:                        case 15:
                    982:                                subwaytracksector[subwaytrackcnt][0] = i;
                    983: 
                    984:                                subwaystopcnt[subwaytrackcnt] = 0;
                    985:                                dax = 0x7fffffff;
                    986:                                day = 0x7fffffff;
                    987:                                dax2 = 0x80000000;
                    988:                                day2 = 0x80000000;
                    989:                                startwall = sector[i].wallptr;
                    990:                                endwall = startwall+sector[i].wallnum;
                    991:                                for(j=startwall;j<endwall;j++)
                    992:                                {
                    993:                                        if (wall[j].x < dax) dax = wall[j].x;
                    994:                                        if (wall[j].y < day) day = wall[j].y;
                    995:                                        if (wall[j].x > dax2) dax2 = wall[j].x;
                    996:                                        if (wall[j].y > day2) day2 = wall[j].y;
                    997:                                }
                    998:                                for(j=startwall;j<endwall;j++)
                    999:                                {
                   1000:                                        if (wall[j].lotag == 5)
                   1001:                                        {
                   1002:                                                if ((wall[j].x > dax) && (wall[j].y > day) && (wall[j].x < dax2) && (wall[j].y < day2))
                   1003:                                                {
                   1004:                                                        subwayx[subwaytrackcnt] = wall[j].x;
                   1005:                                                }
                   1006:                                                else
                   1007:                                                {
                   1008:                                                        subwaystop[subwaytrackcnt][subwaystopcnt[subwaytrackcnt]] = wall[j].x;
                   1009:                                                        subwaystopcnt[subwaytrackcnt]++;
                   1010:                                                }
                   1011:                                        }
                   1012:                                }
                   1013: 
                   1014:                                for(j=1;j<subwaystopcnt[subwaytrackcnt];j++)
                   1015:                                        for(k=0;k<j;k++)
                   1016:                                                if (subwaystop[subwaytrackcnt][j] < subwaystop[subwaytrackcnt][k])
                   1017:                                                {
                   1018:                                                        s = subwaystop[subwaytrackcnt][j];
                   1019:                                                        subwaystop[subwaytrackcnt][j] = subwaystop[subwaytrackcnt][k];
                   1020:                                                        subwaystop[subwaytrackcnt][k] = s;
                   1021:                                                }
                   1022: 
                   1023:                                subwaygoalstop[subwaytrackcnt] = 0;
                   1024:                                for(j=0;j<subwaystopcnt[subwaytrackcnt];j++)
                   1025:                                        if (klabs(subwaystop[subwaytrackcnt][j]-subwayx[subwaytrackcnt]) < klabs(subwaystop[subwaytrackcnt][subwaygoalstop[subwaytrackcnt]]-subwayx[subwaytrackcnt]))
                   1026:                                                subwaygoalstop[subwaytrackcnt] = j;
                   1027: 
                   1028:                                subwaytrackx1[subwaytrackcnt] = dax;
                   1029:                                subwaytracky1[subwaytrackcnt] = day;
                   1030:                                subwaytrackx2[subwaytrackcnt] = dax2;
                   1031:                                subwaytracky2[subwaytrackcnt] = day2;
                   1032: 
                   1033:                                subwaynumsectors[subwaytrackcnt] = 1;
                   1034:                                for(j=0;j<numsectors;j++)
                   1035:                                        if (j != i)
                   1036:                                        {
                   1037:                                                startwall = sector[j].wallptr;
                   1038:                                                if (wall[startwall].x > subwaytrackx1[subwaytrackcnt])
                   1039:                                                        if (wall[startwall].y > subwaytracky1[subwaytrackcnt])
                   1040:                                                                if (wall[startwall].x < subwaytrackx2[subwaytrackcnt])
                   1041:                                                                        if (wall[startwall].y < subwaytracky2[subwaytrackcnt])
                   1042:                                                                        {
                   1043:                                                                                if (sector[j].floorz != sector[i].floorz)
                   1044:                                                                                {
                   1045:                                                                                        sector[j].ceilingstat |= 64;
                   1046:                                                                                        sector[j].floorstat |= 64;
                   1047:                                                                                }
                   1048:                                                                                subwaytracksector[subwaytrackcnt][subwaynumsectors[subwaytrackcnt]] = j;
                   1049:                                                                                subwaynumsectors[subwaytrackcnt]++;
                   1050:                                                                        }
                   1051:                                        }
                   1052: 
                   1053:                                subwayvel[subwaytrackcnt] = 64;
                   1054:                                subwaypausetime[subwaytrackcnt] = 720;
                   1055: 
                   1056:                                startwall = sector[i].wallptr;
                   1057:                                endwall = startwall+sector[i].wallnum;
                   1058:                                for(k=startwall;k<endwall;k++)
                   1059:                                        if (wall[k].x > subwaytrackx1[subwaytrackcnt])
                   1060:                                                if (wall[k].y > subwaytracky1[subwaytrackcnt])
                   1061:                                                        if (wall[k].x < subwaytrackx2[subwaytrackcnt])
                   1062:                                                                if (wall[k].y < subwaytracky2[subwaytrackcnt])
                   1063:                                                                        setinterpolation(&wall[k].x);
                   1064: 
                   1065:                                for(j=1;j<subwaynumsectors[subwaytrackcnt];j++)
                   1066:                                {
                   1067:                                        dasector = subwaytracksector[subwaytrackcnt][j];
                   1068: 
                   1069:                                        startwall = sector[dasector].wallptr;
                   1070:                                        endwall = startwall+sector[dasector].wallnum;
                   1071:                                        for(k=startwall;k<endwall;k++)
                   1072:                                                setinterpolation(&wall[k].x);
                   1073: 
                   1074:                                        for(k=headspritesect[dasector];k>=0;k=nextspritesect[k])
                   1075:                                                if (statrate[sprite[k].statnum] < 0)
                   1076:                                                        setinterpolation(&sprite[k].x);
                   1077:                                }
                   1078: 
                   1079: 
                   1080:                                subwaytrackcnt++;
                   1081:                                break;
                   1082:                }
                   1083:                if (sector[i].floorpicnum == FLOORMIRROR)
                   1084:                        floormirrorsector[mirrorcnt++] = i;
                   1085:        }
                   1086: 
                   1087:                //Scan wall tags
                   1088: 
                   1089:        mirrorcnt = 0;
                   1090:        tilesizx[MIRROR] = 0;
                   1091:        tilesizy[MIRROR] = 0;
                   1092:        for(i=0;i<MAXMIRRORS;i++)
                   1093:        {
                   1094:                tilesizx[i+MIRRORLABEL] = 0;
                   1095:                tilesizy[i+MIRRORLABEL] = 0;
                   1096:        }
                   1097: 
                   1098:        ypanningwallcnt = 0;
                   1099:        for(i=0;i<numwalls;i++)
                   1100:        {
                   1101:                if (wall[i].lotag == 1) ypanningwalllist[ypanningwallcnt++] = i;
                   1102:                s = wall[i].nextsector;
                   1103:                if ((s >= 0) && (wall[i].overpicnum == MIRROR) && (wall[i].cstat&32))
                   1104:                {
                   1105:                        if ((sector[s].floorstat&1) == 0)
                   1106:                        {
                   1107:                                wall[i].overpicnum = MIRRORLABEL+mirrorcnt;
                   1108:                                sector[s].ceilingpicnum = MIRRORLABEL+mirrorcnt;
                   1109:                                sector[s].floorpicnum = MIRRORLABEL+mirrorcnt;
                   1110:                                sector[s].floorstat |= 1;
                   1111:                                mirrorwall[mirrorcnt] = i;
                   1112:                                mirrorsector[mirrorcnt] = s;
                   1113:                                mirrorcnt++;
                   1114:                        }
                   1115:                        else
                   1116:                                wall[i].overpicnum = sector[s].ceilingpicnum;
                   1117:                }
                   1118:        }
                   1119: 
                   1120:                //Invalidate textures in sector behind mirror
                   1121:        for(i=0;i<mirrorcnt;i++)
                   1122:        {
                   1123:                k = mirrorsector[i];
                   1124:                startwall = sector[k].wallptr;
                   1125:                endwall = startwall + sector[k].wallnum;
                   1126:                for(j=startwall;j<endwall;j++)
                   1127:                {
                   1128:                        wall[j].picnum = MIRROR;
                   1129:                        wall[j].overpicnum = MIRROR;
                   1130:                }
                   1131:        }
                   1132: 
                   1133:                //Scan sprite tags&picnum's
                   1134: 
                   1135:        turnspritecnt = 0;
                   1136:        for(i=0;i<MAXSPRITES;i++)
                   1137:        {
                   1138:                if (sprite[i].lotag == 3) turnspritelist[turnspritecnt++] = i;
                   1139: 
                   1140:                if (sprite[i].statnum < MAXSTATUS)    //That is, if sprite exists
                   1141:                        switch(sprite[i].picnum)
                   1142:                        {
                   1143:                                case BROWNMONSTER:              //All cases here put the sprite
                   1144:                                        if ((sprite[i].cstat&128) == 0)
                   1145:                                        {
                   1146:                                                sprite[i].z -= ((tilesizy[sprite[i].picnum]*sprite[i].yrepeat)<<1);
                   1147:                                                sprite[i].cstat |= 128;
                   1148:                                        }
                   1149:                                        sprite[i].extra = 0;
                   1150:                                        sprite[i].clipdist = mulscale7(sprite[i].xrepeat,tilesizx[sprite[i].picnum]);
                   1151:                                        if (sprite[i].statnum != 1) changespritestat(i,2);   //on waiting for you (list 2)
                   1152:                                        sprite[i].lotag = mulscale5(sprite[i].xrepeat,sprite[i].yrepeat);
                   1153:                                        sprite[i].cstat |= 0x101;    //Set the hitscan sensitivity bit
                   1154:                                        break;
                   1155:                                case AL:
                   1156:                                        sprite[i].cstat |= 0x101;    //Set the hitscan sensitivity bit
                   1157:                                        changespritestat(i,0);
                   1158:                                        break;
                   1159:                                case EVILAL:
                   1160:                                        sprite[i].cstat |= 0x101;    //Set the hitscan sensitivity bit
                   1161:                                        changespritestat(i,10);
                   1162:                                        break;
                   1163:                        }
                   1164:        }
                   1165: 
                   1166:        for(i=MAXSPRITES-1;i>=0;i--) copybuf(&sprite[i].x,&osprite[i].x,3);
                   1167: 
                   1168:        searchmap(cursectnum[connecthead]);
                   1169: 
                   1170:        lockclock = 0;
                   1171:        ototalclock = 0;
                   1172:        gotlastpacketclock = 0;
                   1173: 
                   1174:        screensize = xdim;
                   1175:        dax = ((xdim-screensize)>>1);
                   1176:        dax2 = dax+screensize-1;
                   1177:        day = (((ydim-32)-scale(screensize,ydim-32,xdim))>>1);
                   1178:        day2 = day + scale(screensize,ydim-32,xdim)-1;
                   1179:        setview(dax,day,dax2,day2);
                   1180: 
                   1181:        startofdynamicinterpolations = numinterpolations;
                   1182: }
                   1183: 
                   1184: checktouchsprite(short snum, short sectnum)
                   1185: {
                   1186:        long i, nexti;
                   1187: 
                   1188:        if ((sectnum < 0) || (sectnum >= numsectors)) return;
                   1189: 
                   1190:        for(i=headspritesect[sectnum];i>=0;i=nexti)
                   1191:        {
                   1192:                nexti = nextspritesect[i];
                   1193:                if (sprite[i].cstat&0x8000) continue;
                   1194:                if ((klabs(posx[snum]-sprite[i].x)+klabs(posy[snum]-sprite[i].y) < 512) && (klabs((posz[snum]>>8)-((sprite[i].z>>8)-(tilesizy[sprite[i].picnum]>>1))) <= 40))
                   1195:                {
                   1196:                        switch(sprite[i].picnum)
                   1197:                        {
                   1198:                                case COINSTACK:
                   1199:                                        wsayfollow("getstuff.wav",4096L+(krand()&127)-64,256L,&sprite[i].x,&sprite[i].y,0);
                   1200:                                        changehealth(snum,25);
                   1201:                                        sprite[i].cstat |= 0x8000;
                   1202:                                        sprite[i].extra = 120*180;
                   1203:                                        changespritestat((short)i,11);
                   1204:                                        break;
                   1205:                                case GIFTBOX:
                   1206:                                        wsayfollow("getstuff.wav",4096L+(krand()&127)+256-mulscale4(sprite[i].xrepeat,sprite[i].yrepeat),208L,&sprite[i].x,&sprite[i].y,0);
                   1207:                                        changehealth(snum,max(mulscale8(sprite[i].xrepeat,sprite[i].yrepeat),1));
                   1208:                                        deletesprite((short)i);
                   1209:                                        break;
                   1210:                                case COIN:
                   1211:                                        wsayfollow("getstuff.wav",4096L+(krand()&127)-64,192L,&sprite[i].x,&sprite[i].y,0);
                   1212:                                        changehealth(snum,5);
                   1213:                                        sprite[i].cstat |= 0x8000;
                   1214:                                        sprite[i].extra = 120*60;
                   1215:                                        changespritestat((short)i,11);
                   1216:                                        break;
                   1217:                                case DIAMONDS:
                   1218:                                        wsayfollow("getstuff.wav",4096L+(krand()&127)-64,256L,&sprite[i].x,&sprite[i].y,0);
                   1219:                                        changehealth(snum,15);
                   1220:                                        sprite[i].cstat |= 0x8000;
                   1221:                                        sprite[i].extra = 120*120;
                   1222:                                        changespritestat((short)i,11);
                   1223:                                        break;
                   1224:                                case CANON:
                   1225:                                        wsayfollow("getstuff.wav",3584L+(krand()&127)-64,256L,&sprite[i].x,&sprite[i].y,0);
                   1226:                                        if (snum == myconnectindex) keystatus[4] = 1;
                   1227:                                        numbombs[snum] += ((sprite[i].xrepeat+sprite[i].yrepeat)>>1);
                   1228:                                        sprite[i].cstat |= 0x8000;
                   1229:                                        sprite[i].extra = 60*(sprite[i].xrepeat+sprite[i].yrepeat);
                   1230:                                        changespritestat((short)i,11);
                   1231:                                        break;
                   1232:                                case AIRPLANE:
                   1233:                                        wsayfollow("getstuff.wav",4096L+(krand()&127)-64,256L,&sprite[i].x,&sprite[i].y,0);
                   1234:                                        if (flytime[snum] < lockclock) flytime[snum] = lockclock;
                   1235:                                        flytime[snum] += 60*(sprite[i].xrepeat+sprite[i].yrepeat);
                   1236:                                        sprite[i].cstat |= 0x8000;
                   1237:                                        sprite[i].extra = 120*(sprite[i].xrepeat+sprite[i].yrepeat);
                   1238:                                        changespritestat((short)i,11);
                   1239:                                        break;
                   1240:                        }
                   1241:                }
                   1242:        }
                   1243: }
                   1244: 
                   1245: shootgun(short snum, long x, long y, long z,
                   1246:                        short daang, long dahoriz, short dasectnum, char guntype)
                   1247: {
                   1248:        short hitsect, hitwall, hitsprite, daang2;
                   1249:        long i, j, daz2, hitx, hity, hitz;
                   1250: 
                   1251:        switch(guntype)
                   1252:        {
                   1253:                case 0:    //Shoot silver sphere bullet
                   1254:                        spawnsprite(j,x,y,z,1+128,0,0,16,64,64,0,0,BULLET,daang,
                   1255:                                                  sintable[(daang+512)&2047]>>5,sintable[daang&2047]>>5,
                   1256:                                                  (100-dahoriz)<<6,snum+4096,dasectnum,6,0,0,0);
                   1257:                        wsayfollow("shoot2.wav",4096L+(krand()&127)-64,184L,&sprite[j].x,&sprite[j].y,1);
                   1258:                        break;
                   1259:                case 1:    //Shoot chain gun
                   1260:                        daang2 = ((daang + (krand()&31)-16)&2047);
                   1261:                        daz2 = ((100-dahoriz)*2000) + ((krand()-32768)>>1);
                   1262: 
                   1263:                        hitscan(x,y,z,dasectnum,                   //Start position
                   1264:                                sintable[(daang2+512)&2047],            //X vector of 3D ang
                   1265:                                sintable[daang2&2047],                  //Y vector of 3D ang
                   1266:                                daz2,                                   //Z vector of 3D ang
                   1267:                                &hitsect,&hitwall,&hitsprite,&hitx,&hity,&hitz);
                   1268: 
                   1269:                        if (wall[hitwall].picnum == KENPICTURE)
                   1270:                        {
                   1271:                                if (waloff[4095] != 0) wall[hitwall].picnum = 4095;
                   1272:                                wsayfollow("hello.wav",4096L+(krand()&127)-64,256L,&wall[hitwall].x,&wall[hitwall].y,0);
                   1273:                        }
                   1274:                        else if (((hitwall < 0) && (hitsprite < 0) && (hitz >= z) && ((sector[hitsect].floorpicnum == SLIME) || (sector[hitsect].floorpicnum == FLOORMIRROR))) || ((hitwall >= 0) && (wall[hitwall].picnum == SLIME)))
                   1275:                        {    //If you shoot slime, make a splash
                   1276:                                wsayfollow("splash.wav",4096L+(krand()&511)-256,256L,&hitx,&hity,0);
                   1277:                                spawnsprite(j,hitx,hity,hitz,2,0,0,32,64,64,0,0,SPLASH,daang,
                   1278:                                        0,0,0,snum+4096,hitsect,4,63,0,0); //63=time left for splash
                   1279:                        }
                   1280:                        else
                   1281:                        {
                   1282:                                wsayfollow("shoot.wav",4096L+(krand()&127)-64,256L,&hitx,&hity,0);
                   1283: 
                   1284:                                if ((hitsprite >= 0) && (sprite[hitsprite].statnum < MAXSTATUS))
                   1285:                                        switch(sprite[hitsprite].picnum)
                   1286:                                        {
                   1287:                                                case BROWNMONSTER:
                   1288:                                                        if (sprite[hitsprite].lotag > 0) sprite[hitsprite].lotag -= 10;
                   1289:                                                        if (sprite[hitsprite].lotag > 0)
                   1290:                                                        {
                   1291:                                                                wsayfollow("hurt.wav",4096L+(krand()&511)-256,256L,&hitx,&hity,0);
                   1292:                                                                if (sprite[hitsprite].lotag <= 25)
                   1293:                                                                        sprite[hitsprite].cstat |= 2;
                   1294:                                                        }
                   1295:                                                        else
                   1296:                                                        {
                   1297:                                                                wsayfollow("blowup.wav",4096L+(krand()&127)-64,256L,&hitx,&hity,0);
                   1298:                                                                sprite[hitsprite].z += ((tilesizy[sprite[hitsprite].picnum]*sprite[hitsprite].yrepeat)<<1);
                   1299:                                                                sprite[hitsprite].picnum = GIFTBOX;
                   1300:                                                                sprite[hitsprite].cstat &= ~0x83;    //Should not clip, foot-z
                   1301:                                                                changespritestat(hitsprite,0);
                   1302: 
                   1303:                                                                spawnsprite(j,hitx,hity,hitz+(32<<8),0,-4,0,32,64,64,
                   1304:                                                                        0,0,EXPLOSION,daang,0,0,0,snum+4096,
                   1305:                                                                        hitsect,5,31,0,0);
                   1306:                                                        }
                   1307:                                                        break;
                   1308:                                                case EVILAL:
                   1309:                                                        wsayfollow("blowup.wav",4096L+(krand()&127)-64,256L,&hitx,&hity,0);
                   1310:                                                        sprite[hitsprite].picnum = EVILALGRAVE;
                   1311:                                                        sprite[hitsprite].cstat = 0;
                   1312:                                                        sprite[hitsprite].lotag = 255;
                   1313:                                                        sprite[hitsprite].xvel = (krand()&255)-128;
                   1314:                                                        sprite[hitsprite].yvel = (krand()&255)-128;
                   1315:                                                        sprite[hitsprite].zvel = (krand()&4095)-3072;
                   1316:                                                        changespritestat(hitsprite,9);
                   1317: 
                   1318:                                                        spawnsprite(j,hitx,hity,hitz+(32<<8),0,-4,0,32,64,64,0,
                   1319:                                                                0,EXPLOSION,daang,0,0,0,snum+4096,hitsect,5,31,0,0);
                   1320:                                                                 //31=time left for explosion
                   1321: 
                   1322:                                                        break;
                   1323:                                                case DOOMGUY:
                   1324:                                                        for(j=connecthead;j>=0;j=connectpoint2[j])
                   1325:                                                                if (playersprite[j] == hitsprite)
                   1326:                                                                {
                   1327:                                                                        wsayfollow("ouch.wav",4096L+(krand()&127)-64,256L,&hitx,&hity,0);
                   1328:                                                                        changehealth(j,-10);
                   1329:                                                                        break;
                   1330:                                                                }
                   1331:                                                        break;
                   1332:                                        }
                   1333: 
                   1334:                                spawnsprite(j,hitx,hity,hitz+(8<<8),2,-4,0,32,16,16,0,0,
                   1335:                                        EXPLOSION,daang,0,0,0,snum+4096,hitsect,3,63,0,0);
                   1336: 
                   1337:                                        //Sprite starts out with center exactly on wall.
                   1338:                                        //This moves it back enough to see it at all angles.
                   1339:                                movesprite((short)j,-(((long)sintable[(512+daang)&2047]*TICSPERFRAME)<<4),-(((long)sintable[daang]*TICSPERFRAME)<<4),0L,4L<<8,4L<<8,1);
                   1340:                        }
                   1341:                        break;
                   1342:                case 2:    //Shoot bomb
                   1343:                  spawnsprite(j,x,y,z,128,0,0,12,16,16,0,0,BOMB,daang,
                   1344:                          sintable[(daang+512)&2047]*5>>8,sintable[daang&2047]*5>>8,
                   1345:                          (80-dahoriz)<<6,snum+4096,dasectnum,6,0,0,0);
                   1346: 
                   1347:                        wsayfollow("shoot3.wav",4096L+(krand()&127)-64,256L,&sprite[j].x,&sprite[j].y,1);
                   1348:                        break;
                   1349:        }
                   1350: }
                   1351: 
                   1352: analyzesprites(long dax, long day)
                   1353: {
                   1354:        long i, j, k;
                   1355:        point3d *ospr;
                   1356:        spritetype *tspr;
                   1357: 
                   1358:                //This function is called between drawrooms() and drawmasks()
                   1359:                //It has a list of possible sprites that may be drawn on this frame
                   1360: 
                   1361:        for(i=0,tspr=&tsprite[0];i<spritesortcnt;i++,tspr++)
                   1362:        {
                   1363:                switch(tspr->picnum)
                   1364:                {
                   1365:                        case DOOMGUY:
                   1366:                                        //Get which of the 8 angles of the sprite to draw (0-7)
                   1367:                                        //k ranges from 0-7
                   1368:                                k = getangle(tspr->x-dax,tspr->y-day);
                   1369:                                k = (((tspr->ang+3072+128-k)&2047)>>8)&7;
                   1370:                                        //This guy has only 5 pictures for 8 angles (3 are x-flipped)
                   1371:                                if (k <= 4)
                   1372:                                {
                   1373:                                        tspr->picnum += (k<<2);
                   1374:                                        tspr->cstat &= ~4;   //clear x-flipping bit
                   1375:                                }
                   1376:                                else
                   1377:                                {
                   1378:                                        tspr->picnum += ((8-k)<<2);
                   1379:                                        tspr->cstat |= 4;    //set x-flipping bit
                   1380:                                }
                   1381:                                break;
                   1382:                }
                   1383: 
                   1384:                k = statrate[tspr->statnum];
                   1385:                if (k >= 0)  //Interpolate moving sprite
                   1386:                {
                   1387:                        ospr = &osprite[tspr->owner];
                   1388:                        switch(k)
                   1389:                        {
                   1390:                                case 0: j = smoothratio; break;
                   1391:                                case 1: j = (smoothratio>>1)+(((nummoves-tspr->owner)&1)<<15); break;
                   1392:                                case 3: j = (smoothratio>>2)+(((nummoves-tspr->owner)&3)<<14); break;
                   1393:                                case 7: j = (smoothratio>>3)+(((nummoves-tspr->owner)&7)<<13); break;
                   1394:                                case 15: j = (smoothratio>>4)+(((nummoves-tspr->owner)&15)<<12); break;
                   1395:                        }
                   1396:                        k = tspr->x-ospr->x; tspr->x = ospr->x;
                   1397:                        if (k != 0) tspr->x += mulscale16(k,j);
                   1398:                        k = tspr->y-ospr->y; tspr->y = ospr->y;
                   1399:                        if (k != 0) tspr->y += mulscale16(k,j);
                   1400:                        k = tspr->z-ospr->z; tspr->z = ospr->z;
                   1401:                        if (k != 0) tspr->z += mulscale16(k,j);
                   1402:                }
                   1403: 
                   1404:                        //Don't allow close explosion sprites to be transluscent
                   1405:                k = tspr->statnum;
                   1406:                if ((k == 3) || (k == 4) || (k == 5) || (k == 7))
                   1407:                        if (klabs(dax-tspr->x) < 256)
                   1408:                                if (klabs(day-tspr->y) < 256)
                   1409:                                        tspr->cstat &= ~2;
                   1410: 
                   1411:                tspr->shade += 6;
                   1412:                if (sector[tspr->sectnum].ceilingstat&1)
                   1413:                        tspr->shade += sector[tspr->sectnum].ceilingshade;
                   1414:                else
                   1415:                        tspr->shade += sector[tspr->sectnum].floorshade;
                   1416:        }
                   1417: }
                   1418: 
                   1419: tagcode()
                   1420: {
                   1421:        long i, nexti, j, k, l, s, dax, day, daz, dax2, day2, cnt, good;
                   1422:        short startwall, endwall, dasector, p, oldang;
                   1423: 
                   1424:        for(p=connecthead;p>=0;p=connectpoint2[p])
                   1425:        {
                   1426:                if (sector[cursectnum[p]].lotag == 1)
                   1427:                {
                   1428:                        activatehitag(sector[cursectnum[p]].hitag);
                   1429:                        sector[cursectnum[p]].lotag = 0;
                   1430:                        sector[cursectnum[p]].hitag = 0;
                   1431:                }
                   1432:                if ((sector[cursectnum[p]].lotag == 2) && (cursectnum[p] != ocursectnum[p]))
                   1433:                        activatehitag(sector[cursectnum[p]].hitag);
                   1434:        }
                   1435: 
                   1436:        for(i=0;i<warpsectorcnt;i++)
                   1437:        {
                   1438:                dasector = warpsectorlist[i];
                   1439:                j = ((lockclock&127)>>2);
                   1440:                if (j >= 16) j = 31-j;
                   1441:                {
                   1442:                        sector[dasector].ceilingshade = j;
                   1443:                        sector[dasector].floorshade = j;
                   1444:                        startwall = sector[dasector].wallptr;
                   1445:                        endwall = startwall+sector[dasector].wallnum;
                   1446:                        for(s=startwall;s<endwall;s++)
                   1447:                                wall[s].shade = j;
                   1448:                }
                   1449:        }
                   1450: 
                   1451:        for(p=connecthead;p>=0;p=connectpoint2[p])
                   1452:                if (sector[cursectnum[p]].lotag == 10)  //warp sector
                   1453:                {
                   1454:                        if (cursectnum[p] != ocursectnum[p])
                   1455:                        {
                   1456:                                warpsprite(playersprite[p]);
                   1457:                                posx[p] = sprite[playersprite[p]].x;
                   1458:                                posy[p] = sprite[playersprite[p]].y;
                   1459:                                posz[p] = sprite[playersprite[p]].z;
                   1460:                                ang[p] = sprite[playersprite[p]].ang;
                   1461:                                cursectnum[p] = sprite[playersprite[p]].sectnum;
                   1462: 
                   1463:                                sprite[playersprite[p]].z += (32<<8);
                   1464: 
                   1465:                                //warp(&posx[p],&posy[p],&posz[p],&ang[p],&cursectnum[p]);
                   1466:                                        //Update sprite representation of player
                   1467:                                //setsprite(playersprite[p],posx[p],posy[p],posz[p]+(32<<8));
                   1468:                                //sprite[playersprite[p]].ang = ang[p];
                   1469:                        }
                   1470:                }
                   1471: 
                   1472:        for(i=0;i<xpanningsectorcnt;i++)   //animate wall x-panning sectors
                   1473:        {
                   1474:                dasector = xpanningsectorlist[i];
                   1475: 
                   1476:                startwall = sector[dasector].wallptr;
                   1477:                endwall = startwall+sector[dasector].wallnum;
                   1478:                for(s=startwall;s<endwall;s++)
                   1479:                        wall[s].xpanning = ((lockclock>>2)&255);
                   1480:        }
                   1481: 
                   1482:        for(i=0;i<ypanningwallcnt;i++)
                   1483:                wall[ypanningwalllist[i]].ypanning = ~(lockclock&255);
                   1484: 
                   1485:        for(i=0;i<turnspritecnt;i++)
                   1486:        {
                   1487:                sprite[turnspritelist[i]].ang += (TICSPERFRAME<<2);
                   1488:                sprite[turnspritelist[i]].ang &= 2047;
                   1489:        }
                   1490: 
                   1491:        for(i=0;i<floorpanningcnt;i++)   //animate floor of slime sectors
                   1492:        {
                   1493:                sector[floorpanninglist[i]].floorxpanning = ((lockclock>>2)&255);
                   1494:                sector[floorpanninglist[i]].floorypanning = ((lockclock>>2)&255);
                   1495:        }
                   1496: 
                   1497:        for(i=0;i<dragsectorcnt;i++)
                   1498:        {
                   1499:                dasector = dragsectorlist[i];
                   1500: 
                   1501:                startwall = sector[dasector].wallptr;
                   1502:                endwall = startwall+sector[dasector].wallnum;
                   1503: 
                   1504:                if (wall[startwall].x+dragxdir[i] < dragx1[i]) dragxdir[i] = 16;
                   1505:                if (wall[startwall].y+dragydir[i] < dragy1[i]) dragydir[i] = 16;
                   1506:                if (wall[startwall].x+dragxdir[i] > dragx2[i]) dragxdir[i] = -16;
                   1507:                if (wall[startwall].y+dragydir[i] > dragy2[i]) dragydir[i] = -16;
                   1508: 
                   1509:                for(j=startwall;j<endwall;j++)
                   1510:                        dragpoint(j,wall[j].x+dragxdir[i],wall[j].y+dragydir[i]);
                   1511:                j = sector[dasector].floorz;
                   1512:                sector[dasector].floorz = dragfloorz[i]+(sintable[(lockclock<<4)&2047]>>3);
                   1513: 
                   1514:                for(p=connecthead;p>=0;p=connectpoint2[p])
                   1515:                        if (cursectnum[p] == dasector)
                   1516:                        {
                   1517:                                posx[p] += dragxdir[i];
                   1518:                                posy[p] += dragydir[i];
                   1519:                                //posz[p] += (sector[dasector].floorz-j);
                   1520: 
                   1521:                                        //Update sprite representation of player
                   1522:                                setsprite(playersprite[p],posx[p],posy[p],posz[p]+(32<<8));
                   1523:                                sprite[playersprite[p]].ang = ang[p];
                   1524:                        }
                   1525:        }
                   1526: 
                   1527:        for(i=0;i<swingcnt;i++)
                   1528:        {
                   1529:                if (swinganginc[i] != 0)
                   1530:                {
                   1531:                        oldang = swingang[i];
                   1532:                        for(j=0;j<(TICSPERFRAME<<2);j++)
                   1533:                        {
                   1534:                                swingang[i] = ((swingang[i]+swinganginc[i])&2047);
                   1535:                                if (swingang[i] == swingangclosed[i])
                   1536:                                {
                   1537:                                        wsayfollow("closdoor.wav",4096L+(krand()&511)-256,256L,&swingx[i][0],&swingy[i][0],0);
                   1538:                                        swinganginc[i] = 0;
                   1539:                                }
                   1540:                                if (swingang[i] == swingangopen[i]) swinganginc[i] = 0;
                   1541:                        }
                   1542:                        for(k=1;k<=3;k++)
                   1543:                                rotatepoint(swingx[i][0],swingy[i][0],swingx[i][k],swingy[i][k],swingang[i],&wall[swingwall[i][k]].x,&wall[swingwall[i][k]].y);
                   1544: 
                   1545:                        if (swinganginc[i] != 0)
                   1546:                        {
                   1547:                                for(p=connecthead;p>=0;p=connectpoint2[p])
                   1548:                                        if ((cursectnum[p] == swingsector[i]) || (testneighborsectors(cursectnum[p],swingsector[i]) == 1))
                   1549:                                        {
                   1550:                                                cnt = 256;
                   1551:                                                do
                   1552:                                                {
                   1553:                                                        good = 1;
                   1554: 
                   1555:                                                                //swingangopendir is -1 if forwards, 1 is backwards
                   1556:                                                        l = (swingangopendir[i] > 0);
                   1557:                                                        for(k=l+3;k>=l;k--)
                   1558:                                                                if (clipinsidebox(posx[p],posy[p],swingwall[i][k],128L) != 0)
                   1559:                                                                {
                   1560:                                                                        good = 0;
                   1561:                                                                        break;
                   1562:                                                                }
                   1563:                                                        if (good == 0)
                   1564:                                                        {
                   1565:                                                                if (cnt == 256)
                   1566:                                                                {
                   1567:                                                                        swinganginc[i] = -swinganginc[i];
                   1568:                                                                        swingang[i] = oldang;
                   1569:                                                                }
                   1570:                                                                else
                   1571:                                                                {
                   1572:                                                                        swingang[i] = ((swingang[i]-swinganginc[i])&2047);
                   1573:                                                                }
                   1574:                                                                for(k=1;k<=3;k++)
                   1575:                                                                        rotatepoint(swingx[i][0],swingy[i][0],swingx[i][k],swingy[i][k],swingang[i],&wall[swingwall[i][k]].x,&wall[swingwall[i][k]].y);
                   1576:                                                                if (swingang[i] == swingangclosed[i])
                   1577:                                                                {
                   1578:                                                                        wsayfollow("closdoor.wav",4096L+(krand()&511)-256,256L,&swingx[i][0],&swingy[i][0],0);
                   1579:                                                                        swinganginc[i] = 0;
                   1580:                                                                        break;
                   1581:                                                                }
                   1582:                                                                if (swingang[i] == swingangopen[i])
                   1583:                                                                {
                   1584:                                                                        swinganginc[i] = 0;
                   1585:                                                                        break;
                   1586:                                                                }
                   1587:                                                                cnt--;
                   1588:                                                        }
                   1589:                                                } while ((good == 0) && (cnt > 0));
                   1590:                                        }
                   1591:                        }
                   1592:                }
                   1593:                if (swinganginc[i] == 0)
                   1594:                        for(j=1;j<=3;j++)
                   1595:                        {
                   1596:                                stopinterpolation(&wall[swingwall[i][j]].x);
                   1597:                                stopinterpolation(&wall[swingwall[i][j]].y);
                   1598:                        }
                   1599:        }
                   1600: 
                   1601:        for(i=0;i<revolvecnt;i++)
                   1602:        {
                   1603:                startwall = sector[revolvesector[i]].wallptr;
                   1604:                endwall = startwall + sector[revolvesector[i]].wallnum;
                   1605: 
                   1606:                revolveang[i] = ((revolveang[i]-(TICSPERFRAME<<2))&2047);
                   1607:                for(k=startwall;k<endwall;k++)
                   1608:                {
                   1609:                        rotatepoint(revolvepivotx[i],revolvepivoty[i],revolvex[i][k-startwall],revolvey[i][k-startwall],revolveang[i],&dax,&day);
                   1610:                        dragpoint(k,dax,day);
                   1611:                }
                   1612:        }
                   1613: 
                   1614:        for(i=0;i<subwaytrackcnt;i++)
                   1615:        {
                   1616:                if ((subwayvel[i] < -2) || (subwayvel[i] > 2))
                   1617:                {
                   1618:                        dasector = subwaytracksector[i][0];
                   1619:                        startwall = sector[dasector].wallptr;
                   1620:                        endwall = startwall+sector[dasector].wallnum;
                   1621:                        for(k=startwall;k<endwall;k++)
                   1622:                                if (wall[k].x > subwaytrackx1[i])
                   1623:                                        if (wall[k].y > subwaytracky1[i])
                   1624:                                                if (wall[k].x < subwaytrackx2[i])
                   1625:                                                        if (wall[k].y < subwaytracky2[i])
                   1626:                                                                wall[k].x += subwayvel[i];
                   1627: 
                   1628:                        for(j=1;j<subwaynumsectors[i];j++)
                   1629:                        {
                   1630:                                dasector = subwaytracksector[i][j];
                   1631: 
                   1632:                                startwall = sector[dasector].wallptr;
                   1633:                                endwall = startwall+sector[dasector].wallnum;
                   1634:                                for(k=startwall;k<endwall;k++)
                   1635:                                        wall[k].x += subwayvel[i];
                   1636: 
                   1637:                                for(s=headspritesect[dasector];s>=0;s=nextspritesect[s])
                   1638:                                        sprite[s].x += subwayvel[i];
                   1639:                        }
                   1640: 
                   1641:                        for(p=connecthead;p>=0;p=connectpoint2[p])
                   1642:                                if (cursectnum[p] != subwaytracksector[i][0])
                   1643:                                        if (sector[cursectnum[p]].floorz != sector[subwaytracksector[i][0]].floorz)
                   1644:                                                if (posx[p] > subwaytrackx1[i])
                   1645:                                                        if (posy[p] > subwaytracky1[i])
                   1646:                                                                if (posx[p] < subwaytrackx2[i])
                   1647:                                                                        if (posy[p] < subwaytracky2[i])
                   1648:                                                                        {
                   1649:                                                                                posx[p] += subwayvel[i];
                   1650: 
                   1651:                                                                                        //Update sprite representation of player
                   1652:                                                                                setsprite(playersprite[p],posx[p],posy[p],posz[p]+(32<<8));
                   1653:                                                                                sprite[playersprite[p]].ang = ang[p];
                   1654:                                                                        }
                   1655: 
                   1656:                        subwayx[i] += subwayvel[i];
                   1657:                }
                   1658: 
                   1659:                j = subwayvel[i];
                   1660:                k = subwaystop[i][subwaygoalstop[i]] - subwayx[i];
                   1661:                if (k > 0)
                   1662:                {
                   1663:                        if (k > 4096)
                   1664:                        {
                   1665:                                if (subwayvel[i] < 256) subwayvel[i]++;
                   1666:                        }
                   1667:                        else
                   1668:                                subwayvel[i] = (k>>4)+1;
                   1669:                }
                   1670:                else if (k < 0)
                   1671:                {
                   1672:                        if (k < -4096)
                   1673:                        {
                   1674:                                if (subwayvel[i] > -256) subwayvel[i]--;
                   1675:                        }
                   1676:                        else
                   1677:                                subwayvel[i] = (k>>4)-1;
                   1678:                }
                   1679:                if ((j < 0) && (subwayvel[i] >= 0)) subwayvel[i] = -1;
                   1680:                if ((j > 0) && (subwayvel[i] <= 0)) subwayvel[i] = 1;
                   1681: 
                   1682:                if ((subwayvel[i] <= 2) && (subwayvel[i] >= -2) && (klabs(k) < 2048))
                   1683:                {
                   1684:                          //Open / close doors
                   1685:                        if ((subwaypausetime[i] == 720) || ((subwaypausetime[i] >= 120) && (subwaypausetime[i]-TICSPERFRAME < 120)))
                   1686:                                activatehitag(sector[subwaytracksector[i][0]].hitag);
                   1687: 
                   1688:                        subwaypausetime[i] -= TICSPERFRAME;
                   1689:                        if (subwaypausetime[i] < 0)
                   1690:                        {
                   1691:                                subwaypausetime[i] = 720;
                   1692:                                if (subwayvel[i] < 0)
                   1693:                                {
                   1694:                                        subwaygoalstop[i]--;
                   1695:                                        if (subwaygoalstop[i] < 0)
                   1696:                                        {
                   1697:                                                subwaygoalstop[i] = 1;
                   1698:                                                subwayvel[i] = 1;
                   1699:                                        }
                   1700:                                }
                   1701:                                else if (subwayvel[i] > 0)
                   1702:                                {
                   1703:                                        subwaygoalstop[i]++;
                   1704:                                        if (subwaygoalstop[i] >= subwaystopcnt[i])
                   1705:                                        {
                   1706:                                                subwaygoalstop[i] = subwaystopcnt[i]-2;
                   1707:                                                subwayvel[i] = -1;
                   1708:                                        }
                   1709:                                }
                   1710:                        }
                   1711:                }
                   1712:        }
                   1713: }
                   1714: 
                   1715: statuslistcode()
                   1716: {
                   1717:        short p, target, hitobject, daang, osectnum, movestat;
                   1718:        long i, nexti, j, nextj, k, l, dax, day, daz, dist, ox, oy, mindist;
                   1719:        long doubvel, xvect, yvect;
                   1720: 
                   1721:                //Go through active BROWNMONSTER list
                   1722:        for(i=headspritestat[1];i>=0;i=nexti)
                   1723:        {
                   1724:                nexti = nextspritestat[i];
                   1725: 
                   1726:                k = (krand()&63);
                   1727: 
                   1728:                        //Choose a target player
                   1729:                mindist = 0x7fffffff; target = connecthead;
                   1730:                for(p=connecthead;p>=0;p=connectpoint2[p])
                   1731:                {
                   1732:                        dist = klabs(sprite[i].x-posx[p])+klabs(sprite[i].y-posy[p]);
                   1733:                        if (dist < mindist) mindist = dist, target = p;
                   1734:                }
                   1735: 
                   1736:                        //brown monster decides to shoot bullet
                   1737:                if ((sprite[i].lotag > 25) && (k == 23))
                   1738:                {
                   1739:                        if (cansee(sprite[i].x,sprite[i].y,sprite[i].z-(tilesizy[sprite[i].picnum]<<7),sprite[i].sectnum,posx[target],posy[target],posz[target],cursectnum[target]) == 0)
                   1740:                        {
                   1741:                                changespritestat(i,2);
                   1742:                        }
                   1743:                        else
                   1744:                        {
                   1745:                                wsayfollow("zipguns.wav",5144L+(krand()&127)-64,256L,&sprite[i].x,&sprite[i].y,1);
                   1746: 
                   1747:                                doubvel = (TICSPERFRAME<<((sync[target].bits&256)>0));
                   1748:                                xvect = 0, yvect = 0;
                   1749:                                if (sync[target].fvel != 0)
                   1750:                                {
                   1751:                                        xvect += ((((long)sync[target].fvel)*doubvel*(long)sintable[(ang[target]+512)&2047])>>3);
                   1752:                                        yvect += ((((long)sync[target].fvel)*doubvel*(long)sintable[ang[target]&2047])>>3);
                   1753:                                }
                   1754:                                if (sync[target].svel != 0)
                   1755:                                {
                   1756:                                        xvect += ((((long)sync[target].svel)*doubvel*(long)sintable[ang[target]&2047])>>3);
                   1757:                                        yvect += ((((long)sync[target].svel)*doubvel*(long)sintable[(ang[target]+1536)&2047])>>3);
                   1758:                                }
                   1759: 
                   1760:                                ox = posx[target]; oy = posy[target];
                   1761: 
                   1762:                                        //distance is k
                   1763:                                k = ksqrt((ox-sprite[i].x)*(ox-sprite[i].x)+(oy-sprite[i].y)*(oy-sprite[i].y));
                   1764: 
                   1765:                                switch(sprite[i].extra&3)
                   1766:                                {
                   1767:                                        case 1: k = -(k>>1); break;
                   1768:                                        case 3: k = 0; break;
                   1769:                                        case 0: case 2: break;
                   1770:                                }
                   1771:                                sprite[i].extra++;
                   1772: 
                   1773:                                        //rate is (TICSPERFRAME<<19)
                   1774:                                xvect = scale(xvect,k,TICSPERFRAME<<19);
                   1775:                                yvect = scale(yvect,k,TICSPERFRAME<<19);
                   1776:                                clipmove(&ox,&oy,&posz[target],&cursectnum[target],xvect<<14,yvect<<14,128L,4<<8,4<<8,0);
                   1777:                                ox -= sprite[i].x;
                   1778:                                oy -= sprite[i].y;
                   1779: 
                   1780:                                daang = ((getangle(ox,oy)+(krand()&7)-4)&2047);
                   1781: 
                   1782:                                dax = (sintable[(daang+512)&2047]>>6);
                   1783:                                day = (sintable[daang&2047]>>6);
                   1784:                                daz = 0;
                   1785:                                if (ox != 0)
                   1786:                                        daz = scale(dax,posz[target]+(8<<8)-sprite[i].z,ox);
                   1787:                                else if (oy != 0)
                   1788:                                        daz = scale(day,posz[target]+(8<<8)-sprite[i].z,oy);
                   1789: 
                   1790:                                spawnsprite(j,sprite[i].x,sprite[i].y,sprite[i].z,128,0,0,
                   1791:                                        16,sprite[i].xrepeat,sprite[i].yrepeat,0,0,BULLET,daang,dax,day,daz,i,sprite[i].sectnum,6,0,0,0);
                   1792: 
                   1793:                                sprite[i].extra = 0;
                   1794:                        }
                   1795:                }
                   1796: 
                   1797:                        //Move brown monster
                   1798:                dax = sprite[i].x;   //Back up old x&y if stepping off cliff
                   1799:                day = sprite[i].y;
                   1800: 
                   1801:                doubvel = max(mulscale7(sprite[i].xrepeat,sprite[i].yrepeat),4);
                   1802: 
                   1803:                osectnum = sprite[i].sectnum;
                   1804:                movestat = movesprite((short)i,(long)sintable[(sprite[i].ang+512)&2047]*doubvel,(long)sintable[sprite[i].ang]*doubvel,0L,4L<<8,4L<<8,0);
                   1805:                if (globloz > sprite[i].z+(48<<8))
                   1806:                        { sprite[i].x = dax; sprite[i].y = day; movestat = 1; }
                   1807:                else
                   1808:                        sprite[i].z = globloz-((tilesizy[sprite[i].picnum]*sprite[i].yrepeat)<<1);
                   1809: 
                   1810:                if ((sprite[i].sectnum != osectnum) && (sector[sprite[i].sectnum].lotag == 10))
                   1811:                        { warpsprite((short)i); movestat = 0; }
                   1812: 
                   1813:                if ((movestat != 0) || (k == 1))
                   1814:                {
                   1815:                        daang = (getangle(posx[target]-sprite[i].x,posy[target]-sprite[i].y)&2047);
                   1816:                        sprite[i].ang = ((daang+(krand()&1023)-512)&2047);
                   1817:                }
                   1818:        }
                   1819: 
                   1820:        for(i=headspritestat[10];i>=0;i=nexti)  //EVILAL list
                   1821:        {
                   1822:                nexti = nextspritestat[i];
                   1823: 
                   1824:                if (sprite[i].yrepeat < 38) continue;
                   1825:                if (sprite[i].yrepeat < 64)
                   1826:                {
                   1827:                        sprite[i].xrepeat++;
                   1828:                        sprite[i].yrepeat++;
                   1829:                        continue;
                   1830:                }
                   1831: 
                   1832:                if ((nummoves-i)&statrate[10]) continue;
                   1833: 
                   1834:                        //Choose a target player
                   1835:                mindist = 0x7fffffff; target = connecthead;
                   1836:                for(p=connecthead;p>=0;p=connectpoint2[p])
                   1837:                {
                   1838:                        dist = klabs(sprite[i].x-posx[p])+klabs(sprite[i].y-posy[p]);
                   1839:                        if (dist < mindist) mindist = dist, target = p;
                   1840:                }
                   1841: 
                   1842:                k = (krand()&255);
                   1843: 
                   1844:                if (k < 48)  //Al decides to reproduce
                   1845:                {
                   1846:                        if (k < 2)  //Give him a chance to reproduce without seeing you
                   1847:                        {
                   1848:                                spawnsprite(j,sprite[i].x,sprite[i].y,sprite[i].z,1+2+256,0,0,
                   1849:                                        32,38,38,0,0,EVILAL,krand()&2047,0,0,0,i,
                   1850:                                        sprite[i].sectnum,10,0,0,0);
                   1851:                        }
                   1852:                        else if (cansee(sprite[i].x,sprite[i].y,sprite[i].z-(tilesizy[sprite[i].picnum]<<7),sprite[i].sectnum,posx[target],posy[target],posz[target],cursectnum[target]) == 1)
                   1853:                        {
                   1854:                                spawnsprite(j,sprite[i].x,sprite[i].y,sprite[i].z,1+2+256,0,0,
                   1855:                                        32,38,38,0,0,EVILAL,krand()&2047,0,0,0,i,
                   1856:                                        sprite[i].sectnum,10,0,0,0);
                   1857:                        }
                   1858:                }
                   1859:                if (k >= 208)     //Al decides to shoot bullet
                   1860:                {
                   1861:                        if (cansee(sprite[i].x,sprite[i].y,sprite[i].z-(tilesizy[sprite[i].picnum]<<7),sprite[i].sectnum,posx[target],posy[target],posz[target],cursectnum[target]) == 1)
                   1862:                        {
                   1863:                                wsayfollow("zipguns.wav",5144L+(krand()&127)-64,256L,&sprite[i].x,&sprite[i].y,1);
                   1864: 
                   1865:                                spawnsprite(j,sprite[i].x,sprite[i].y,
                   1866:                                        sector[sprite[i].sectnum].floorz-(24<<8),
                   1867:                                        0,0,0,16,32,32,0,0,BULLET,
                   1868:                                        (getangle(posx[target]-sprite[j].x,
                   1869:                                                posy[target]-sprite[j].y)+(krand()&15)-8)&2047,
                   1870:                                        sintable[(sprite[j].ang+512)&2047]>>6,
                   1871:                                        sintable[sprite[j].ang&2047]>>6,
                   1872:                                        ((posz[target]+(8<<8)-sprite[j].z)<<8) /
                   1873:                                          (ksqrt((posx[target]-sprite[j].x) *
                   1874:                                                                (posx[target]-sprite[j].x) +
                   1875:                                                                (posy[target]-sprite[j].y) *
                   1876:                                                                (posy[target]-sprite[j].y))+1),
                   1877:                                                                i,sprite[i].sectnum,6,0,0,0);
                   1878:                        }
                   1879:                }
                   1880: 
                   1881:                        //Move Al
                   1882:                dax = ((sintable[(sprite[i].ang+512)&2047]*TICSPERFRAME)<<8);
                   1883:                day = ((sintable[sprite[i].ang]*TICSPERFRAME)<<8);
                   1884: 
                   1885:                osectnum = sprite[i].sectnum;
                   1886:                movestat = movesprite((short)i,dax,day,0L,-8L<<8,-8L<<8,0);
                   1887:                sprite[i].z = globloz;
                   1888:                if ((sprite[i].sectnum != osectnum) && (sector[sprite[i].sectnum].lotag == 10))
                   1889:                {
                   1890:                        warpsprite((short)i);
                   1891:                        movestat = 0;
                   1892:                }
                   1893: 
                   1894:                if (movestat != 0)
                   1895:                {
                   1896:                        if ((k&2) && (cansee(sprite[i].x,sprite[i].y,sprite[i].z-(tilesizy[sprite[i].picnum]<<7),sprite[i].sectnum,posx[target],posy[target],posz[target],cursectnum[target]) == 1))
                   1897:                                sprite[i].ang = getangle(posx[target]-sprite[i].x,posy[target]-sprite[i].y);
                   1898:                        else
                   1899:                                sprite[i].ang = (krand()&2047);
                   1900: 
                   1901:                        if ((movestat&49152) == 49152)
                   1902:                                if (sprite[movestat&16383].picnum == EVILAL)
                   1903:                                        if ((k&31) >= 30)
                   1904:                                        {
                   1905:                                                wsayfollow("blowup.wav",5144L+(krand()&127)-64,256L,&sprite[i].x,&sprite[i].y,0);
                   1906:                                                sprite[i].picnum = EVILALGRAVE;
                   1907:                                                sprite[i].cstat = 0;
                   1908:                                                sprite[i].lotag = 255;
                   1909:                                                sprite[i].xvel = (krand()&255)-128;
                   1910:                                                sprite[i].yvel = (krand()&255)-128;
                   1911:                                                sprite[i].zvel = (krand()&4095)-3072;
                   1912:                                                changespritestat(i,9);
                   1913:                                        }
                   1914:                        if (movestat == -1)
                   1915:                        {
                   1916:                                wsayfollow("blowup.wav",5144L+(krand()&127)-64,256L,&sprite[i].x,&sprite[i].y,0);
                   1917:                                sprite[i].picnum = EVILALGRAVE;
                   1918:                                sprite[i].cstat = 0;
                   1919:                                sprite[i].lotag = 255;
                   1920:                                sprite[i].xvel = (krand()&255)-128;
                   1921:                                sprite[i].yvel = (krand()&255)-128;
                   1922:                                sprite[i].zvel = (krand()&4095)-3072;
                   1923:                                changespritestat(i,9);
                   1924:                        }
                   1925:                }
                   1926:        }
                   1927: 
                   1928:                //Go through travelling bullet sprites
                   1929:        for(i=headspritestat[6];i>=0;i=nexti)
                   1930:        {
                   1931:                nexti = nextspritestat[i];
                   1932: 
                   1933:                if ((nummoves-i)&statrate[6]) continue;
                   1934: 
                   1935:                         //If the sprite is a bullet then...
                   1936:                if ((sprite[i].picnum == BULLET) || (sprite[i].picnum == BOMB))
                   1937:                {
                   1938:                        dax = ((((long)sprite[i].xvel)*TICSPERFRAME)<<12);
                   1939:                        day = ((((long)sprite[i].yvel)*TICSPERFRAME)<<12);
                   1940:                        daz = ((((long)sprite[i].zvel)*TICSPERFRAME)>>2);
                   1941:                        if (sprite[i].picnum == BOMB) daz = 0;
                   1942: 
                   1943:                        osectnum = sprite[i].sectnum;
                   1944:                        hitobject = movesprite((short)i,dax,day,daz,4L<<8,4L<<8,1);
                   1945:                        if ((sprite[i].sectnum != osectnum) && (sector[sprite[i].sectnum].lotag == 10))
                   1946:                        {
                   1947:                                warpsprite((short)i);
                   1948:                                hitobject = 0;
                   1949:                        }
                   1950: 
                   1951:                        if (sprite[i].picnum == BOMB)
                   1952:                        {
                   1953:                                j = sprite[i].sectnum;
                   1954:                                if ((sector[j].floorstat&2) && (sprite[i].z > globloz-(8<<8)))
                   1955:                                {
                   1956:                                        k = sector[j].wallptr;
                   1957:                                        daang = getangle(wall[wall[k].point2].x-wall[k].x,wall[wall[k].point2].y-wall[k].y);
                   1958:                                        sprite[i].xvel += mulscale22(sintable[(daang+1024)&2047],sector[j].floorheinum);
                   1959:                                        sprite[i].yvel += mulscale22(sintable[(daang+512)&2047],sector[j].floorheinum);
                   1960:                                }
                   1961:                        }
                   1962: 
                   1963:                        if (sprite[i].picnum == BOMB)
                   1964:                        {
                   1965:                                sprite[i].z += sprite[i].zvel;
                   1966:                                sprite[i].zvel += (TICSPERFRAME<<7);
                   1967:                                if (sprite[i].z < globhiz+(tilesizy[BOMB]<<6))
                   1968:                                {
                   1969:                                        sprite[i].z = globhiz+(tilesizy[BOMB]<<6);
                   1970:                                        sprite[i].zvel = -(sprite[i].zvel>>1);
                   1971:                                }
                   1972:                                if (sprite[i].z > globloz-(tilesizy[BOMB]<<6))
                   1973:                                {
                   1974:                                        sprite[i].z = globloz-(tilesizy[BOMB]<<6);
                   1975:                                        sprite[i].zvel = -(sprite[i].zvel>>1);
                   1976:                                }
                   1977:                                dax = sprite[i].xvel; day = sprite[i].yvel;
                   1978:                                dist = dax*dax+day*day;
                   1979:                                if (dist < 512)
                   1980:                                {
                   1981:                                        bombexplode(i);
                   1982:                                        goto bulletisdeletedskip;
                   1983:                                }
                   1984:                                if (dist < 4096)
                   1985:                                {
                   1986:                                        sprite[i].xrepeat = ((4096+2048)*16) / (dist+2048);
                   1987:                                        sprite[i].yrepeat = sprite[i].xrepeat;
                   1988:                                        sprite[i].xoffset = (krand()&15)-8;
                   1989:                                        sprite[i].yoffset = (krand()&15)-8;
                   1990:                                }
                   1991:                                if (mulscale30(krand(),dist) == 0)
                   1992:                                {
                   1993:                                        sprite[i].xvel -= ksgn(sprite[i].xvel);
                   1994:                                        sprite[i].yvel -= ksgn(sprite[i].yvel);
                   1995:                                        sprite[i].zvel -= ksgn(sprite[i].zvel);
                   1996:                                }
                   1997:                        }
                   1998: 
                   1999:                                //Check for bouncy objects before killing bullet
                   2000:                        if ((hitobject&0xc000) == 32768)  //Bullet hit a wall
                   2001:                        {
                   2002:                                if (wall[hitobject&4095].lotag == 8)
                   2003:                                {
                   2004:                                        dax = sprite[i].xvel; day = sprite[i].yvel;
                   2005:                                        if ((sprite[i].picnum != BOMB) || (dax*dax+day*day >= 512))
                   2006:                                        {
                   2007:                                                k = (hitobject&4095); l = wall[k].point2;
                   2008:                                                j = getangle(wall[l].x-wall[k].x,wall[l].y-wall[k].y)+512;
                   2009: 
                   2010:                                                        //k = cos(ang) * sin(ang) * 2
                   2011:                                                k = mulscale13(sintable[(j+512)&2047],sintable[j&2047]);
                   2012:                                                        //l = cos(ang * 2)
                   2013:                                                l = sintable[((j<<1)+512)&2047];
                   2014: 
                   2015:                                                ox = sprite[i].xvel; oy = sprite[i].yvel;
                   2016:                                                dax = -ox; day = -oy;
                   2017:                                                sprite[i].xvel = dmulscale14(day,k,dax,l);
                   2018:                                                sprite[i].yvel = dmulscale14(dax,k,-day,l);
                   2019: 
                   2020:                                                if (sprite[i].picnum == BOMB)
                   2021:                                                {
                   2022:                                                        sprite[i].xvel -= (sprite[i].xvel>>3);
                   2023:                                                        sprite[i].yvel -= (sprite[i].yvel>>3);
                   2024:                                                        sprite[i].zvel -= (sprite[i].zvel>>3);
                   2025:                                                }
                   2026:                                                ox -= sprite[i].xvel; oy -= sprite[i].yvel;
                   2027:                                                dist = ((ox*ox+oy*oy)>>8);
                   2028:                                                wsayfollow("bouncy.wav",4096L+(krand()&127)-64,min(dist,256),&sprite[i].x,&sprite[i].y,1);
                   2029:                                                hitobject = 0;
                   2030:                                                sprite[i].owner = -1;   //Bullet turns evil!
                   2031:                                        }
                   2032:                                }
                   2033:                        }
                   2034:                        else if ((hitobject&0xc000) == 49152)  //Bullet hit a sprite
                   2035:                        {
                   2036:                                if (sprite[hitobject&4095].picnum == BOUNCYMAT)
                   2037:                                {
                   2038:                                        if ((sprite[hitobject&4095].cstat&48) == 0)
                   2039:                                        {
                   2040:                                                sprite[i].xvel = -sprite[i].xvel;
                   2041:                                                sprite[i].yvel = -sprite[i].yvel;
                   2042:                                                sprite[i].zvel = -sprite[i].zvel;
                   2043:                                                dist = 255;
                   2044:                                        }
                   2045:                                        else if ((sprite[hitobject&4095].cstat&48) == 16)
                   2046:                                        {
                   2047:                                                j = sprite[hitobject&4095].ang;
                   2048: 
                   2049:                                                        //k = cos(ang) * sin(ang) * 2
                   2050:                                                k = mulscale13(sintable[(j+512)&2047],sintable[j&2047]);
                   2051:                                                        //l = cos(ang * 2)
                   2052:                                                l = sintable[((j<<1)+512)&2047];
                   2053: 
                   2054:                                                ox = sprite[i].xvel; oy = sprite[i].yvel;
                   2055:                                                dax = -ox; day = -oy;
                   2056:                                                sprite[i].xvel = dmulscale14(day,k,dax,l);
                   2057:                                                sprite[i].yvel = dmulscale14(dax,k,-day,l);
                   2058: 
                   2059:                                                ox -= sprite[i].xvel; oy -= sprite[i].yvel;
                   2060:                                                dist = ((ox*ox+oy*oy)>>8);
                   2061:                                        }
                   2062:                                        sprite[i].owner = -1;   //Bullet turns evil!
                   2063:                                        wsayfollow("bouncy.wav",4096L+(krand()&127)-64,min(dist,256),&sprite[i].x,&sprite[i].y,1);
                   2064:                                        hitobject = 0;
                   2065:                                }
                   2066:                        }
                   2067: 
                   2068:                        if (hitobject != 0)
                   2069:                        {
                   2070:                                if (sprite[i].picnum == BOMB)
                   2071:                                {
                   2072:                                        if ((hitobject&0xc000) == 49152)
                   2073:                                                if (sprite[hitobject&4095].lotag == 5)  //Basketball hoop
                   2074:                                                {
                   2075:                                                        wsayfollow("niceshot.wav",3840L+(krand()&127)-64,256L,&sprite[i].x,&sprite[i].y,0);
                   2076:                                                        deletesprite((short)i);
                   2077:                                                        goto bulletisdeletedskip;
                   2078:                                                }
                   2079: 
                   2080:                                        bombexplode(i);
                   2081:                                        goto bulletisdeletedskip;
                   2082:                                }
                   2083: 
                   2084:                                if ((hitobject&0xc000) == 16384)  //Hits a ceiling / floor
                   2085:                                {
                   2086:                                        wsayfollow("bullseye.wav",4096L+(krand()&127)-64,256L,&sprite[i].x,&sprite[i].y,0);
                   2087:                                        deletesprite((short)i);
                   2088:                                        goto bulletisdeletedskip;
                   2089:                                }
                   2090:                                else if ((hitobject&0xc000) == 32768)  //Bullet hit a wall
                   2091:                                {
                   2092:                                        if (wall[hitobject&4095].picnum == KENPICTURE)
                   2093:                                        {
                   2094:                                                if (waloff[4095] != 0)
                   2095:                                                        wall[hitobject&4095].picnum = 4095;
                   2096:                                                wsayfollow("hello.wav",4096L+(krand()&127)-64,256L,&sprite[i].x,&sprite[i].y,0);   //Ken says, "Hello... how are you today!"
                   2097:                                        }
                   2098:                                        else
                   2099:                                                wsayfollow("bullseye.wav",4096L+(krand()&127)-64,256L,&sprite[i].x,&sprite[i].y,0);
                   2100: 
                   2101:                                        deletesprite((short)i);
                   2102:                                        goto bulletisdeletedskip;
                   2103:                                }
                   2104:                                else if ((hitobject&0xc000) == 49152)  //Bullet hit a sprite
                   2105:                                {
                   2106:                                                //Check if bullet hit a player & find which player it was...
                   2107:                                        if (sprite[hitobject&4095].picnum == DOOMGUY)
                   2108:                                                for(j=connecthead;j>=0;j=connectpoint2[j])
                   2109:                                                        if (sprite[i].owner != j+4096)
                   2110:                                                                if (playersprite[j] == (hitobject&4095))
                   2111:                                                                {
                   2112:                                                                        wsayfollow("ouch.wav",4096L+(krand()&127)-64,256L,&sprite[i].x,&sprite[i].y,0);
                   2113:                                                                        changehealth(j,-mulscale8(sprite[i].xrepeat,sprite[i].yrepeat));
                   2114:                                                                        deletesprite((short)i);
                   2115:                                                                        goto bulletisdeletedskip;
                   2116:                                                                }
                   2117: 
                   2118:                                                //Check if bullet hit any monsters...
                   2119:                                        j = (hitobject&4095);     //j is the spritenum that the bullet (spritenum i) hit
                   2120:                                        if (sprite[i].owner != j)
                   2121:                                        {
                   2122:                                                switch(sprite[j].picnum)
                   2123:                                                {
                   2124:                                                        case BROWNMONSTER:
                   2125:                                                                if (sprite[j].lotag > 0) sprite[j].lotag -= mulscale8(sprite[i].xrepeat,sprite[i].yrepeat);
                   2126:                                                                if (sprite[j].lotag > 0)
                   2127:                                                                {
                   2128:                                                                        if (sprite[j].lotag <= 25) sprite[j].cstat |= 2;
                   2129:                                                                        wsayfollow("hurt.wav",4096L+(krand()&511)-256,256L,&sprite[i].x,&sprite[i].y,1);
                   2130:                                                                }
                   2131:                                                                else
                   2132:                                                                {
                   2133:                                                                        wsayfollow("blowup.wav",4096L+(krand()&127)-64,256L,&sprite[i].x,&sprite[i].y,0);
                   2134:                                                                        sprite[j].z += ((tilesizy[sprite[j].picnum]*sprite[j].yrepeat)<<1);
                   2135:                                                                        sprite[j].picnum = GIFTBOX;
                   2136:                                                                        sprite[j].cstat &= ~0x83;    //Should not clip, foot-z
                   2137: 
                   2138:                                                                        spawnsprite(k,sprite[j].x,sprite[j].y,sprite[j].z,
                   2139:                                                                                0,-4,0,32,64,64,0,0,EXPLOSION,sprite[j].ang,
                   2140:                                                                                0,0,0,j,sprite[j].sectnum,5,31,0,0);
                   2141:                                                                                        //31=Time left for explosion to stay
                   2142: 
                   2143:                                                                        changespritestat(j,0);
                   2144:                                                                }
                   2145:                                                                deletesprite((short)i);
                   2146:                                                                goto bulletisdeletedskip;
                   2147:                                                        case EVILAL:
                   2148:                                                                wsayfollow("blowup.wav",5144L+(krand()&127)-64,256L,&sprite[i].x,&sprite[i].y,0);
                   2149:                                                                sprite[j].picnum = EVILALGRAVE;
                   2150:                                                                sprite[j].cstat = 0;
                   2151:                                                                sprite[j].lotag = 255;
                   2152:                                                                sprite[j].xvel = (krand()&255)-128;
                   2153:                                                                sprite[j].yvel = (krand()&255)-128;
                   2154:                                                                sprite[j].zvel = (krand()&4095)-3072;
                   2155:                                                                changespritestat(j,9);
                   2156: 
                   2157:                                                                deletesprite((short)i);
                   2158:                                                                goto bulletisdeletedskip;
                   2159:                                                        case AL:
                   2160:                                                                wsayfollow("blowup.wav",5144L+(krand()&127)-64,256L,&sprite[i].x,&sprite[i].y,0);
                   2161:                                                                sprite[j].xrepeat += 2;
                   2162:                                                                sprite[j].yrepeat += 2;
                   2163:                                                                if (sprite[j].yrepeat >= 38)
                   2164:                                                                {
                   2165:                                                                        sprite[j].picnum = EVILAL;
                   2166:                                                                        sprite[j].cstat |= 2;      //Make him transluscent
                   2167:                                                                        changespritestat(j,10);
                   2168:                                                                }
                   2169:                                                                deletesprite((short)i);
                   2170:                                                                goto bulletisdeletedskip;
                   2171:                                                        default:
                   2172:                                                                wsayfollow("bullseye.wav",4096L+(krand()&127)-64,256L,&sprite[i].x,&sprite[i].y,0);
                   2173:                                                                deletesprite((short)i);
                   2174:                                                                goto bulletisdeletedskip;
                   2175:                                                }
                   2176:                                        }
                   2177:                                }
                   2178:                        }
                   2179:                }
                   2180: bulletisdeletedskip: continue;
                   2181:        }
                   2182: 
                   2183:                //Go through monster waiting for you list
                   2184:        for(i=headspritestat[2];i>=0;i=nexti)
                   2185:        {
                   2186:                nexti = nextspritestat[i];
                   2187: 
                   2188:                if ((nummoves-i)&15) continue;
                   2189: 
                   2190:                        //Use dot product to see if monster's angle is towards a player
                   2191:                for(p=connecthead;p>=0;p=connectpoint2[p])
                   2192:                        if (sintable[(sprite[i].ang+512)&2047]*(posx[p]-sprite[i].x) + sintable[sprite[i].ang&2047]*(posy[p]-sprite[i].y) >= 0)
                   2193:                                if (cansee(sprite[i].x,sprite[i].y,sprite[i].z-(tilesizy[sprite[i].picnum]<<7),sprite[i].sectnum,posx[p],posy[p],posz[p],cursectnum[p]) == 1)
                   2194:                                {
                   2195:                                        changespritestat(i,1);
                   2196:                                        if (sprite[i].lotag == 100)
                   2197:                                        {
                   2198:                                                wsayfollow("iseeyou.wav",4096L+(krand()&127)-64,256L,&sprite[i].x,&sprite[i].y,1);
                   2199:                                                sprite[i].lotag = 99;
                   2200:                                        }
                   2201:                                }
                   2202:        }
                   2203: 
                   2204:                //Go through smoke sprites
                   2205:        for(i=headspritestat[3];i>=0;i=nexti)
                   2206:        {
                   2207:                nexti = nextspritestat[i];
                   2208: 
                   2209:                sprite[i].z -= (TICSPERFRAME<<6);
                   2210:                sprite[i].lotag -= TICSPERFRAME;
                   2211:                if (sprite[i].lotag < 0) deletesprite(i);
                   2212:        }
                   2213: 
                   2214:                //Go through splash sprites
                   2215:        for(i=headspritestat[4];i>=0;i=nexti)
                   2216:        {
                   2217:                nexti = nextspritestat[i];
                   2218: 
                   2219:                sprite[i].lotag -= TICSPERFRAME;
                   2220:                sprite[i].picnum = SPLASH + ((63-sprite[i].lotag)>>4);
                   2221:                if (sprite[i].lotag < 0) deletesprite(i);
                   2222:        }
                   2223: 
                   2224:                //Go through explosion sprites
                   2225:        for(i=headspritestat[5];i>=0;i=nexti)
                   2226:        {
                   2227:                nexti = nextspritestat[i];
                   2228: 
                   2229:                sprite[i].lotag -= TICSPERFRAME;
                   2230:                if (sprite[i].lotag < 0) deletesprite(i);
                   2231:        }
                   2232: 
                   2233:                //Go through bomb spriral-explosion sprites
                   2234:        for(i=headspritestat[7];i>=0;i=nexti)
                   2235:        {
                   2236:                nexti = nextspritestat[i];
                   2237: 
                   2238:                sprite[i].xrepeat = (sprite[i].lotag>>2);
                   2239:                sprite[i].yrepeat = (sprite[i].lotag>>2);
                   2240:                sprite[i].lotag -= (TICSPERFRAME<<2);
                   2241:                if (sprite[i].lotag < 0) { deletesprite(i); continue; }
                   2242: 
                   2243:                if ((nummoves-i)&statrate[7]) continue;
                   2244: 
                   2245:                sprite[i].x += ((sprite[i].xvel*TICSPERFRAME)>>2);
                   2246:                sprite[i].y += ((sprite[i].yvel*TICSPERFRAME)>>2);
                   2247:                sprite[i].z += ((sprite[i].zvel*TICSPERFRAME)>>2);
                   2248: 
                   2249:                sprite[i].zvel += (TICSPERFRAME<<9);
                   2250:                if (sprite[i].z < sector[sprite[i].sectnum].ceilingz+(4<<8))
                   2251:                {
                   2252:                        sprite[i].z = sector[sprite[i].sectnum].ceilingz+(4<<8);
                   2253:                        sprite[i].zvel = -(sprite[i].zvel>>1);
                   2254:                }
                   2255:                if (sprite[i].z > sector[sprite[i].sectnum].floorz-(4<<8))
                   2256:                {
                   2257:                        sprite[i].z = sector[sprite[i].sectnum].floorz-(4<<8);
                   2258:                        sprite[i].zvel = -(sprite[i].zvel>>1);
                   2259:                }
                   2260:        }
                   2261: 
                   2262:                //EVILALGRAVE shrinking list
                   2263:        for(i=headspritestat[9];i>=0;i=nexti)
                   2264:        {
                   2265:                nexti = nextspritestat[i];
                   2266: 
                   2267:                sprite[i].xrepeat = (sprite[i].lotag>>2);
                   2268:                sprite[i].yrepeat = (sprite[i].lotag>>2);
                   2269:                sprite[i].lotag -= TICSPERFRAME;
                   2270:                if (sprite[i].lotag < 0) { deletesprite(i); continue; }
                   2271: 
                   2272:                if ((nummoves-i)&statrate[9]) continue;
                   2273: 
                   2274:                sprite[i].x += (sprite[i].xvel*TICSPERFRAME);
                   2275:                sprite[i].y += (sprite[i].yvel*TICSPERFRAME);
                   2276:                sprite[i].z += (sprite[i].zvel*TICSPERFRAME);
                   2277: 
                   2278:                sprite[i].zvel += (TICSPERFRAME<<8);
                   2279:                if (sprite[i].z < sector[sprite[i].sectnum].ceilingz)
                   2280:                {
                   2281:                        sprite[i].z = sector[sprite[i].sectnum].ceilingz;
                   2282:                        sprite[i].xvel -= (sprite[i].xvel>>2);
                   2283:                        sprite[i].yvel -= (sprite[i].yvel>>2);
                   2284:                        sprite[i].zvel = -(sprite[i].zvel>>1);
                   2285:                }
                   2286:                if (sprite[i].z > sector[sprite[i].sectnum].floorz)
                   2287:                {
                   2288:                        sprite[i].z = sector[sprite[i].sectnum].floorz;
                   2289:                        sprite[i].xvel -= (sprite[i].xvel>>2);
                   2290:                        sprite[i].yvel -= (sprite[i].yvel>>2);
                   2291:                        sprite[i].zvel = -(sprite[i].zvel>>1);
                   2292:                }
                   2293:        }
                   2294: 
                   2295:                //Re-spawning sprite list
                   2296:        for(i=headspritestat[11];i>=0;i=nexti)
                   2297:        {
                   2298:                nexti = nextspritestat[i];
                   2299: 
                   2300:                sprite[i].extra -= TICSPERFRAME;
                   2301:                if (sprite[i].extra < 0)
                   2302:                {
                   2303:                        wsayfollow("warp.wav",6144L+(krand()&127)-64,128L,&sprite[i].x,&sprite[i].y,0);
                   2304:                        sprite[i].cstat &= ~0x8000;
                   2305:                        sprite[i].extra = -1;
                   2306:                        changespritestat((short)i,0);
                   2307:                }
                   2308:        }
                   2309: }
                   2310: 
                   2311: activatehitag(short dahitag)
                   2312: {
                   2313:        long i, nexti;
                   2314: 
                   2315:        for(i=0;i<numsectors;i++)
                   2316:                if (sector[i].hitag == dahitag) operatesector(i);
                   2317: 
                   2318:        for(i=headspritestat[0];i>=0;i=nexti)
                   2319:        {
                   2320:                nexti = nextspritestat[i];
                   2321:                if (sprite[i].hitag == dahitag) operatesprite(i);
                   2322:        }
                   2323: }
                   2324: 
                   2325: bombexplode(long i)
                   2326: {
                   2327:        long j, nextj, k, daang, dax, day, dist;
                   2328: 
                   2329:        spawnsprite(j,sprite[i].x,sprite[i].y,sprite[i].z,0,-4,0,
                   2330:                32,64,64,0,0,EXPLOSION,sprite[i].ang,
                   2331:                0,0,0,sprite[i].owner,sprite[i].sectnum,5,31,0,0);
                   2332:                  //31=Time left for explosion to stay
                   2333: 
                   2334:        for(k=0;k<12;k++)
                   2335:        {
                   2336:                spawnsprite(j,sprite[i].x,sprite[i].y,sprite[i].z+(8<<8),2,-4,0,
                   2337:                        32,24,24,0,0,EXPLOSION,sprite[i].ang,
                   2338:                        (krand()>>7)-256,(krand()>>7)-256,(krand()>>2)-8192,
                   2339:                        sprite[i].owner,sprite[i].sectnum,7,96,0,0);
                   2340:                                //96=Time left for smoke to be alive
                   2341:        }
                   2342: 
                   2343:        for(j=connecthead;j>=0;j=connectpoint2[j])
                   2344:        {
                   2345:                dist = (posx[j]-sprite[i].x)*(posx[j]-sprite[i].x);
                   2346:                dist += (posy[j]-sprite[i].y)*(posy[j]-sprite[i].y);
                   2347:                dist += ((posz[j]-sprite[i].z)>>4)*((posz[j]-sprite[i].z)>>4);
                   2348:                if (dist < 4194304)
                   2349:                        if (cansee(sprite[i].x,sprite[i].y,sprite[i].z-(tilesizy[sprite[i].picnum]<<7),sprite[i].sectnum,posx[j],posy[j],posz[j],cursectnum[j]) == 1)
                   2350:                        {
                   2351:                                k = ((32768/((dist>>16)+4))>>5);
                   2352:                                if (j == myconnectindex)
                   2353:                                {
                   2354:                                        daang = getangle(posx[j]-sprite[i].x,posy[j]-sprite[i].y);
                   2355:                                        dax = ((k*sintable[(daang+512)&2047])>>14);
                   2356:                                        day = ((k*sintable[daang&2047])>>14);
                   2357:                                        fvel += ((dax*sintable[(ang[j]+512)&2047]+day*sintable[ang[j]&2047])>>14);
                   2358:                                        svel += ((day*sintable[(ang[j]+512)&2047]-dax*sintable[ang[j]&2047])>>14);
                   2359:                                }
                   2360:                                changehealth(j,-k);    //if changehealth returns 1, you're dead
                   2361:                        }
                   2362:        }
                   2363: 
                   2364:        for(k=1;k<=2;k++)         //Check for hurting monsters
                   2365:        {
                   2366:                for(j=headspritestat[k];j>=0;j=nextj)
                   2367:                {
                   2368:                        nextj = nextspritestat[j];
                   2369: 
                   2370:                        dist = (sprite[j].x-sprite[i].x)*(sprite[j].x-sprite[i].x);
                   2371:                        dist += (sprite[j].y-sprite[i].y)*(sprite[j].y-sprite[i].y);
                   2372:                        dist += ((sprite[j].z-sprite[i].z)>>4)*((sprite[j].z-sprite[i].z)>>4);
                   2373:                        if (dist >= 4194304) continue;
                   2374:                        if (cansee(sprite[i].x,sprite[i].y,sprite[i].z-(tilesizy[sprite[i].picnum]<<7),sprite[i].sectnum,sprite[j].x,sprite[j].y,sprite[j].z-(tilesizy[sprite[j].picnum]<<7),sprite[j].sectnum) == 0)
                   2375:                                continue;
                   2376:                        if (sprite[j].picnum == BROWNMONSTER)
                   2377:                        {
                   2378:                                sprite[j].z += ((tilesizy[sprite[j].picnum]*sprite[j].yrepeat)<<1);
                   2379:                                sprite[j].picnum = GIFTBOX;
                   2380:                                sprite[j].cstat &= ~0x83;    //Should not clip, foot-z
                   2381:                                changespritestat(j,0);
                   2382:                        }
                   2383:                }
                   2384:        }
                   2385: 
                   2386:        for(j=headspritestat[10];j>=0;j=nextj)   //Check for EVILAL's
                   2387:        {
                   2388:                nextj = nextspritestat[j];
                   2389: 
                   2390:                dist = (sprite[j].x-sprite[i].x)*(sprite[j].x-sprite[i].x);
                   2391:                dist += (sprite[j].y-sprite[i].y)*(sprite[j].y-sprite[i].y);
                   2392:                dist += ((sprite[j].z-sprite[i].z)>>4)*((sprite[j].z-sprite[i].z)>>4);
                   2393:                if (dist >= 4194304) continue;
                   2394:                if (cansee(sprite[i].x,sprite[i].y,sprite[i].z-(tilesizy[sprite[i].picnum]<<7),sprite[i].sectnum,sprite[j].x,sprite[j].y,sprite[j].z-(tilesizy[sprite[j].picnum]<<7),sprite[j].sectnum) == 0)
                   2395:                        continue;
                   2396: 
                   2397:                sprite[j].picnum = EVILALGRAVE;
                   2398:                sprite[j].cstat = 0;
                   2399:                sprite[j].lotag = 255;
                   2400:                sprite[j].xvel = (krand()&255)-128;
                   2401:                sprite[j].yvel = (krand()&255)-128;
                   2402:                sprite[j].zvel = (krand()&4095)-3072;
                   2403:                changespritestat(j,9);
                   2404:        }
                   2405: 
                   2406:        wsayfollow("blowup.wav",3840L+(krand()&127)-64,256L,&sprite[i].x,&sprite[i].y,0);
                   2407:        deletesprite((short)i);
                   2408: }
                   2409: 
                   2410: processinput(short snum)
                   2411: {
                   2412:        long oldposx, oldposy, nexti;
                   2413:        long i, j, k, doubvel, xvect, yvect, goalz;
                   2414:        long dax, day, dax2, day2, odax, oday, odax2, oday2;
                   2415:        short startwall, endwall;
                   2416:        char *ptr;
                   2417: 
                   2418:                //SHARED KEYS:
                   2419:                //Movement code
                   2420:        if ((sync[snum].fvel|sync[snum].svel) != 0)
                   2421:        {
                   2422:                doubvel = (TICSPERFRAME<<((sync[snum].bits&256)>0));
                   2423: 
                   2424:                xvect = 0, yvect = 0;
                   2425:                if (sync[snum].fvel != 0)
                   2426:                {
                   2427:                        xvect += ((((long)sync[snum].fvel)*doubvel*(long)sintable[(ang[snum]+512)&2047])>>3);
                   2428:                        yvect += ((((long)sync[snum].fvel)*doubvel*(long)sintable[ang[snum]&2047])>>3);
                   2429:                }
                   2430:                if (sync[snum].svel != 0)
                   2431:                {
                   2432:                        xvect += ((((long)sync[snum].svel)*doubvel*(long)sintable[ang[snum]&2047])>>3);
                   2433:                        yvect += ((((long)sync[snum].svel)*doubvel*(long)sintable[(ang[snum]+1536)&2047])>>3);
                   2434:                }
                   2435:                clipmove(&posx[snum],&posy[snum],&posz[snum],&cursectnum[snum],xvect,yvect,128L,4<<8,4<<8,0);
                   2436:                revolvedoorstat[snum] = 1;
                   2437:        }
                   2438:        else
                   2439:        {
                   2440:                revolvedoorstat[snum] = 0;
                   2441:        }
                   2442: 
                   2443:        sprite[playersprite[snum]].cstat &= ~1;
                   2444:                //Push player away from walls if clipmove doesn't work
                   2445:        if (pushmove(&posx[snum],&posy[snum],&posz[snum],&cursectnum[snum],128L,4<<8,4<<8,0) < 0)
                   2446:                changehealth(snum,-1000);  //If this screws up, then instant death!!!
                   2447: 
                   2448:                        // Getzrange returns the highest and lowest z's for an entire box,
                   2449:                        // NOT just a point.  This prevents you from falling off cliffs
                   2450:                        // when you step only slightly over the cliff.
                   2451:        getzrange(posx[snum],posy[snum],posz[snum],cursectnum[snum],&globhiz,&globhihit,&globloz,&globlohit,128L,0);
                   2452:        sprite[playersprite[snum]].cstat |= 1;
                   2453: 
                   2454:        if (sync[snum].avel != 0)          //ang += avel * constant
                   2455:        {                         //ENGINE calculates avel for you
                   2456:                doubvel = TICSPERFRAME;
                   2457:                if ((sync[snum].bits&256) > 0)  //Lt. shift makes turn velocity 50% faster
                   2458:                        doubvel += (TICSPERFRAME>>1);
                   2459:                ang[snum] += ((((long)sync[snum].avel)*doubvel)>>4);
                   2460:                ang[snum] &= 2047;
                   2461:        }
                   2462: 
                   2463:        if (health[snum] < 0)
                   2464:        {
                   2465:                health[snum] -= TICSPERFRAME;
                   2466:                if (health[snum] <= -160)
                   2467:                {
                   2468:                        hvel[snum] = 0;
                   2469:                        if (snum == myconnectindex)
                   2470:                                fvel = 0, svel = 0, avel = 0, keystatus[3] = 1;
                   2471: 
                   2472:                        deaths[snum]++;
                   2473:                        health[snum] = 100;
                   2474:                        numbombs[snum] = 0;
                   2475:                        flytime[snum] = 0;
                   2476: 
                   2477:                        findrandomspot(&posx[snum],&posy[snum],&cursectnum[snum]);
                   2478:                        posz[snum] = getflorzofslope(cursectnum[snum],posx[snum],posy[snum])-(1<<8);
                   2479:                        horiz[snum] = 100;
                   2480:                        ang[snum] = (krand()&2047);
                   2481: 
                   2482:                        setsprite(playersprite[snum],posx[snum],posy[snum],posz[snum]+(32<<8));
                   2483:                        sprite[playersprite[snum]].picnum = DOOMGUY;
                   2484:                        sprite[playersprite[snum]].ang = ang[snum];
                   2485:                        sprite[playersprite[snum]].xrepeat = 64;
                   2486:                        sprite[playersprite[snum]].yrepeat = 64;
                   2487: 
                   2488:                        if ((snum == screenpeek) && (screensize <= xdim))
                   2489:                        {
                   2490:                                sprintf(&tempbuf,"Deaths: %d",deaths[snum]);
                   2491:                                printext((xdim>>1)-(strlen(tempbuf)<<2),ydim-16,tempbuf,ALPHABET,80);
                   2492:                                sprintf(&tempbuf,"Health: %3d",health[snum]);
                   2493:                                printext((xdim>>1)-(strlen(tempbuf)<<2),ydim-24,tempbuf,ALPHABET,80);
                   2494:                        }
                   2495: 
                   2496:                        i = playersprite[snum];
                   2497:                        wsayfollow("zipguns.wav",4096L+(krand()&127)-64,256L,&sprite[i].x,&sprite[i].y,1);
                   2498:                        for(k=0;k<16;k++)
                   2499:                        {
                   2500:                                spawnsprite(j,sprite[i].x,sprite[i].y,sprite[i].z+(8<<8),2,-4,0,
                   2501:                                        32,24,24,0,0,EXPLOSION,sprite[i].ang,
                   2502:                                        (krand()&511)-256,(krand()&511)-256,(krand()&16384)-8192,
                   2503:                                        sprite[i].owner,sprite[i].sectnum,7,96,0,0);
                   2504:                                                //96=Time left for smoke to be alive
                   2505:                        }
                   2506:                }
                   2507:                else
                   2508:                {
                   2509:                        sprite[playersprite[snum]].xrepeat = max(((128+health[snum])>>1),0);
                   2510:                        sprite[playersprite[snum]].yrepeat = max(((128+health[snum])>>1),0);
                   2511: 
                   2512:                        hvel[snum] += (TICSPERFRAME<<2);
                   2513:                        horiz[snum] = max(horiz[snum]-4,0);
                   2514:                        posz[snum] += hvel[snum];
                   2515:                        if (posz[snum] > globloz-(4<<8))
                   2516:                        {
                   2517:                                posz[snum] = globloz-(4<<8);
                   2518:                                horiz[snum] = min(horiz[snum]+5,200);
                   2519:                                hvel[snum] = 0;
                   2520:                        }
                   2521:                }
                   2522:        }
                   2523: 
                   2524:        if (((sync[snum].bits&8) > 0) && (horiz[snum] > 100-(200>>1))) horiz[snum] -= 4;     //-
                   2525:        if (((sync[snum].bits&4) > 0) && (horiz[snum] < 100+(200>>1))) horiz[snum] += 4;   //+
                   2526: 
                   2527:        goalz = globloz-(32<<8);         //32 pixels above floor
                   2528:        if (sector[cursectnum[snum]].lotag == 4)   //slime sector
                   2529:                if ((globlohit&0xc000) != 49152)            //You're not on a sprite
                   2530:                {
                   2531:                        goalz = globloz-(8<<8);
                   2532:                        if (posz[snum] >= goalz-(2<<8))
                   2533:                        {
                   2534:                                clipmove(&posx[snum],&posy[snum],&posz[snum],&cursectnum[snum],-TICSPERFRAME<<14,-TICSPERFRAME<<14,128L,4<<8,4<<8,0);
                   2535: 
                   2536:                                if (slimesoundcnt[snum] >= 0)
                   2537:                                {
                   2538:                                        slimesoundcnt[snum] -= TICSPERFRAME;
                   2539:                                        while (slimesoundcnt[snum] < 0)
                   2540:                                        {
                   2541:                                                slimesoundcnt[snum] += 120;
                   2542:                                                wsayfollow("slime.wav",4096L+(krand()&127)-64,256L,&posx[snum],&posy[snum],1);
                   2543:                                        }
                   2544:                                }
                   2545:                        }
                   2546:                }
                   2547:        if (goalz < globhiz+(16<<8))   //ceiling&floor too close
                   2548:                goalz = ((globloz+globhiz)>>1);
                   2549:        //goalz += mousz;
                   2550:        if (health[snum] >= 0)
                   2551:        {
                   2552:                if ((sync[snum].bits&1) > 0)                         //A (stand high)
                   2553:                {
                   2554:                        if (flytime[snum] <= lockclock)
                   2555:                        {
                   2556:                                if (posz[snum] >= globloz-(32<<8))
                   2557:                                {
                   2558:                                        goalz -= (16<<8);
                   2559:                                        if (sync[snum].bits&256) goalz -= (24<<8);
                   2560:                                }
                   2561:                        }
                   2562:                        else
                   2563:                        {
                   2564:                                hvel[snum] -= 192;
                   2565:                                if (sync[snum].bits&256) hvel[snum] -= 192;
                   2566:                        }
                   2567:                }
                   2568:                if ((sync[snum].bits&2) > 0)                         //Z (stand low)
                   2569:                {
                   2570:                        if (flytime[snum] <= lockclock)
                   2571:                        {
                   2572:                                goalz += (12<<8);
                   2573:                                if (sync[snum].bits&256) goalz += (12<<8);
                   2574:                        }
                   2575:                        else
                   2576:                        {
                   2577:                                hvel[snum] += 192;
                   2578:                                if (sync[snum].bits&256) hvel[snum] += 192;
                   2579:                        }
                   2580:                }
                   2581:        }
                   2582: 
                   2583:        if (flytime[snum] <= lockclock)
                   2584:        {
                   2585:                if (posz[snum] < goalz)
                   2586:                        hvel[snum] += (TICSPERFRAME<<4);
                   2587:                else
                   2588:                        hvel[snum] = (((goalz-posz[snum])*TICSPERFRAME)>>5);
                   2589:        }
                   2590:        else
                   2591:        {
                   2592:                hvel[snum] -= (hvel[snum]>>2);
                   2593:                hvel[snum] -= ksgn(hvel[snum]);
                   2594:        }
                   2595: 
                   2596:        posz[snum] += hvel[snum];
                   2597:        if (posz[snum] > globloz-(4<<8)) posz[snum] = globloz-(4<<8), hvel[snum] = 0;
                   2598:        if (posz[snum] < globhiz+(4<<8)) posz[snum] = globhiz+(4<<8), hvel[snum] = 0;
                   2599: 
                   2600:        if (dimensionmode[snum] != 3)
                   2601:        {
                   2602:                if (((sync[snum].bits&32) > 0) && (zoom[snum] > 48)) zoom[snum] -= (zoom[snum]>>4);
                   2603:                if (((sync[snum].bits&16) > 0) && (zoom[snum] < 4096)) zoom[snum] += (zoom[snum]>>4);
                   2604:        }
                   2605: 
                   2606:                //Update sprite representation of player
                   2607:                //   -should be after movement, but before shooting code
                   2608:        setsprite(playersprite[snum],posx[snum],posy[snum],posz[snum]+(32<<8));
                   2609:        sprite[playersprite[snum]].ang = ang[snum];
                   2610: 
                   2611:        if (health[snum] >= 0)
                   2612:        {
                   2613:                if ((cursectnum[snum] < 0) || (cursectnum[snum] >= numsectors))
                   2614:                {       //How did you get in the wrong sector?
                   2615:                        wsayfollow("ouch.wav",4096L+(krand()&127)-64,64L,&posx[snum],&posy[snum],1);
                   2616:                        changehealth(snum,-TICSPERFRAME);
                   2617:                }
                   2618:                else if (globhiz+(8<<8) > globloz)
                   2619:                {       //Ceiling and floor are smooshing you!
                   2620:                        wsayfollow("ouch.wav",4096L+(krand()&127)-64,64L,&posx[snum],&posy[snum],1);
                   2621:                        changehealth(snum,-TICSPERFRAME);
                   2622:                }
                   2623:        }
                   2624: 
                   2625:        if ((waterfountainwall[snum] >= 0) && (health[snum] >= 0))
                   2626:                if ((wall[neartagwall].lotag != 7) || ((sync[snum].bits&1024) == 0))
                   2627:                {
                   2628:                        i = waterfountainwall[snum];
                   2629:                        if (wall[i].overpicnum == USEWATERFOUNTAIN)
                   2630:                                wall[i].overpicnum = WATERFOUNTAIN;
                   2631:                        else if (wall[i].picnum == USEWATERFOUNTAIN)
                   2632:                                wall[i].picnum = WATERFOUNTAIN;
                   2633: 
                   2634:                        waterfountainwall[snum] = -1;
                   2635:                }
                   2636: 
                   2637:        if ((sync[snum].bits&1024) > 0)  //Space bar
                   2638:        {
                   2639:                        //Continuous triggers...
                   2640: 
                   2641:                neartag(posx[snum],posy[snum],posz[snum],cursectnum[snum],ang[snum],&neartagsector,&neartagwall,&neartagsprite,&neartaghitdist,1024L,3);
                   2642:                if (neartagsector == -1)
                   2643:                {
                   2644:                        i = cursectnum[snum];
                   2645:                        if ((sector[i].lotag|sector[i].hitag) != 0)
                   2646:                                neartagsector = i;
                   2647:                }
                   2648: 
                   2649:                if (wall[neartagwall].lotag == 7)  //Water fountain
                   2650:                {
                   2651:                        if (wall[neartagwall].overpicnum == WATERFOUNTAIN)
                   2652:                        {
                   2653:                                wsayfollow("water.wav",4096L+(krand()&127)-64,256L,&posx[snum],&posy[snum],1);
                   2654:                                wall[neartagwall].overpicnum = USEWATERFOUNTAIN;
                   2655:                                waterfountainwall[snum] = neartagwall;
                   2656:                        }
                   2657:                        else if (wall[neartagwall].picnum == WATERFOUNTAIN)
                   2658:                        {
                   2659:                                wsayfollow("water.wav",4096L+(krand()&127)-64,256L,&posx[snum],&posy[snum],1);
                   2660:                                wall[neartagwall].picnum = USEWATERFOUNTAIN;
                   2661:                                waterfountainwall[snum] = neartagwall;
                   2662:                        }
                   2663: 
                   2664:                        if (waterfountainwall[snum] >= 0)
                   2665:                        {
                   2666:                                waterfountaincnt[snum] -= TICSPERFRAME;
                   2667:                                while (waterfountaincnt[snum] < 0)
                   2668:                                {
                   2669:                                        waterfountaincnt[snum] += 120;
                   2670:                                        wsayfollow("water.wav",4096L+(krand()&127)-64,256L,&posx[snum],&posy[snum],1);
                   2671:                                        changehealth(snum,2);
                   2672:                                }
                   2673:                        }
                   2674:                }
                   2675: 
                   2676:                        //1-time triggers...
                   2677:                if ((oflags[snum]&1024) == 0)
                   2678:                {
                   2679:                        if (neartagsector >= 0)
                   2680:                                if (sector[neartagsector].hitag == 0)
                   2681:                                        operatesector(neartagsector);
                   2682: 
                   2683:                        if (neartagwall >= 0)
                   2684:                                if (wall[neartagwall].lotag == 2)  //Switch
                   2685:                                {
                   2686:                                        activatehitag(wall[neartagwall].hitag);
                   2687: 
                   2688:                                        j = wall[neartagwall].overpicnum;
                   2689:                                        if (j == SWITCH1ON)                     //1-time switch
                   2690:                                        {
                   2691:                                                wall[neartagwall].overpicnum = GIFTBOX;
                   2692:                                                wall[neartagwall].lotag = 0;
                   2693:                                                wall[neartagwall].hitag = 0;
                   2694:                                        }
                   2695:                                        if (j == GIFTBOX)                       //1-time switch
                   2696:                                        {
                   2697:                                                wall[neartagwall].overpicnum = SWITCH1ON;
                   2698:                                                wall[neartagwall].lotag = 0;
                   2699:                                                wall[neartagwall].hitag = 0;
                   2700:                                        }
                   2701:                                        if (j == SWITCH2ON) wall[neartagwall].overpicnum = SWITCH2OFF;
                   2702:                                        if (j == SWITCH2OFF) wall[neartagwall].overpicnum = SWITCH2ON;
                   2703:                                        if (j == SWITCH3ON) wall[neartagwall].overpicnum = SWITCH3OFF;
                   2704:                                        if (j == SWITCH3OFF) wall[neartagwall].overpicnum = SWITCH3ON;
                   2705: 
                   2706:                                        i = wall[neartagwall].point2;
                   2707:                                        dax = ((wall[neartagwall].x+wall[i].x)>>1);
                   2708:                                        day = ((wall[neartagwall].y+wall[i].y)>>1);
                   2709:                                        wsayfollow("switch.wav",4096L+(krand()&255)-128,256L,&dax,&day,0);
                   2710:                                }
                   2711: 
                   2712:                        if (neartagsprite >= 0)
                   2713:                        {
                   2714:                                if (sprite[neartagsprite].lotag == 1)
                   2715:                                {  //if you're shoving innocent little AL around, he gets mad!
                   2716:                                        if (sprite[neartagsprite].picnum == AL)
                   2717:                                        {
                   2718:                                                sprite[neartagsprite].picnum = EVILAL;
                   2719:                                                sprite[neartagsprite].cstat |= 2;   //Make him transluscent
                   2720:                                                sprite[neartagsprite].xrepeat = 38;
                   2721:                                                sprite[neartagsprite].yrepeat = 38;
                   2722:                                                changespritestat(neartagsprite,10);
                   2723:                                        }
                   2724:                                }
                   2725:                                if (sprite[neartagsprite].lotag == 4)
                   2726:                                {
                   2727:                                        activatehitag(sprite[neartagsprite].hitag);
                   2728: 
                   2729:                                        j = sprite[neartagsprite].picnum;
                   2730:                                        if (j == SWITCH1ON)                     //1-time switch
                   2731:                                        {
                   2732:                                                sprite[neartagsprite].picnum = GIFTBOX;
                   2733:                                                sprite[neartagsprite].lotag = 0;
                   2734:                                                sprite[neartagsprite].hitag = 0;
                   2735:                                        }
                   2736:                                        if (j == GIFTBOX)                       //1-time switch
                   2737:                                        {
                   2738:                                                sprite[neartagsprite].picnum = SWITCH1ON;
                   2739:                                                sprite[neartagsprite].lotag = 0;
                   2740:                                                sprite[neartagsprite].hitag = 0;
                   2741:                                        }
                   2742:                                        if (j == SWITCH2ON) sprite[neartagsprite].picnum = SWITCH2OFF;
                   2743:                                        if (j == SWITCH2OFF) sprite[neartagsprite].picnum = SWITCH2ON;
                   2744:                                        if (j == SWITCH3ON) sprite[neartagsprite].picnum = SWITCH3OFF;
                   2745:                                        if (j == SWITCH3OFF) sprite[neartagsprite].picnum = SWITCH3ON;
                   2746: 
                   2747:                                        dax = sprite[neartagsprite].x;
                   2748:                                        day = sprite[neartagsprite].y;
                   2749:                                        wsayfollow("switch.wav",4096L+(krand()&255)-128,256L,&dax,&day,0);
                   2750:                                }
                   2751:                        }
                   2752:                }
                   2753:        }
                   2754: 
                   2755:        if ((sync[snum].bits&2048) > 0)      //Shoot a bullet
                   2756:        {
                   2757:                if ((numbombs[snum] == 0) && (((sync[snum].bits>>13)&7) == 2) && (myconnectindex == snum))
                   2758:                        locselectedgun = 1;
                   2759: 
                   2760:                if ((health[snum] >= 0) || ((krand()&127) > -health[snum]))
                   2761:                        switch((sync[snum].bits>>13)&7)
                   2762:                        {
                   2763:                                case 0:
                   2764:                                        if ((oflags[snum]&2048) == 0)
                   2765:                                                shootgun(snum,posx[snum],posy[snum],posz[snum],ang[snum],horiz[snum],cursectnum[snum],0);
                   2766:                                        break;
                   2767:                                case 1:
                   2768:                                        if (lockclock > lastchaingun[snum]+8)
                   2769:                                        {
                   2770:                                                lastchaingun[snum] = lockclock;
                   2771:                                                shootgun(snum,posx[snum],posy[snum],posz[snum],ang[snum],horiz[snum],cursectnum[snum],1);
                   2772:                                        }
                   2773:                                        break;
                   2774:                                case 2:
                   2775:                                        if ((oflags[snum]&2048) == 0)
                   2776:                                                if (numbombs[snum] > 0)
                   2777:                                                {
                   2778:                                                        shootgun(snum,posx[snum],posy[snum],posz[snum],ang[snum],horiz[snum],cursectnum[snum],2);
                   2779:                                                        numbombs[snum]--;
                   2780:                                                }
                   2781:                                        break;
                   2782:                        }
                   2783:        }
                   2784: 
                   2785:        if ((sync[snum].bits&4096) > (oflags[snum]&4096))  //Keypad enter
                   2786:        {
                   2787:                dimensionmode[snum]++;
                   2788:                if (dimensionmode[snum] > 3) dimensionmode[snum] = 1;
                   2789:        }
                   2790: 
                   2791:        oflags[snum] = sync[snum].bits;
                   2792: }
                   2793: 
                   2794: drawscreen(short snum, long dasmoothratio)
                   2795: {
                   2796:        long i, j, k, l, charsperline, templong;
                   2797:        long x1, y1, x2, y2, ox1, oy1, ox2, oy2, dist, maxdist;
                   2798:        long cposx, cposy, cposz, choriz, czoom, tposx, tposy;
                   2799:        long tiltlock, *longptr, ovisibility, oparallaxvisibility;
                   2800:        short cang, tang;
                   2801:        char ch, *ptr, *ptr2, *ptr3, *ptr4;
                   2802:        spritetype *tspr;
                   2803: 
                   2804:        smoothratio = max(min(dasmoothratio,65536),0);
                   2805: 
                   2806:        dointerpolations();
                   2807: 
                   2808:        cposx = oposx[snum]+mulscale16(posx[snum]-oposx[snum],smoothratio);
                   2809:        cposy = oposy[snum]+mulscale16(posy[snum]-oposy[snum],smoothratio);
                   2810:        cposz = oposz[snum]+mulscale16(posz[snum]-oposz[snum],smoothratio);
                   2811:        choriz = ohoriz[snum]+mulscale16(horiz[snum]-ohoriz[snum],smoothratio);
                   2812:        czoom = ozoom[snum]+mulscale16(zoom[snum]-ozoom[snum],smoothratio);
                   2813:        cang = oang[snum]+mulscale16(((ang[snum]+1024-oang[snum])&2047)-1024,smoothratio);
                   2814: 
                   2815:        setears(cposx,cposy,(long)sintable[(cang+512)&2047]<<14,(long)sintable[cang&2047]<<14);
                   2816: 
                   2817:        if (typemode != 0)
                   2818:        {
                   2819:                charsperline = 40;
                   2820:                //if (dimensionmode[snum] == 2) charsperline = 80;
                   2821: 
                   2822:                for(i=0;i<=typemessageleng;i+=charsperline)
                   2823:                {
                   2824:                        for(j=0;j<charsperline;j++)
                   2825:                                tempbuf[j] = typemessage[i+j];
                   2826:                        if (typemessageleng < i+charsperline)
                   2827:                        {
                   2828:                                tempbuf[(typemessageleng-i)] = '_';
                   2829:                                tempbuf[(typemessageleng-i)+1] = 0;
                   2830:                        }
                   2831:                        else
                   2832:                                tempbuf[charsperline] = 0;
                   2833:                        //if (dimensionmode[snum] == 3)
                   2834:                                printext256(0L,(i/charsperline)<<3,183,-1,tempbuf,0);
                   2835:                        //else
                   2836:                        //   printext16(0L,((i/charsperline)<<3)+(pageoffset/640),10,-1,tempbuf,0);
                   2837:                }
                   2838:        }
                   2839:        else
                   2840:        {
                   2841:                if (dimensionmode[myconnectindex] == 3)
                   2842:                {
                   2843:                        templong = screensize;
                   2844: 
                   2845:                        if (((loc.bits&32) > (screensizeflag&32)) && (screensize > 64))
                   2846:                        {
                   2847:                                ox1 = ((xdim-screensize)>>1);
                   2848:                                ox2 = ox1+screensize-1;
                   2849:                                oy1 = (((ydim-32)-scale(screensize,ydim-32,xdim))>>1);
                   2850:                                oy2 = oy1 + scale(screensize,ydim-32,xdim)-1;
                   2851:                                screensize -= (screensize>>3);
                   2852: 
                   2853:                                if (templong > xdim)
                   2854:                                {
                   2855:                                        screensize = xdim;
                   2856: 
                   2857:                                        rotatesprite((xdim-320)<<15,(ydim-32)<<16,65536L,0,STATUSBAR,0,0,8+16+64+128,0L,0L,xdim-1L,ydim-1L);
                   2858:                                        i = ((xdim-320)>>1);
                   2859:                                        while (i >= 8) i -= 8, rotatesprite(i<<16,(ydim-32)<<16,65536L,0,STATUSBARFILL8,0,0,8+16+64+128,0L,0L,xdim-1L,ydim-1L);
                   2860:                                        if (i >= 4) i -= 4, rotatesprite(i<<16,(ydim-32)<<16,65536L,0,STATUSBARFILL4,0,0,8+16+64+128,0L,0L,xdim-1L,ydim-1L);
                   2861:                                        i = ((xdim-320)>>1)+320;
                   2862:                                        while (i <= xdim-8) rotatesprite(i<<16,(ydim-32)<<16,65536L,0,STATUSBARFILL8,0,0,8+16+64+128,0L,0L,xdim-1L,ydim-1L), i += 8;
                   2863:                                        if (i <= xdim-4) rotatesprite(i<<16,(ydim-32)<<16,65536L,0,STATUSBARFILL4,0,0,8+16+64+128,0L,0L,xdim-1L,ydim-1L), i += 4;
                   2864: 
                   2865:                                        sprintf(&tempbuf,"Deaths: %d",deaths[screenpeek]);
                   2866:                                        printext((xdim>>1)-(strlen(tempbuf)<<2),ydim-16,tempbuf,ALPHABET,80);
                   2867: 
                   2868:                                        sprintf(&tempbuf,"Health: %3d",health[screenpeek]);
                   2869:                                        printext((xdim>>1)-(strlen(tempbuf)<<2),ydim-24,tempbuf,ALPHABET,80);
                   2870:                                }
                   2871: 
                   2872:                                x1 = ((xdim-screensize)>>1);
                   2873:                                x2 = x1+screensize-1;
                   2874:                                y1 = (((ydim-32)-scale(screensize,ydim-32,xdim))>>1);
                   2875:                                y2 = y1 + scale(screensize,ydim-32,xdim)-1;
                   2876:                                setview(x1,y1,x2,y2);
                   2877: 
                   2878:                                // (ox1,oy1)旼컴컴컴컴컴컴컴컴
                   2879:                                //            (x1,y1)        
                   2880:                                //               旼컴컴     
                   2881:                                //                         
                   2882:                                //               읕컴컴     
                   2883:                                //                  (x2,y2)  
                   2884:                                //          읕컴컴컴컴컴컴컴컴(ox2,oy2)
                   2885: 
                   2886:                                drawtilebackground(0L,0L,BACKGROUND,8,ox1,oy1,x1-1,oy2,0);
                   2887:                                drawtilebackground(0L,0L,BACKGROUND,8,x2+1,oy1,ox2,oy2,0);
                   2888:                                drawtilebackground(0L,0L,BACKGROUND,8,x1,oy1,x2,y1-1,0);
                   2889:                                drawtilebackground(0L,0L,BACKGROUND,8,x1,y2+1,x2,oy2,0);
                   2890:                        }
                   2891:                        if (((loc.bits&16) > (screensizeflag&16)) && (screensize <= xdim))
                   2892:                        {
                   2893:                                screensize += (screensize>>3);
                   2894:                                if ((screensize > xdim) && (templong == xdim))
                   2895:                                {
                   2896:                                        screensize = xdim+1;
                   2897:                                        x1 = 0; y1 = 0;
                   2898:                                        x2 = xdim-1; y2 = ydim-1;
                   2899:                                }
                   2900:                                else
                   2901:                                {
                   2902:                                        if (screensize > xdim) screensize = xdim;
                   2903:                                        x1 = ((xdim-screensize)>>1);
                   2904:                                        x2 = x1+screensize-1;
                   2905:                                        y1 = (((ydim-32)-scale(screensize,ydim-32,xdim))>>1);
                   2906:                                        y2 = y1 + scale(screensize,ydim-32,xdim)-1;
                   2907:                                }
                   2908:                                setview(x1,y1,x2,y2);
                   2909:                        }
                   2910:                        screensizeflag = loc.bits;
                   2911:                }
                   2912:        }
                   2913: 
                   2914:        if (dimensionmode[snum] != 2)
                   2915:        {
                   2916:                if ((numplayers > 1) && (option[4] == 0))
                   2917:                {
                   2918:                                //Do not draw other views constantly if they're staying still
                   2919:                                //It's a shame this trick will only work in screen-buffer mode
                   2920:                                //At least screen-buffer mode covers all the HI hi-res modes
                   2921:                        if (vidoption == 2)
                   2922:                        {
                   2923:                                for(i=connecthead;i>=0;i=connectpoint2[i]) frame2draw[i] = 0;
                   2924:                                frame2draw[snum] = 1;
                   2925: 
                   2926:                                        //2-1,3-1,4-2
                   2927:                                        //5-2,6-2,7-2,8-3,9-3,10-3,11-3,12-4,13-4,14-4,15-4,16-5
                   2928:                                x1 = posx[snum]; y1 = posy[snum];
                   2929:                                for(j=(numplayers>>2)+1;j>0;j--)
                   2930:                                {
                   2931:                                        maxdist = 0x80000000;
                   2932:                                        for(i=connecthead;i>=0;i=connectpoint2[i])
                   2933:                                                if (frame2draw[i] == 0)
                   2934:                                                {
                   2935:                                                        x2 = posx[i]-x1; y2 = posy[i]-y1;
                   2936:                                                        dist = dmulscale12(x2,x2,y2,y2);
                   2937: 
                   2938:                                                        if (dist < 64) dist = 16384;
                   2939:                                                        else if (dist > 16384) dist = 64;
                   2940:                                                        else dist = 1048576 / dist;
                   2941: 
                   2942:                                                        dist *= frameskipcnt[i];
                   2943: 
                   2944:                                                                //Increase frame rate if screen is moving
                   2945:                                                        if ((posx[i] != oposx[i]) || (posy[i] != oposy[i]) ||
                   2946:                                                                 (posz[i] != oposz[i]) || (ang[i] != oang[i]) ||
                   2947:                                                                 (horiz[i] != ohoriz[i])) dist += dist;
                   2948: 
                   2949:                                                        if (dist > maxdist) maxdist = dist, k = i;
                   2950:                                                }
                   2951: 
                   2952:                                        for(i=connecthead;i>=0;i=connectpoint2[i])
                   2953:                                                frameskipcnt[i] += (frameskipcnt[i]>>3)+1;
                   2954:                                        frameskipcnt[k] = 0;
                   2955: 
                   2956:                                        frame2draw[k] = 1;
                   2957:                                }
                   2958:                        }
                   2959:                        else
                   2960:                        {
                   2961:                                for(i=connecthead;i>=0;i=connectpoint2[i]) frame2draw[i] = 1;
                   2962:                        }
                   2963: 
                   2964:                        for(i=connecthead,j=0;i>=0;i=connectpoint2[i],j++)
                   2965:                                if (frame2draw[i] != 0)
                   2966:                                {
                   2967:                                        if (numplayers <= 4)
                   2968:                                        {
                   2969:                                                switch(j)
                   2970:                                                {
                   2971:                                                        case 0: setview(0,0,(xdim>>1)-1,(ydim>>1)-1); break;
                   2972:                                                        case 1: setview((xdim>>1),0,xdim-1,(ydim>>1)-1); break;
                   2973:                                                        case 2: setview(0,(ydim>>1),(xdim>>1)-1,ydim-1); break;
                   2974:                                                        case 3: setview((xdim>>1),(ydim>>1),xdim-1,ydim-1); break;
                   2975:                                                }
                   2976:                                        }
                   2977:                                        else
                   2978:                                        {
                   2979:                                                switch(j)
                   2980:                                                {
                   2981:                                                        case 0: setview(0,0,(xdim>>2)-1,(ydim>>2)-1); break;
                   2982:                                                        case 1: setview(xdim>>2,0,(xdim>>1)-1,(ydim>>2)-1); break;
                   2983:                                                        case 2: setview(xdim>>1,0,xdim-(xdim>>2)-1,(ydim>>2)-1); break;
                   2984:                                                        case 3: setview(xdim-(xdim>>2),0,xdim-1,(ydim>>2)-1); break;
                   2985:                                                        case 4: setview(0,ydim>>2,(xdim>>2)-1,(ydim>>1)-1); break;
                   2986:                                                        case 5: setview(xdim>>2,ydim>>2,(xdim>>1)-1,(ydim>>1)-1); break;
                   2987:                                                        case 6: setview(xdim>>1,ydim>>2,xdim-(xdim>>2)-1,(ydim>>1)-1); break;
                   2988:                                                        case 7: setview(xdim-(xdim>>2),ydim>>2,xdim-1,(ydim>>1)-1); break;
                   2989:                                                        case 8: setview(0,ydim>>1,(xdim>>2)-1,ydim-(ydim>>2)-1); break;
                   2990:                                                        case 9: setview(xdim>>2,ydim>>1,(xdim>>1)-1,ydim-(ydim>>2)-1); break;
                   2991:                                                        case 10: setview(xdim>>1,ydim>>1,xdim-(xdim>>2)-1,ydim-(ydim>>2)-1); break;
                   2992:                                                        case 11: setview(xdim-(xdim>>2),ydim>>1,xdim-1,ydim-(ydim>>2)-1); break;
                   2993:                                                        case 12: setview(0,ydim-(ydim>>2),(xdim>>2)-1,ydim-1); break;
                   2994:                                                        case 13: setview(xdim>>2,ydim-(ydim>>2),(xdim>>1)-1,ydim-1); break;
                   2995:                                                        case 14: setview(xdim>>1,ydim-(ydim>>2),xdim-(xdim>>2)-1,ydim-1); break;
                   2996:                                                        case 15: setview(xdim-(xdim>>2),ydim-(ydim>>2),xdim-1,ydim-1); break;
                   2997:                                                }
                   2998:                                        }
                   2999: 
                   3000:                                        if (i == snum)
                   3001:                                        {
                   3002:                                                drawrooms(cposx,cposy,cposz,cang,choriz,cursectnum[i]);
                   3003:                                                analyzesprites(cposx,cposy);
                   3004:                                        }
                   3005:                                        else
                   3006:                                        {
                   3007:                                                drawrooms(posx[i],posy[i],posz[i],ang[i],horiz[i],cursectnum[i]);
                   3008:                                                analyzesprites(posx[i],posy[i]);
                   3009:                                        }
                   3010:                                        drawmasks();
                   3011:                                        if (numbombs[i] > 0)
                   3012:                                                rotatesprite(160<<16,184L<<16,65536,0,GUNONBOTTOM,sector[cursectnum[i]].floorshade,0,2,windowx1,windowy1,windowx2,windowy2);
                   3013: 
                   3014:                                        if (lockclock < 384)
                   3015:                                        {
                   3016:                                                if (lockclock < 128)
                   3017:                                                        rotatesprite(320<<15,200<<15,lockclock<<9,lockclock<<4,DEMOSIGN,(128-lockclock)>>2,0,1+2,windowx1,windowy1,windowx2,windowy2);
                   3018:                                                else if (lockclock < 256)
                   3019:                                                        rotatesprite(320<<15,200<<15,65536,0,DEMOSIGN,0,0,2,windowx1,windowy1,windowx2,windowy2);
                   3020:                                                else
                   3021:                                                        rotatesprite(320<<15,200<<15,(384-lockclock)<<9,lockclock<<4,DEMOSIGN,(lockclock-256)>>2,0,1+2,windowx1,windowy1,windowx2,windowy2);
                   3022:                                        }
                   3023: 
                   3024:                                        if (health[i] <= 0)
                   3025:                                                rotatesprite(320<<15,200<<15,(-health[i])<<11,(-health[i])<<5,NO,0,0,2,windowx1,windowy1,windowx2,windowy2);
                   3026:                                }
                   3027:                }
                   3028:                else
                   3029:                {
                   3030:                                //Init for screen rotation
                   3031:                        tiltlock = screentilt;
                   3032:                        if ((tiltlock) || (detailmode))
                   3033:                        {
                   3034:                                walock[4094] = 255;
                   3035:                                if (waloff[4094] == 0)
                   3036:                                        allocache(&waloff[4094],320L*320L,&walock[4094]);
                   3037:                                if ((tiltlock&1023) == 0)
                   3038:                                        setviewtotile(4094,200L>>detailmode,320L>>detailmode);
                   3039:                                else
                   3040:                                        setviewtotile(4094,320L>>detailmode,320L>>detailmode);
                   3041:                                if ((tiltlock&1023) == 512)
                   3042:                                {     //Block off unscreen section of 90 tilted screen
                   3043:                                        j = ((320-60)>>detailmode);
                   3044:                                        for(i=(60>>detailmode)-1;i>=0;i--)
                   3045:                                        {
                   3046:                                                startumost[i] = 1; startumost[i+j] = 1;
                   3047:                                                startdmost[i] = 0; startdmost[i+j] = 0;
                   3048:                                        }
                   3049:                                }
                   3050:                        }
                   3051: 
                   3052:                        if ((gotpic[FLOORMIRROR>>3]&(1<<(FLOORMIRROR&7))) > 0)
                   3053:                        {
                   3054:                                if (!chainstat)
                   3055:                                {
                   3056:                                        dist = 0x7fffffff; i = 0;
                   3057:                                        for(k=floormirrorcnt-1;k>=0;k--)
                   3058:                                        {
                   3059:                                                j = klabs(wall[sector[floormirrorsector[k]].wallptr].x-cposx);
                   3060:                                                j += klabs(wall[sector[floormirrorsector[k]].wallptr].y-cposy);
                   3061:                                                if (j < dist) dist = j, i = k;
                   3062:                                        }
                   3063: 
                   3064:                                        j = floormirrorsector[i];
                   3065: 
                   3066:                                        drawrooms(cposx,cposy,(sector[j].floorz<<1)-cposz,cang,201-choriz,j);
                   3067:                                        analyzesprites(cposx,cposy);
                   3068:                                        drawmasks();
                   3069: 
                   3070:                                                //Temp horizon
                   3071:                                        l = scale(choriz-100,windowx2-windowx1,320)+((windowy1+windowy2)>>1);
                   3072:                                        for(y1=windowy1,y2=windowy2;y1<y2;y1++,y2--)
                   3073:                                        {
                   3074:                                                ptr = (char *)(frameplace+ylookup[y1]);
                   3075:                                                ptr2 = (char *)(frameplace+ylookup[y2]);
                   3076:                                                ptr3 = palookup[18];
                   3077:                                                ptr3 += (min(klabs(y1-l)>>2,31)<<8);
                   3078:                                                ptr4 = palookup[18];
                   3079:                                                ptr4 += (min(klabs(y2-l)>>2,31)<<8);
                   3080: 
                   3081:                                                j = sintable[((y2+numframes)<<7)&2047];
                   3082:                                                j += sintable[((y2-numframes)<<8)&2047];
                   3083:                                                j >>= 14;
                   3084: 
                   3085:                                                ptr2 += j;
                   3086: 
                   3087:                                                for(x1=windowx1;x1<=windowx2;x1++)
                   3088:                                                        { ch = ptr[x1]; ptr[x1] = ptr3[ptr2[x1]]; ptr2[x1] = ptr4[ch]; }
                   3089:                                        }
                   3090:                                        gotpic[FLOORMIRROR>>3] &= ~(1<<(FLOORMIRROR&7));
                   3091:                                }
                   3092:                        }
                   3093: 
                   3094:                                //Startdmost optimization for weapons
                   3095:                        if ((numbombs[screenpeek] > 0) && (windowx1 == 0) && (windowx2 == 319) && (yxaspect == 65536) && (tiltlock == 0))
                   3096:                        {
                   3097:                                x1 = 160L-(tilesizx[GUNONBOTTOM]>>1);
                   3098:                                y1 = 184L-(tilesizy[GUNONBOTTOM]>>1);
                   3099:                                for(i=0;i<tilesizx[GUNONBOTTOM];i++)
                   3100:                                        startdmost[i+x1] = min(windowy2+1,gundmost[i]+y1);
                   3101:                        }
                   3102: 
                   3103:                                //WARNING!  Assuming (MIRRORLABEL&31) = 0 and MAXMIRRORS = 64
                   3104:                        longptr = (long *)FP_OFF(gotpic[MIRRORLABEL>>3]);
                   3105:                        if (longptr[0]|longptr[1])
                   3106:                                for(i=MAXMIRRORS-1;i>=0;i--)
                   3107:                                        if (gotpic[(i+MIRRORLABEL)>>3]&(1<<(i&7)))
                   3108:                                        {
                   3109:                                                gotpic[(i+MIRRORLABEL)>>3] &= ~(1<<(i&7));
                   3110: 
                   3111:                                                        //Prepare drawrooms for drawing mirror and calculate reflected
                   3112:                                                        //position into tposx, tposy, and tang (tposz == cposz)
                   3113:                                                        //Must call preparemirror before drawrooms and
                   3114:                                                        //          completemirror after drawrooms
                   3115:                                                preparemirror(cposx,cposy,cposz,cang,choriz,
                   3116:                                                                          mirrorwall[i],mirrorsector[i],&tposx,&tposy,&tang);
                   3117: 
                   3118:                                                ovisibility = visibility;
                   3119:                                                oparallaxvisibility = parallaxvisibility;
                   3120:                                                visibility <<= 1;
                   3121:                                                parallaxvisibility <<= 1;
                   3122:                                                ptr = palookup[0]; palookup[0] = palookup[17]; palookup[17] = ptr;
                   3123: 
                   3124:                                                drawrooms(tposx,tposy,cposz,tang,choriz,mirrorsector[i]);
                   3125:                                                for(j=0,tspr=&tsprite[0];j<spritesortcnt;j++,tspr++)
                   3126:                                                        if ((tspr->cstat&48) == 0) tspr->cstat |= 4;
                   3127:                                                analyzesprites(tposx,tposy);
                   3128:                                                drawmasks();
                   3129: 
                   3130:                                                ptr = palookup[0]; palookup[0] = palookup[17]; palookup[17] = ptr;
                   3131:                                                visibility = ovisibility;
                   3132:                                                parallaxvisibility = oparallaxvisibility;
                   3133: 
                   3134:                                                completemirror();   //Reverse screen x-wise in this function
                   3135: 
                   3136:                                                break;
                   3137:                                        }
                   3138: 
                   3139:                                //Over the shoulder mode
                   3140:                        //cposx -= (sintable[(cang+512)&2047]>>4);
                   3141:                        //cposy -= (sintable[cang&2047]>>4);
                   3142:                        drawrooms(cposx,cposy,cposz,cang,choriz,cursectnum[snum]);
                   3143:                        analyzesprites(cposx,cposy);
                   3144:                        drawmasks();
                   3145: 
                   3146:                        if ((gotpic[FLOORMIRROR>>3]&(1<<(FLOORMIRROR&7))) > 0)
                   3147:                                transarea += (windowx2-windowx1)*(windowy2-windowy1);
                   3148: 
                   3149:                                //Finish for screen rotation
                   3150:                        if ((tiltlock) || (detailmode))
                   3151:                        {
                   3152:                                setviewback();
                   3153:                                rotatesprite(320<<15,200<<15,65536+(detailmode<<16),tiltlock+512,4094,0,0,2+4+64,windowx1,windowy1,windowx2,windowy2);
                   3154:                                walock[4094] = 1;
                   3155:                        }
                   3156: 
                   3157:                        if (numbombs[screenpeek] > 0)
                   3158:                        {
                   3159:                                        //Reset startdmost to bottom of screen
                   3160:                                if ((windowx1 == 0) && (windowx2 == 319) && (yxaspect == 65536) && (tiltlock == 0))
                   3161:                                {
                   3162:                                        x1 = 160L-(tilesizx[GUNONBOTTOM]>>1); y1 = windowy2+1;
                   3163:                                        for(i=0;i<tilesizx[GUNONBOTTOM];i++)
                   3164:                                                startdmost[i+x1] = y1;
                   3165:                                }
                   3166:                                rotatesprite(160<<16,184L<<16,65536,0,GUNONBOTTOM,sector[cursectnum[screenpeek]].floorshade,0,2,windowx1,windowy1,windowx2,windowy2);
                   3167:                        }
                   3168: 
                   3169:                        if (cachecount != 0)
                   3170:                        {
                   3171:                                rotatesprite((320-16)<<16,16<<16,32768,0,BUILDDISK,0,0,2+64,windowx1,windowy1,windowx2,windowy2);
                   3172:                                cachecount = 0;
                   3173:                        }
                   3174: 
                   3175:                        if (lockclock < 384)
                   3176:                        {
                   3177:                                if (lockclock < 128)
                   3178:                                        rotatesprite(320<<15,200<<15,lockclock<<9,lockclock<<4,DEMOSIGN,(128-lockclock)>>2,0,1+2,windowx1,windowy1,windowx2,windowy2);
                   3179:                                else if (lockclock < 256)
                   3180:                                        rotatesprite(320<<15,200<<15,65536,0,DEMOSIGN,0,0,2,windowx1,windowy1,windowx2,windowy2);
                   3181:                                else
                   3182:                                        rotatesprite(320<<15,200<<15,(384-lockclock)<<9,lockclock<<4,DEMOSIGN,(lockclock-256)>>2,0,1+2,windowx1,windowy1,windowx2,windowy2);
                   3183:                        }
                   3184: 
                   3185:                        if (health[screenpeek] <= 0)
                   3186:                                rotatesprite(320<<15,200<<15,(-health[screenpeek])<<11,(-health[screenpeek])<<5,NO,0,0,2,windowx1,windowy1,windowx2,windowy2);
                   3187:                }
                   3188:        }
                   3189: 
                   3190:                //Only animate lava if its picnum is on screen
                   3191:                //gotpic is a bit array where the tile number's bit is set
                   3192:                //whenever it is drawn (ceilings, walls, sprites, etc.)
                   3193:        if ((gotpic[SLIME>>3]&(1<<(SLIME&7))) > 0)
                   3194:        {
                   3195:                gotpic[SLIME>>3] &= ~(1<<(SLIME&7));
                   3196:                if (waloff[SLIME] != 0) movelava((char *)waloff[SLIME]);
                   3197:        }
                   3198: 
                   3199:        if ((show2dsector[cursectnum[snum]>>3]&(1<<(cursectnum[snum]&7))) == 0)
                   3200:                searchmap(cursectnum[snum]);
                   3201: 
                   3202:        if (dimensionmode[snum] != 3)
                   3203:        {
                   3204:                        //Move back pivot point
                   3205:                i = scale(czoom,screensize,320);
                   3206:                if (dimensionmode[snum] == 2)
                   3207:                {
                   3208:                        clearview(0L);  //Clear screen to specified color
                   3209:                        drawmapview(cposx,cposy,i,cang);
                   3210:                }
                   3211:                drawoverheadmap(cposx,cposy,i,cang);
                   3212:        }
                   3213: 
                   3214:        if (getmessageleng > 0)
                   3215:        {
                   3216:                charsperline = 40;
                   3217:                //if (dimensionmode[snum] == 2) charsperline = 80;
                   3218: 
                   3219:                for(i=0;i<=getmessageleng;i+=charsperline)
                   3220:                {
                   3221:                        for(j=0;j<charsperline;j++)
                   3222:                                tempbuf[j] = getmessage[i+j];
                   3223:                        if (getmessageleng < i+charsperline)
                   3224:                                tempbuf[(getmessageleng-i)] = 0;
                   3225:                        else
                   3226:                                tempbuf[charsperline] = 0;
                   3227: 
                   3228:                        printext256(0L,((i/charsperline)<<3)+(200-32-8)-(((getmessageleng-1)/charsperline)<<3),151,-1,tempbuf,0);
                   3229:                }
                   3230:                if (totalclock > getmessagetimeoff)
                   3231:                        getmessageleng = 0;
                   3232:        }
                   3233:        if ((numplayers >= 2) && (screenpeek != myconnectindex))
                   3234:        {
                   3235:                j = 1;
                   3236:                for(i=connecthead;i>=0;i=connectpoint2[i])
                   3237:                {
                   3238:                        if (i == screenpeek) break;
                   3239:                        j++;
                   3240:                }
                   3241:                sprintf(tempbuf,"(Player %ld's view)",j);
                   3242:                printext256((xdim>>1)-(strlen(tempbuf)<<2),0,24,-1,tempbuf,0);
                   3243:        }
                   3244: 
                   3245:        if (syncstat != 0) printext256(68L,84L,31,0,"OUT OF SYNC!",0);
                   3246:        if (syncstate != 0) printext256(68L,92L,31,0,"Missed Network packet!",0);
                   3247: 
                   3248:        nextpage();
                   3249: 
                   3250:        if (keystatus[0x3f] > 0)   //F5
                   3251:        {
                   3252:                keystatus[0x3f] = 0;
                   3253:                detailmode ^= 1;
                   3254:        }
                   3255:        if (keystatus[0x58] > 0)   //F12
                   3256:        {
                   3257:                keystatus[0x58] = 0;
                   3258:                screencapture("captxxxx.pcx",keystatus[0x2a]|keystatus[0x36]);
                   3259:        }
                   3260:        if (stereofps != 0)  //Adjustments for red-blue / 120 crystal eyes modes
                   3261:        {
                   3262:                if ((keystatus[0x2a]|keystatus[0x36]) > 0)
                   3263:                {
                   3264:                        if (keystatus[0x1a] > 0) stereopixelwidth--;   //Shift [
                   3265:                        if (keystatus[0x1b] > 0) stereopixelwidth++;   //Shift ]
                   3266:                }
                   3267:                else
                   3268:                {
                   3269:                        if (keystatus[0x1a] > 0) stereowidth -= 512;   //[
                   3270:                        if (keystatus[0x1b] > 0) stereowidth += 512;   //]
                   3271:                }
                   3272:        }
                   3273: 
                   3274:        if (option[4] == 0)           //Single player only keys
                   3275:        {
                   3276:                if (keystatus[0xd2] > 0)   //Insert - Insert player
                   3277:                {
                   3278:                        keystatus[0xd2] = 0;
                   3279:                        if (numplayers < MAXPLAYERS)
                   3280:                        {
                   3281:                                connectpoint2[numplayers-1] = numplayers;
                   3282:                                connectpoint2[numplayers] = -1;
                   3283: 
                   3284:                                initplayersprite(numplayers);
                   3285: 
                   3286:                                clearallviews(0L);  //Clear screen to specified color
                   3287: 
                   3288:                                numplayers++;
                   3289:                        }
                   3290:                }
                   3291:                if (keystatus[0xd3] > 0)   //Delete - Delete player
                   3292:                {
                   3293:                        keystatus[0xd3] = 0;
                   3294:                        if (numplayers > 1)
                   3295:                        {
                   3296:                                numplayers--;
                   3297:                                connectpoint2[numplayers-1] = -1;
                   3298: 
                   3299:                                deletesprite(playersprite[numplayers]);
                   3300:                                playersprite[numplayers] = -1;
                   3301: 
                   3302:                                if (myconnectindex >= numplayers) myconnectindex = 0;
                   3303:                                if (screenpeek >= numplayers) screenpeek = 0;
                   3304: 
                   3305:                                if (numplayers < 2)
                   3306:                                        setup3dscreen();
                   3307:                                else
                   3308:                                        clearallviews(0L);  //Clear screen to specified color
                   3309:                        }
                   3310:                }
                   3311:                if (keystatus[0x46] > 0)   //Scroll Lock
                   3312:                {
                   3313:                        keystatus[0x46] = 0;
                   3314: 
                   3315:                        myconnectindex = connectpoint2[myconnectindex];
                   3316:                        if (myconnectindex < 0) myconnectindex = connecthead;
                   3317:                        screenpeek = myconnectindex;
                   3318:                }
                   3319:        }
                   3320: 
                   3321:        restoreinterpolations();
                   3322: }
                   3323: 
                   3324: movethings()
                   3325: {
                   3326:        long i;
                   3327: 
                   3328:        gotlastpacketclock = totalclock;
                   3329:        for(i=connecthead;i>=0;i=connectpoint2[i])
                   3330:        {
                   3331:                baksync[movefifoend][i].fvel = fsync[i].fvel;
                   3332:                baksync[movefifoend][i].svel = fsync[i].svel;
                   3333:                baksync[movefifoend][i].avel = fsync[i].avel;
                   3334:                baksync[movefifoend][i].bits = fsync[i].bits;
                   3335:        }
                   3336:        movefifoend = ((movefifoend+1)&(MOVEFIFOSIZ-1));
                   3337: }
                   3338: 
                   3339: domovethings()
                   3340: {
                   3341:        short i, j, startwall, endwall;
                   3342:        spritetype *spr;
                   3343:        walltype *wal;
                   3344:        point3d *ospr;
                   3345: 
                   3346:        nummoves++;
                   3347: 
                   3348:        for(i=connecthead;i>=0;i=connectpoint2[i])
                   3349:        {
                   3350:                sync[i].fvel = baksync[movefifoplc][i].fvel;
                   3351:                sync[i].svel = baksync[movefifoplc][i].svel;
                   3352:                sync[i].avel = baksync[movefifoplc][i].avel;
                   3353:                sync[i].bits = baksync[movefifoplc][i].bits;
                   3354:        }
                   3355:        movefifoplc = ((movefifoplc+1)&(MOVEFIFOSIZ-1));
                   3356: 
                   3357:        if (option[4] != 0)
                   3358:        {
                   3359:                syncval[syncvalhead] = getsyncstat();
                   3360:                syncvalhead = ((syncvalhead+1)&(MOVEFIFOSIZ-1));
                   3361:        }
                   3362: 
                   3363:        for(i=connecthead;i>=0;i=connectpoint2[i])
                   3364:        {
                   3365:                oposx[i] = posx[i];
                   3366:                oposy[i] = posy[i];
                   3367:                oposz[i] = posz[i];
                   3368:                ohoriz[i] = horiz[i];
                   3369:                ozoom[i] = zoom[i];
                   3370:                oang[i] = ang[i];
                   3371:        }
                   3372: 
                   3373:        for(i=NUMSTATS-1;i>=0;i--)
                   3374:                if (statrate[i] >= 0)
                   3375:                        for(j=headspritestat[i];j>=0;j=nextspritestat[j])
                   3376:                                if (((nummoves-j)&statrate[i]) == 0)
                   3377:                                        copybuf(&sprite[j].x,&osprite[j].x,3);
                   3378: 
                   3379:        for(i=connecthead;i>=0;i=connectpoint2[i])
                   3380:                ocursectnum[i] = cursectnum[i];
                   3381: 
                   3382:        updateinterpolations();
                   3383: 
                   3384:        if ((numplayers <= 2) && (recstat == 1))
                   3385:        {
                   3386:                j = 0;
                   3387:                for(i=connecthead;i>=0;i=connectpoint2[i])
                   3388:                {
                   3389:                        recsync[reccnt][j].fvel = sync[i].fvel;
                   3390:                        recsync[reccnt][j].svel = sync[i].svel;
                   3391:                        recsync[reccnt][j].avel = sync[i].avel;
                   3392:                        recsync[reccnt][j].bits = sync[i].bits;
                   3393:                        j++;
                   3394:                }
                   3395:                reccnt++; if (reccnt > 16383) reccnt = 16383;
                   3396:        }
                   3397: 
                   3398:        lockclock += TICSPERFRAME;
                   3399: 
                   3400:        for(i=connecthead;i>=0;i=connectpoint2[i])
                   3401:        {
                   3402:                processinput(i);                        //Move player
                   3403: 
                   3404:                checktouchsprite(i,cursectnum[i]);      //Pick up coins
                   3405:                startwall = sector[cursectnum[i]].wallptr;
                   3406:                endwall = startwall + sector[cursectnum[i]].wallnum;
                   3407:                for(j=startwall,wal=&wall[j];j<endwall;j++,wal++)
                   3408:                        if (wal->nextsector >= 0) checktouchsprite(i,wal->nextsector);
                   3409:        }
                   3410: 
                   3411:        doanimations();
                   3412:        tagcode();            //Door code, moving sector code, other stuff
                   3413:        statuslistcode();     //Monster / bullet code / explosions
                   3414: 
                   3415:        checkmasterslaveswitch();
                   3416: }
                   3417: 
                   3418: getinput()
                   3419: {
                   3420:        char ch, keystate, *ptr;
                   3421:        long i, j, k;
                   3422:        short mousx, mousy, bstatus;
                   3423: 
                   3424:        if (typemode == 0)           //if normal game keys active
                   3425:        {
                   3426:                if ((keystatus[0x2a]&keystatus[0x36]&keystatus[0x13]) > 0)   //Sh.Sh.R (replay)
                   3427:                {
                   3428:                        keystatus[0x13] = 0;
                   3429:                        playback();
                   3430:                }
                   3431: 
                   3432:                if ((keystatus[0x26]&(keystatus[0x1d]|keystatus[0x9d])) > 0) //Load game
                   3433:                {
                   3434:                        keystatus[0x26] = 0;
                   3435:                        loadgame();
                   3436:                }
                   3437: 
                   3438:                if ((keystatus[0x1f]&(keystatus[0x1d]|keystatus[0x9d])) > 0) //Save game
                   3439:                {
                   3440:                        keystatus[0x1f] = 0;
                   3441:                        savegame();
                   3442:                }
                   3443: 
                   3444:                if (keystatus[keys[15]] > 0)
                   3445:                {
                   3446:                        keystatus[keys[15]] = 0;
                   3447: 
                   3448:                        screenpeek = connectpoint2[screenpeek];
                   3449:                        if (screenpeek < 0) screenpeek = connecthead;
                   3450:                }
                   3451: 
                   3452:                for(i=7;i>=0;i--)
                   3453:                        if (keystatus[i+2] > 0)
                   3454:                                { keystatus[i+2] = 0; locselectedgun = i; break; }
                   3455:        }
                   3456: 
                   3457: 
                   3458:                //KEYTIMERSTUFF
                   3459:        if (keystatus[keys[5]] == 0)
                   3460:        {
                   3461:                if (keystatus[keys[2]] > 0) avel = max(avel-16*TICSPERFRAME,-128);
                   3462:                if (keystatus[keys[3]] > 0) avel = min(avel+16*TICSPERFRAME,127);
                   3463:        }
                   3464:        else
                   3465:        {
                   3466:                if (keystatus[keys[2]] > 0) svel = min(svel+8*TICSPERFRAME,127);
                   3467:                if (keystatus[keys[3]] > 0) svel = max(svel-8*TICSPERFRAME,-128);
                   3468:        }
                   3469:        if (keystatus[keys[0]] > 0) fvel = min(fvel+8*TICSPERFRAME,127);
                   3470:        if (keystatus[keys[1]] > 0) fvel = max(fvel-8*TICSPERFRAME,-128);
                   3471:        if (keystatus[keys[12]] > 0) svel = min(svel+8*TICSPERFRAME,127);
                   3472:        if (keystatus[keys[13]] > 0) svel = max(svel-8*TICSPERFRAME,-128);
                   3473: 
                   3474:        if (avel < 0) avel = min(avel+12*TICSPERFRAME,0);
                   3475:        if (avel > 0) avel = max(avel-12*TICSPERFRAME,0);
                   3476:        if (svel < 0) svel = min(svel+2*TICSPERFRAME,0);
                   3477:        if (svel > 0) svel = max(svel-2*TICSPERFRAME,0);
                   3478:        if (fvel < 0) fvel = min(fvel+2*TICSPERFRAME,0);
                   3479:        if (fvel > 0) fvel = max(fvel-2*TICSPERFRAME,0);
                   3480: 
                   3481:        if ((option[4] == 0) && (numplayers == 2))
                   3482:        {
                   3483:                if (keystatus[0x4f] == 0)
                   3484:                {
                   3485:                        if (keystatus[0x4b] > 0) avel2 = max(avel2-16*TICSPERFRAME,-128);
                   3486:                        if (keystatus[0x4d] > 0) avel2 = min(avel2+16*TICSPERFRAME,127);
                   3487:                }
                   3488:                else
                   3489:                {
                   3490:                        if (keystatus[0x4b] > 0) svel2 = min(svel2+8*TICSPERFRAME,127);
                   3491:                        if (keystatus[0x4d] > 0) svel2 = max(svel2-8*TICSPERFRAME,-128);
                   3492:                }
                   3493:                if (keystatus[0x48] > 0) fvel2 = min(fvel2+8*TICSPERFRAME,127);
                   3494:                if (keystatus[0x4c] > 0) fvel2 = max(fvel2-8*TICSPERFRAME,-128);
                   3495: 
                   3496:                if (avel2 < 0) avel2 = min(avel2+12*TICSPERFRAME,0);
                   3497:                if (avel2 > 0) avel2 = max(avel2-12*TICSPERFRAME,0);
                   3498:                if (svel2 < 0) svel2 = min(svel2+2*TICSPERFRAME,0);
                   3499:                if (svel2 > 0) svel2 = max(svel2-2*TICSPERFRAME,0);
                   3500:                if (fvel2 < 0) fvel2 = min(fvel2+2*TICSPERFRAME,0);
                   3501:                if (fvel2 > 0) fvel2 = max(fvel2-2*TICSPERFRAME,0);
                   3502:        }
                   3503: 
                   3504:        if (keystatus[0x1a] != 0) screentilt += ((4*TICSPERFRAME)<<(keystatus[0x2a]|keystatus[0x36]));
                   3505:        if (keystatus[0x1b] != 0) screentilt -= ((4*TICSPERFRAME)<<(keystatus[0x2a]|keystatus[0x36]));
                   3506: 
                   3507:        i = (TICSPERFRAME<<1);
                   3508:        while ((screentilt != 0) && (i > 0))
                   3509:                { screentilt = ((screentilt+ksgn(screentilt-1024))&2047); i--; }
                   3510:        if (keystatus[0x28] != 0) screentilt = 1536;
                   3511: 
                   3512: 
                   3513:        loc.fvel = min(max(fvel,-128+8),127-8);
                   3514:        loc.svel = min(max(svel,-128+8),127-8);
                   3515:        loc.avel = min(max(avel,-128+16),127-16);
                   3516: 
                   3517:        getmousevalues(&mousx,&mousy,&bstatus);
                   3518:        loc.avel = min(max(loc.avel+(mousx<<3),-128),127);
                   3519:        loc.fvel = min(max(loc.fvel-(mousy<<3),-128),127);
                   3520: 
                   3521:        loc.bits = (locselectedgun<<13);
                   3522:        if (typemode == 0)           //if normal game keys active
                   3523:        {
                   3524:                loc.bits |= (keystatus[0x32]<<9);                 //M (be master)
                   3525:                loc.bits |= ((keystatus[keys[14]]==1)<<12);       //Map mode
                   3526:        }
                   3527:        loc.bits |= keystatus[keys[8]];                   //Stand high
                   3528:        loc.bits |= (keystatus[keys[9]]<<1);              //Stand low
                   3529:        loc.bits |= (keystatus[keys[16]]<<4);             //Zoom in
                   3530:        loc.bits |= (keystatus[keys[17]]<<5);             //Zoom out
                   3531:        loc.bits |= (keystatus[keys[4]]<<8);                 //Run
                   3532:        loc.bits |= (keystatus[keys[10]]<<2);                //Look up
                   3533:        loc.bits |= (keystatus[keys[11]]<<3);                //Look down
                   3534:        loc.bits |= ((keystatus[keys[7]]==1)<<10);           //Space
                   3535:        loc.bits |= ((keystatus[keys[6]]==1)<<11);           //Shoot
                   3536:        loc.bits |= (((bstatus&6)>(oldmousebstatus&6))<<10); //Space
                   3537:        loc.bits |= (((bstatus&1)>(oldmousebstatus&1))<<11); //Shoot
                   3538: 
                   3539:        oldmousebstatus = bstatus;
                   3540:        if (((loc.bits&2048) > 0) && (locselectedgun == 1))
                   3541:                oldmousebstatus &= ~1;     //Allow continous fire with mouse for chain gun
                   3542: 
                   3543:                //PRIVATE KEYS:
                   3544:        if (keystatus[0xb7] > 0)  //Printscreen
                   3545:        {
                   3546:                keystatus[0xb7] = 0;
                   3547:                printscreeninterrupt();
                   3548:        }
                   3549:        if (keystatus[0x57] > 0)  //F11 - brightness
                   3550:        {
                   3551:                keystatus[0x57] = 0;
                   3552:                brightness++;
                   3553:                if (brightness > 8) brightness = 0;
                   3554:                setbrightness(brightness,(char *)&palette[0]);
                   3555:        }
                   3556: 
                   3557:        if (typemode == 0)           //if normal game keys active
                   3558:        {
                   3559:                if (keystatus[0x19] > 0)  //P
                   3560:                {
                   3561:                        keystatus[0x19] = 0;
                   3562:                        parallaxtype++;
                   3563:                        if (parallaxtype > 2) parallaxtype = 0;
                   3564:                }
                   3565:                if ((keystatus[0x38]|keystatus[0xb8]) > 0)  //ALT
                   3566:                {
                   3567:                        if (keystatus[0x4a] > 0)  // Keypad -
                   3568:                                visibility = min(visibility+(visibility>>3),16384);
                   3569:                        if (keystatus[0x4e] > 0)  // Keypad +
                   3570:                                visibility = max(visibility-(visibility>>3),128);
                   3571:                }
                   3572: 
                   3573:                /*if ((option[1] == 1) && (option[4] >= 5))
                   3574:                {
                   3575:                        if ((keystatus[0x13] > 0) && (recsnddone == 1) && (recording == -2))      //R (record)
                   3576:                        {
                   3577:                                wrec(32768L);
                   3578:                                recording = -1;
                   3579:                        }
                   3580:                        if ((recording == -1) && ((keystatus[0x13] == 0) || (recsnddone == 1)))
                   3581:                        {
                   3582:                                continueplay();
                   3583:                                recsnddone = 1;
                   3584:                                recording = 0;
                   3585:                                wsay("recordedvoice",2972L,255L,255L);
                   3586:                        }
                   3587:                        if ((recording >= 0) && (screenpeek != myconnectindex))
                   3588:                        {
                   3589:                                packbuf[0] = 3;
                   3590: 
                   3591:                                ptr = (char *)(recsndoffs+recording);
                   3592:                                for(i=0;i<256;i++)
                   3593:                                        packbuf[i+1] = *ptr++;
                   3594:                                recording += 256;
                   3595: 
                   3596:                                sendpacket(screenpeek,packbuf,257L);
                   3597:                                if (recording >= 32768)
                   3598:                                        recording = -2;
                   3599:                        }
                   3600:                }*/
                   3601: 
                   3602:                if ((keystatus[keys[18]]) > 0)   //Typing mode
                   3603:                {
                   3604:                        keystatus[keys[18]] = 0;
                   3605:                        typemode = 1;
                   3606:                        keyfifoplc = keyfifoend;      //Reset keyboard fifo
                   3607:                }
                   3608:        }
                   3609:        else
                   3610:        {
                   3611:                while (keyfifoplc != keyfifoend)
                   3612:                {
                   3613:                        ch = keyfifo[keyfifoplc];
                   3614:                        keystate = keyfifo[(keyfifoplc+1)&(KEYFIFOSIZ-1)];
                   3615:                        keyfifoplc = ((keyfifoplc+2)&(KEYFIFOSIZ-1));
                   3616: 
                   3617:                        if (keystate != 0)
                   3618:                        {
                   3619:                                if (ch == 0xe)   //Backspace
                   3620:                                {
                   3621:                                        if (typemessageleng == 0) { typemode = 0; break; }
                   3622:                                        typemessageleng--;
                   3623:                                }
                   3624:                                if (ch == 0xf)
                   3625:                                {
                   3626:                                        keystatus[0xf] = 0;
                   3627:                                        typemode = 0;
                   3628:                                        break;
                   3629:                                }
                   3630:                                if ((ch == 0x1c) || (ch == 0x9c))  //Either ENTER
                   3631:                                {
                   3632:                                        keystatus[0x1c] = 0; keystatus[0x9c] = 0;
                   3633:                                        if (typemessageleng > 0)
                   3634:                                        {
                   3635:                                                packbuf[0] = 2;          //Sending text is message type 4
                   3636:                                                for(j=typemessageleng-1;j>=0;j--)
                   3637:                                                        packbuf[j+1] = typemessage[j];
                   3638: 
                   3639:                                                for(i=connecthead;i>=0;i=connectpoint2[i])
                   3640:                                                        if (i != myconnectindex)
                   3641:                                                                sendpacket(i,packbuf,typemessageleng+1);
                   3642: 
                   3643:                                                typemessageleng = 0;
                   3644:                                        }
                   3645:                                        typemode = 0;
                   3646:                                        break;
                   3647:                                }
                   3648: 
                   3649:                                if ((typemessageleng < 159) && (ch < 128))
                   3650:                                {
                   3651:                                        if ((keystatus[0x2a]|keystatus[0x36]) != 0)
                   3652:                                                ch = scantoascwithshift[ch];
                   3653:                                        else
                   3654:                                                ch = scantoasc[ch];
                   3655: 
                   3656:                                        if (ch != 0) typemessage[typemessageleng++] = ch;
                   3657:                                }
                   3658:                        }
                   3659:                }
                   3660:                        //Here's a trick of making key repeat after a 1/2 second
                   3661:                if (keystatus[0xe] > 0)
                   3662:                {
                   3663:                        if (keystatus[0xe] < 30)
                   3664:                                keystatus[0xe] += TICSPERFRAME;
                   3665:                        else
                   3666:                        {
                   3667:                                if (typemessageleng == 0)
                   3668:                                        typemode = 0;
                   3669:                                else
                   3670:                                        typemessageleng--;
                   3671:                        }
                   3672:                }
                   3673:        }
                   3674: }
                   3675: 
                   3676: initplayersprite(short snum)
                   3677: {
                   3678:        long i;
                   3679: 
                   3680:        if (playersprite[snum] >= 0) return;
                   3681: 
                   3682:        spawnsprite(playersprite[snum],posx[snum],posy[snum],posz[snum]+(32<<8),
                   3683:                1+256,0,snum,32,64,64,0,0,DOOMGUY,ang[snum],0,0,0,snum+4096,
                   3684:                cursectnum[snum],8,0,0,0);
                   3685: 
                   3686:        switch(snum)
                   3687:        {
                   3688:                case 1: for(i=0;i<32;i++) tempbuf[i+192] = i+128; break; //green->red
                   3689:                case 2: for(i=0;i<32;i++) tempbuf[i+192] = i+32; break;  //green->blue
                   3690:                case 3: for(i=0;i<32;i++) tempbuf[i+192] = i+224; break; //green->pink
                   3691:                case 4: for(i=0;i<32;i++) tempbuf[i+192] = i+64; break;  //green->brown
                   3692:                case 5: for(i=0;i<32;i++) tempbuf[i+192] = i+96; break;
                   3693:                case 6: for(i=0;i<32;i++) tempbuf[i+192] = i+160; break;
                   3694:                case 7: for(i=0;i<32;i++) tempbuf[i+192] = i+192; break;
                   3695:                default: for(i=0;i<256;i++) tempbuf[i] = i; break;
                   3696:        }
                   3697:        makepalookup(snum,tempbuf,0,0,0,1);
                   3698: }
                   3699: 
                   3700: playback()
                   3701: {
                   3702:        long i, j, k;
                   3703: 
                   3704:        ready2send = 0;
                   3705:        recstat = 0; i = reccnt;
                   3706:        while (keystatus[1] == 0)
                   3707:        {
                   3708:                while (totalclock >= lockclock+TICSPERFRAME)
                   3709:                {
                   3710:                        if (i >= reccnt)
                   3711:                        {
                   3712:                                prepareboard(boardfilename);
                   3713:                                for(i=connecthead;i>=0;i=connectpoint2[i])
                   3714:                                        initplayersprite((short)i);
                   3715:                                resettiming(); ototalclock = 0; gotlastpacketclock = 0;
                   3716:                                i = 0;
                   3717:                        }
                   3718: 
                   3719:                        k = 0;
                   3720:                        for(j=connecthead;j>=0;j=connectpoint2[j])
                   3721:                        {
                   3722:                                fsync[j].fvel = recsync[i][k].fvel;
                   3723:                                fsync[j].svel = recsync[i][k].svel;
                   3724:                                fsync[j].avel = recsync[i][k].avel;
                   3725:                                fsync[j].bits = recsync[i][k].bits;
                   3726:                                k++;
                   3727:                        }
                   3728:                        movethings(); domovethings();
                   3729:                        i++;
                   3730:                }
                   3731:                drawscreen(screenpeek,(totalclock-lockclock)*(65536/TICSPERFRAME));
                   3732: 
                   3733:                if (keystatus[keys[15]] > 0)
                   3734:                {
                   3735:                        keystatus[keys[15]] = 0;
                   3736: 
                   3737:                        screenpeek = connectpoint2[screenpeek];
                   3738:                        if (screenpeek < 0) screenpeek = connecthead;
                   3739:                }
                   3740:                if (keystatus[keys[14]] > 0)
                   3741:                {
                   3742:                        keystatus[keys[14]] = 0;
                   3743:                        dimensionmode[screenpeek]++;
                   3744:                        if (dimensionmode[screenpeek] > 3) dimensionmode[screenpeek] = 1;
                   3745:                }
                   3746:        }
                   3747: 
                   3748:        musicoff();
                   3749:        uninitmultiplayers();
                   3750:        uninittimer();
                   3751:        uninitkeys();
                   3752:        uninitengine();
                   3753:        uninitsb();
                   3754:        uninitgroupfile();
                   3755:        setvmode(0x3);        //Set back to text mode
                   3756:        exit(0);
                   3757: }
                   3758: 
                   3759: setup3dscreen()
                   3760: {
                   3761:        long i, dax, day, dax2, day2;
                   3762: 
                   3763:        setgamemode();
                   3764: 
                   3765:          //Make that ugly pink into black in case it ever shows up!
                   3766:        outp(0x3c8,255); outp(0x3c9,0); outp(0x3c9,0); outp(0x3c9,0);
                   3767: 
                   3768:        if (screensize > xdim)
                   3769:        {
                   3770:                dax = 0; day = 0;
                   3771:                dax2 = xdim-1; day2 = ydim-1;
                   3772:        }
                   3773:        else
                   3774:        {
                   3775:                dax = ((xdim-screensize)>>1);
                   3776:                dax2 = dax+screensize-1;
                   3777:                day = (((ydim-32)-scale(screensize,ydim-32,xdim))>>1);
                   3778:                day2 = day + scale(screensize,ydim-32,xdim)-1;
                   3779:                setview(dax,day,dax2,day2);
                   3780:        }
                   3781: 
                   3782:        if (screensize < xdim)
                   3783:                drawtilebackground(0L,0L,BACKGROUND,8,0L,0L,xdim-1L,ydim-1L,0);      //Draw background
                   3784: 
                   3785:        if (screensize <= xdim)
                   3786:        {
                   3787:                rotatesprite((xdim-320)<<15,(ydim-32)<<16,65536L,0,STATUSBAR,0,0,8+16+64+128,0L,0L,xdim-1L,ydim-1L);
                   3788:                i = ((xdim-320)>>1);
                   3789:                while (i >= 8) i -= 8, rotatesprite(i<<16,(ydim-32)<<16,65536L,0,STATUSBARFILL8,0,0,8+16+64+128,0L,0L,xdim-1L,ydim-1L);
                   3790:                if (i >= 4) i -= 4, rotatesprite(i<<16,(ydim-32)<<16,65536L,0,STATUSBARFILL4,0,0,8+16+64+128,0L,0L,xdim-1L,ydim-1L);
                   3791:                i = ((xdim-320)>>1)+320;
                   3792:                while (i <= xdim-8) rotatesprite(i<<16,(ydim-32)<<16,65536L,0,STATUSBARFILL8,0,0,8+16+64+128,0L,0L,xdim-1L,ydim-1L), i += 8;
                   3793:                if (i <= xdim-4) rotatesprite(i<<16,(ydim-32)<<16,65536L,0,STATUSBARFILL4,0,0,8+16+64+128,0L,0L,xdim-1L,ydim-1L), i += 4;
                   3794: 
                   3795:                sprintf(&tempbuf,"Deaths: %d",deaths[screenpeek]);
                   3796:                printext((xdim>>1)-(strlen(tempbuf)<<2),ydim-16,tempbuf,ALPHABET,80);
                   3797: 
                   3798:                sprintf(&tempbuf,"Health: %3d",health[screenpeek]);
                   3799:                printext((xdim>>1)-(strlen(tempbuf)<<2),ydim-24,tempbuf,ALPHABET,80);
                   3800:        }
                   3801: }
                   3802: 
                   3803: findrandomspot(long *x, long *y, short *sectnum)
                   3804: {
                   3805:        short startwall, endwall, s, dasector;
                   3806:        long dax, day, daz, minx, maxx, miny, maxy, cnt;
                   3807: 
                   3808:        for(cnt=256;cnt>=0;cnt--)
                   3809:        {
                   3810:                do
                   3811:                {
                   3812:                        dasector = mulscale16(krand(),numsectors);
                   3813:                } while ((sector[dasector].ceilingz+(8<<8) >= sector[dasector].floorz) || ((sector[dasector].lotag|sector[dasector].hitag) != 0) || ((sector[dasector].floorstat&1) != 0));
                   3814: 
                   3815:                startwall = sector[dasector].wallptr;
                   3816:                endwall = startwall+sector[dasector].wallnum;
                   3817:                if (endwall <= startwall) continue;
                   3818: 
                   3819:                dax = 0L;
                   3820:                day = 0L;
                   3821:                minx = 0x7fffffff; maxx = 0x80000000;
                   3822:                miny = 0x7fffffff; maxy = 0x80000000;
                   3823: 
                   3824:                for(s=startwall;s<endwall;s++)
                   3825:                {
                   3826:                        dax += wall[s].x;
                   3827:                        day += wall[s].y;
                   3828:                        if (wall[s].x < minx) minx = wall[s].x;
                   3829:                        if (wall[s].x > maxx) maxx = wall[s].x;
                   3830:                        if (wall[s].y < miny) miny = wall[s].y;
                   3831:                        if (wall[s].y > maxy) maxy = wall[s].y;
                   3832:                }
                   3833: 
                   3834:                if ((maxx-minx <= 256) || (maxy-miny <= 256)) continue;
                   3835: 
                   3836:                dax /= (endwall-startwall);
                   3837:                day /= (endwall-startwall);
                   3838: 
                   3839:                if (inside(dax,day,dasector) == 0) continue;
                   3840: 
                   3841:                daz = sector[dasector].floorz-(32<<8);
                   3842:                if (pushmove(&dax,&day,&daz,&dasector,128L,4<<8,4<<8,0) < 0) continue;
                   3843: 
                   3844:                *x = dax; *y = day; *sectnum = dasector;
                   3845:                return;
                   3846:        }
                   3847: }
                   3848: 
                   3849: warp(long *x, long *y, long *z, short *daang, short *dasector)
                   3850: {
                   3851:        short startwall, endwall, s;
                   3852:        long i, j, dax, day, ox, oy;
                   3853: 
                   3854:        ox = *x; oy = *y;
                   3855: 
                   3856:        for(i=0;i<warpsectorcnt;i++)
                   3857:                if (warpsectorlist[i] == *dasector)
                   3858:                {
                   3859:                        j = sector[*dasector].hitag;
                   3860:                        do
                   3861:                        {
                   3862:                                i++;
                   3863:                                if (i >= warpsectorcnt) i = 0;
                   3864:                        } while (sector[warpsectorlist[i]].hitag != j);
                   3865:                        *dasector = warpsectorlist[i];
                   3866:                        break;
                   3867:                }
                   3868: 
                   3869:                //Find center of sector
                   3870:        startwall = sector[*dasector].wallptr;
                   3871:        endwall = startwall+sector[*dasector].wallnum;
                   3872:        dax = 0L, day = 0L;
                   3873:        for(s=startwall;s<endwall;s++)
                   3874:        {
                   3875:                dax += wall[s].x, day += wall[s].y;
                   3876:                if (wall[s].nextsector >= 0)
                   3877:                        i = s;
                   3878:        }
                   3879:        *x = dax / (endwall-startwall);
                   3880:        *y = day / (endwall-startwall);
                   3881:        *z = sector[*dasector].floorz-(32<<8);
                   3882:        updatesector(*x,*y,dasector);
                   3883:        dax = ((wall[i].x+wall[wall[i].point2].x)>>1);
                   3884:        day = ((wall[i].y+wall[wall[i].point2].y)>>1);
                   3885:        *daang = getangle(dax-*x,day-*y);
                   3886: 
                   3887:        wsayfollow("warp.wav",3072L+(krand()&127)-64,192L,&ox,&oy,0);
                   3888:        wsayfollow("warp.wav",4096L+(krand()&127)-64,256L,x,y,0);
                   3889: }
                   3890: 
                   3891: warpsprite(short spritenum)
                   3892: {
                   3893:        short dasectnum;
                   3894: 
                   3895:        dasectnum = sprite[spritenum].sectnum;
                   3896:        warp(&sprite[spritenum].x,&sprite[spritenum].y,&sprite[spritenum].z,
                   3897:                  &sprite[spritenum].ang,&dasectnum);
                   3898: 
                   3899:        copybuf(&sprite[spritenum].x,&osprite[spritenum].x,3);
                   3900:        changespritesect(spritenum,dasectnum);
                   3901: 
                   3902:        show2dsprite[spritenum>>3] &= ~(1<<(spritenum&7));
                   3903:        if (show2dsector[dasectnum>>3]&(1<<(dasectnum&7)))
                   3904:                show2dsprite[spritenum>>3] |= (1<<(spritenum&7));
                   3905: }
                   3906: 
                   3907: initlava()
                   3908: {
                   3909:        long x, y, z, r;
                   3910: 
                   3911:        for(x=-16;x<=16;x++)
                   3912:                for(y=-16;y<=16;y++)
                   3913:                {
                   3914:                        r = ksqrt(x*x + y*y);
                   3915:                        lavaradx[r][lavaradcnt[r]] = x;
                   3916:                        lavarady[r][lavaradcnt[r]] = y;
                   3917:                        lavaradcnt[r]++;
                   3918:                }
                   3919: 
                   3920:        for(z=0;z<16;z++)
                   3921:                lavadropsizlookup[z] = 8 / (ksqrt(z)+1);
                   3922: 
                   3923:        for(z=0;z<LAVASIZ;z++)
                   3924:                lavainc[z] = klabs((((z^17)>>4)&7)-4)+12;
                   3925: 
                   3926:        lavanumdrops = 0;
                   3927:        lavanumframes = 0;
                   3928: }
                   3929: 
                   3930: #pragma aux addlava =\
                   3931:        "mov al, byte ptr [ebx-133]",\
                   3932:        "mov dl, byte ptr [ebx-1]",\
                   3933:        "add al, byte ptr [ebx-132]",\
                   3934:        "add dl, byte ptr [ebx+131]",\
                   3935:        "add al, byte ptr [ebx-131]",\
                   3936:        "add dl, byte ptr [ebx+132]",\
                   3937:        "add al, byte ptr [ebx+1]",\
                   3938:        "add al, dl",\
                   3939:        parm [ebx]\
                   3940:        modify exact [eax edx]\
                   3941: 
                   3942: movelava(char *dapic)
                   3943: {
                   3944:        long i, j, x, y, z, zz, dalavadropsiz, dadropsizlookup;
                   3945:        long dalavax, dalavay, *ptr, *ptr2;
                   3946: 
                   3947:        for(z=min(LAVAMAXDROPS-lavanumdrops-1,3);z>=0;z--)
                   3948:        {
                   3949:                lavadropx[lavanumdrops] = (rand()&(LAVASIZ-1));
                   3950:                lavadropy[lavanumdrops] = (rand()&(LAVASIZ-1));
                   3951:                lavadropsiz[lavanumdrops] = 1;
                   3952:                lavanumdrops++;
                   3953:        }
                   3954: 
                   3955:        for(z=lavanumdrops-1;z>=0;z--)
                   3956:        {
                   3957:                dadropsizlookup = lavadropsizlookup[lavadropsiz[z]]*(((z&1)<<1)-1);
                   3958:                dalavadropsiz = lavadropsiz[z];
                   3959:                dalavax = lavadropx[z]; dalavay = lavadropy[z];
                   3960:                for(zz=lavaradcnt[lavadropsiz[z]]-1;zz>=0;zz--)
                   3961:                {
                   3962:                        i = (((lavaradx[dalavadropsiz][zz]+dalavax)&(LAVASIZ-1))<<LAVALOGSIZ);
                   3963:                        i += ((lavarady[dalavadropsiz][zz]+dalavay)&(LAVASIZ-1));
                   3964:                        dapic[i] += dadropsizlookup;
                   3965:                        if (dapic[i] < 192) dapic[i] = 192;
                   3966:                }
                   3967: 
                   3968:                lavadropsiz[z]++;
                   3969:                if (lavadropsiz[z] > 10)
                   3970:                {
                   3971:                        lavanumdrops--;
                   3972:                        lavadropx[z] = lavadropx[lavanumdrops];
                   3973:                        lavadropy[z] = lavadropy[lavanumdrops];
                   3974:                        lavadropsiz[z] = lavadropsiz[lavanumdrops];
                   3975:                }
                   3976:        }
                   3977: 
                   3978:                //Back up dapic with 1 pixel extra on each boundary
                   3979:                //(to prevent anding for wrap-around)
                   3980:        ptr = (long *)dapic;
                   3981:        ptr2 = (long *)((LAVASIZ+4)+1+((long)lavabakpic));
                   3982:        for(x=0;x<LAVASIZ;x++)
                   3983:        {
                   3984:                for(y=(LAVASIZ>>2);y>0;y--) *ptr2++ = ((*ptr++)&0x1f1f1f1f);
                   3985:                ptr2++;
                   3986:        }
                   3987:        for(y=0;y<LAVASIZ;y++)
                   3988:        {
                   3989:                lavabakpic[y+1] = (dapic[y+((LAVASIZ-1)<<LAVALOGSIZ)]&31);
                   3990:                lavabakpic[y+1+(LAVASIZ+1)*(LAVASIZ+4)] = (dapic[y]&31);
                   3991:        }
                   3992:        for(x=0;x<LAVASIZ;x++)
                   3993:        {
                   3994:                lavabakpic[(x+1)*(LAVASIZ+4)] = (dapic[(x<<LAVALOGSIZ)+(LAVASIZ-1)]&31);
                   3995:                lavabakpic[(x+1)*(LAVASIZ+4)+(LAVASIZ+1)] = (dapic[x<<LAVALOGSIZ]&31);
                   3996:        }
                   3997:        lavabakpic[0] = (dapic[LAVASIZ*LAVASIZ-1]&31);
                   3998:        lavabakpic[LAVASIZ+1] = (dapic[LAVASIZ*(LAVASIZ-1)]&31);
                   3999:        lavabakpic[(LAVASIZ+4)*(LAVASIZ+1)] = (dapic[LAVASIZ-1]&31);
                   4000:        lavabakpic[(LAVASIZ+4)*(LAVASIZ+2)-1] = (dapic[0]&31);
                   4001: 
                   4002:        ptr = (long *)dapic;
                   4003:        for(x=0;x<LAVASIZ;x++)
                   4004:        {
                   4005:                i = (long)&lavabakpic[(x+1)*(LAVASIZ+4)+1];
                   4006:                j = i+LAVASIZ;
                   4007:                for(y=i;y<j;y+=4)
                   4008:                {
                   4009:                        *ptr++ = ((addlava(y+0)&0xf8)>>3)+
                   4010:                                                ((addlava(y+1)&0xf8)<<5)+
                   4011:                                                ((addlava(y+2)&0xf8)<<13)+
                   4012:                                                ((addlava(y+3)&0xf8)<<21)+
                   4013:                                                0xc2c2c2c2;
                   4014:                }
                   4015:        }
                   4016: 
                   4017:        lavanumframes++;
                   4018: }
                   4019: 
                   4020: doanimations()
                   4021: {
                   4022:        long i, j;
                   4023: 
                   4024:        for(i=animatecnt-1;i>=0;i--)
                   4025:        {
                   4026:                j = *animateptr[i];
                   4027: 
                   4028:                if (j < animategoal[i])
                   4029:                        j = min(j+animatevel[i]*TICSPERFRAME,animategoal[i]);
                   4030:                else
                   4031:                        j = max(j-animatevel[i]*TICSPERFRAME,animategoal[i]);
                   4032:                animatevel[i] += animateacc[i];
                   4033: 
                   4034:                *animateptr[i] = j;
                   4035: 
                   4036:                if (j == animategoal[i])
                   4037:                {
                   4038:                        animatecnt--;
                   4039:                        if (i != animatecnt)
                   4040:                        {
                   4041:                                stopinterpolation(animateptr[i]);
                   4042:                                animateptr[i] = animateptr[animatecnt];
                   4043:                                animategoal[i] = animategoal[animatecnt];
                   4044:                                animatevel[i] = animatevel[animatecnt];
                   4045:                                animateacc[i] = animateacc[animatecnt];
                   4046:                        }
                   4047:                }
                   4048:        }
                   4049: }
                   4050: 
                   4051: getanimationgoal(long animptr)
                   4052: {
                   4053:        long i;
                   4054: 
                   4055:        for(i=animatecnt-1;i>=0;i--)
                   4056:                if (animptr == animateptr[i]) return(i);
                   4057:        return(-1);
                   4058: }
                   4059: 
                   4060: setanimation(long *animptr, long thegoal, long thevel, long theacc)
                   4061: {
                   4062:        long i, j;
                   4063: 
                   4064:        if (animatecnt >= MAXANIMATES) return(-1);
                   4065: 
                   4066:        j = animatecnt;
                   4067:        for(i=animatecnt-1;i>=0;i--)
                   4068:                if (animptr == animateptr[i])
                   4069:                        { j = i; break; }
                   4070: 
                   4071:        setinterpolation(animptr);
                   4072: 
                   4073:        animateptr[j] = animptr;
                   4074:        animategoal[j] = thegoal;
                   4075:        animatevel[j] = thevel;
                   4076:        animateacc[j] = theacc;
                   4077:        if (j == animatecnt) animatecnt++;
                   4078:        return(j);
                   4079: }
                   4080: 
                   4081: checkmasterslaveswitch()
                   4082: {
                   4083:        long i, j;
                   4084: 
                   4085:        if (option[4] == 0) return;
                   4086: 
                   4087:        j = 0;
                   4088:        for(i=connecthead;i>=0;i=connectpoint2[i])
                   4089:                if (sync[i].bits&512) j++;
                   4090:        if (j != 1) return;
                   4091: 
                   4092:        i = connecthead;
                   4093:        for(j=connectpoint2[i];j>=0;j=connectpoint2[j])
                   4094:        {
                   4095:                if (sync[j].bits&512)
                   4096:                {
                   4097:                        connectpoint2[i] = connectpoint2[j];
                   4098:                        connectpoint2[j] = connecthead;
                   4099:                        connecthead = (short)j;
                   4100: 
                   4101:                        oloc.fvel = loc.fvel+1;
                   4102:                        oloc.svel = loc.svel+1;
                   4103:                        oloc.avel = loc.avel+1;
                   4104:                        oloc.bits = loc.bits+1;
                   4105:                        for(i=0;i<MAXPLAYERS;i++)
                   4106:                        {
                   4107:                                osync[i].fvel = fsync[i].fvel+1;
                   4108:                                osync[i].svel = fsync[i].svel+1;
                   4109:                                osync[i].avel = fsync[i].avel+1;
                   4110:                                osync[i].bits = fsync[i].bits+1;
                   4111:                        }
                   4112: 
                   4113:                        syncvalhead = othersyncvalhead = syncvaltail = 0L;
                   4114:                        totalclock = ototalclock = gotlastpacketclock = lockclock;
                   4115: 
                   4116:                        j = 1;
                   4117:                        for(i=connecthead;i>=0;i=connectpoint2[i])
                   4118:                        {
                   4119:                                if (myconnectindex == i) break;
                   4120:                                j++;
                   4121:                        }
                   4122:                        if (j == 1)
                   4123:                                strcpy(getmessage,"Player 1 (Master)");
                   4124:                        else
                   4125:                                sprintf(getmessage,"Player %ld (Slave)",j);
                   4126:                        getmessageleng = strlen(getmessage);
                   4127:                        getmessagetimeoff = totalclock+120;
                   4128: 
                   4129:                        return;
                   4130:                }
                   4131:                i = j;
                   4132:        }
                   4133: }
                   4134: 
                   4135: inittimer()
                   4136: {
                   4137:        outp(0x43,54); outp(0x40,9942&255); outp(0x40,9942>>8);  //120 times/sec
                   4138:        oldtimerhandler = _dos_getvect(0x8);
                   4139:        _disable(); _dos_setvect(0x8, timerhandler); _enable();
                   4140: }
                   4141: 
                   4142: uninittimer()
                   4143: {
                   4144:        outp(0x43,54); outp(0x40,255); outp(0x40,255);           //18.2 times/sec
                   4145:        _disable(); _dos_setvect(0x8, oldtimerhandler); _enable();
                   4146: }
                   4147: 
                   4148: void __interrupt __far timerhandler()
                   4149: {
                   4150:        totalclock++;
                   4151:        _chain_intr(oldtimerhandler);
                   4152:        outp(0x20,0x20);
                   4153: }
                   4154: 
                   4155: initkeys()
                   4156: {
                   4157:        long i;
                   4158: 
                   4159:        keyfifoplc = 0; keyfifoend = 0;
                   4160:        for(i=0;i<256;i++) keystatus[i] = 0;
                   4161:        oldkeyhandler = _dos_getvect(0x9);
                   4162:        _disable(); _dos_setvect(0x9, keyhandler); _enable();
                   4163: }
                   4164: 
                   4165: uninitkeys()
                   4166: {
                   4167:        short *ptr;
                   4168: 
                   4169:        _dos_setvect(0x9, oldkeyhandler);
                   4170:                //Turn off shifts to prevent stucks with quitting
                   4171:        ptr = (short *)0x417; *ptr &= ~0x030f;
                   4172: }
                   4173: 
                   4174: void __interrupt __far keyhandler()
                   4175: {
                   4176:        koutp(0x20,0x20);
                   4177:        oldreadch = readch; readch = kinp(0x60);
                   4178:        keytemp = kinp(0x61); koutp(0x61,keytemp|128); koutp(0x61,keytemp&127);
                   4179:        if ((readch|1) == 0xe1) { extended = 128; return; }
                   4180:        if (oldreadch != readch)
                   4181:        {
                   4182:                if ((readch&128) == 0)
                   4183:                {
                   4184:                        keytemp = readch+extended;
                   4185:                        if (keystatus[keytemp] == 0)
                   4186:                        {
                   4187:                                keystatus[keytemp] = 1;
                   4188:                                keyfifo[keyfifoend] = keytemp;
                   4189:                                keyfifo[(keyfifoend+1)&(KEYFIFOSIZ-1)] = 1;
                   4190:                                keyfifoend = ((keyfifoend+2)&(KEYFIFOSIZ-1));
                   4191:                        }
                   4192:                }
                   4193:                else
                   4194:                {
                   4195:                        keytemp = (readch&127)+extended;
                   4196:                        keystatus[keytemp] = 0;
                   4197:                        keyfifo[keyfifoend] = keytemp;
                   4198:                        keyfifo[(keyfifoend+1)&(KEYFIFOSIZ-1)] = 0;
                   4199:                        keyfifoend = ((keyfifoend+2)&(KEYFIFOSIZ-1));
                   4200:                }
                   4201:        }
                   4202:        extended = 0;
                   4203: }
                   4204: 
                   4205: testneighborsectors(short sect1, short sect2)
                   4206: {
                   4207:        short i, startwall, num1, num2;
                   4208: 
                   4209:        num1 = sector[sect1].wallnum;
                   4210:        num2 = sector[sect2].wallnum;
                   4211:        if (num1 < num2) //Traverse walls of sector with fewest walls (for speed)
                   4212:        {
                   4213:                startwall = sector[sect1].wallptr;
                   4214:                for(i=num1-1;i>=0;i--)
                   4215:                        if (wall[i+startwall].nextsector == sect2)
                   4216:                                return(1);
                   4217:        }
                   4218:        else
                   4219:        {
                   4220:                startwall = sector[sect2].wallptr;
                   4221:                for(i=num2-1;i>=0;i--)
                   4222:                        if (wall[i+startwall].nextsector == sect1)
                   4223:                                return(1);
                   4224:        }
                   4225:        return(0);
                   4226: }
                   4227: 
                   4228: loadgame()
                   4229: {
                   4230:        long i;
                   4231:        FILE *fil;
                   4232: 
                   4233:        if ((fil = fopen("save0000.gam","rb")) == 0) return(-1);
                   4234:        fread(&numplayers,2,1,fil);
                   4235:        fread(&myconnectindex,2,1,fil);
                   4236:        fread(&connecthead,2,1,fil);
                   4237:        fread(connectpoint2,MAXPLAYERS<<1,1,fil);
                   4238: 
                   4239:                //Make sure palookups get set, sprites will get overwritten later
                   4240:        for(i=connecthead;i>=0;i=connectpoint2[i]) initplayersprite((short)i);
                   4241: 
                   4242:        fread(posx,MAXPLAYERS<<2,1,fil);
                   4243:        fread(posy,MAXPLAYERS<<2,1,fil);
                   4244:        fread(posz,MAXPLAYERS<<2,1,fil);
                   4245:        fread(horiz,MAXPLAYERS<<2,1,fil);
                   4246:        fread(zoom,MAXPLAYERS<<2,1,fil);
                   4247:        fread(hvel,MAXPLAYERS<<2,1,fil);
                   4248:        fread(ang,MAXPLAYERS<<1,1,fil);
                   4249:        fread(cursectnum,MAXPLAYERS<<1,1,fil);
                   4250:        fread(ocursectnum,MAXPLAYERS<<1,1,fil);
                   4251:        fread(playersprite,MAXPLAYERS<<1,1,fil);
                   4252:        fread(deaths,MAXPLAYERS<<1,1,fil);
                   4253:        fread(lastchaingun,MAXPLAYERS<<2,1,fil);
                   4254:        fread(health,MAXPLAYERS<<2,1,fil);
                   4255:        fread(numbombs,MAXPLAYERS<<1,1,fil);
                   4256:        fread(oflags,MAXPLAYERS<<1,1,fil);
                   4257:        fread(dimensionmode,MAXPLAYERS,1,fil);
                   4258:        fread(revolvedoorstat,MAXPLAYERS,1,fil);
                   4259:        fread(revolvedoorang,MAXPLAYERS<<1,1,fil);
                   4260:        fread(revolvedoorrotang,MAXPLAYERS<<1,1,fil);
                   4261:        fread(revolvedoorx,MAXPLAYERS<<2,1,fil);
                   4262:        fread(revolvedoory,MAXPLAYERS<<2,1,fil);
                   4263: 
                   4264:        fread(&numsectors,2,1,fil);
                   4265:        fread(sector,sizeof(sectortype)*numsectors,1,fil);
                   4266: 
                   4267:        fread(&numwalls,2,1,fil);
                   4268:        fread(wall,sizeof(walltype)*numwalls,1,fil);
                   4269: 
                   4270:                //Store all sprites (even holes) to preserve indeces
                   4271:        fread(sprite,sizeof(spritetype)*MAXSPRITES,1,fil);
                   4272:        fread(headspritesect,(MAXSECTORS+1)<<1,1,fil);
                   4273:        fread(prevspritesect,MAXSPRITES<<1,1,fil);
                   4274:        fread(nextspritesect,MAXSPRITES<<1,1,fil);
                   4275:        fread(headspritestat,(MAXSTATUS+1)<<1,1,fil);
                   4276:        fread(prevspritestat,MAXSPRITES<<1,1,fil);
                   4277:        fread(nextspritestat,MAXSPRITES<<1,1,fil);
                   4278: 
                   4279:        fread(&fvel,4,1,fil);
                   4280:        fread(&svel,4,1,fil);
                   4281:        fread(&avel,4,1,fil);
                   4282: 
                   4283:        fread(&locselectedgun,4,1,fil);
                   4284:        fread(&loc.fvel,1,1,fil);
                   4285:        fread(&oloc.fvel,1,1,fil);
                   4286:        fread(&loc.svel,1,1,fil);
                   4287:        fread(&oloc.svel,1,1,fil);
                   4288:        fread(&loc.avel,1,1,fil);
                   4289:        fread(&oloc.avel,1,1,fil);
                   4290:        fread(&loc.bits,2,1,fil);
                   4291:        fread(&oloc.bits,2,1,fil);
                   4292: 
                   4293:        fread(&locselectedgun2,4,1,fil);
                   4294:        fread(&loc2.fvel,sizeof(input),1,fil);
                   4295: 
                   4296:        fread(sync,sizeof(input)*MAXPLAYERS,1,fil);
                   4297:        fread(osync,sizeof(input)*MAXPLAYERS,1,fil);
                   4298: 
                   4299:        fread(boardfilename,80,1,fil);
                   4300:        fread(&screenpeek,2,1,fil);
                   4301:        fread(&oldmousebstatus,2,1,fil);
                   4302:        fread(&brightness,2,1,fil);
                   4303:        fread(&neartagsector,2,1,fil);
                   4304:        fread(&neartagwall,2,1,fil);
                   4305:        fread(&neartagsprite,2,1,fil);
                   4306:        fread(&lockclock,4,1,fil);
                   4307:        fread(&neartagdist,4,1,fil);
                   4308:        fread(&neartaghitdist,4,1,fil);
                   4309: 
                   4310:        fread(turnspritelist,16<<1,1,fil);
                   4311:        fread(&turnspritecnt,2,1,fil);
                   4312:        fread(warpsectorlist,16<<1,1,fil);
                   4313:        fread(&warpsectorcnt,2,1,fil);
                   4314:        fread(xpanningsectorlist,16<<1,1,fil);
                   4315:        fread(&xpanningsectorcnt,2,1,fil);
                   4316:        fread(ypanningwalllist,64<<1,1,fil);
                   4317:        fread(&ypanningwallcnt,2,1,fil);
                   4318:        fread(floorpanninglist,64<<1,1,fil);
                   4319:        fread(&floorpanningcnt,2,1,fil);
                   4320:        fread(dragsectorlist,16<<1,1,fil);
                   4321:        fread(dragxdir,16<<1,1,fil);
                   4322:        fread(dragydir,16<<1,1,fil);
                   4323:        fread(&dragsectorcnt,2,1,fil);
                   4324:        fread(dragx1,16<<2,1,fil);
                   4325:        fread(dragy1,16<<2,1,fil);
                   4326:        fread(dragx2,16<<2,1,fil);
                   4327:        fread(dragy2,16<<2,1,fil);
                   4328:        fread(dragfloorz,16<<2,1,fil);
                   4329:        fread(&swingcnt,2,1,fil);
                   4330:        fread(swingwall,(32*5)<<1,1,fil);
                   4331:        fread(swingsector,32<<1,1,fil);
                   4332:        fread(swingangopen,32<<1,1,fil);
                   4333:        fread(swingangclosed,32<<1,1,fil);
                   4334:        fread(swingangopendir,32<<1,1,fil);
                   4335:        fread(swingang,32<<1,1,fil);
                   4336:        fread(swinganginc,32<<1,1,fil);
                   4337:        fread(swingx,(32*8)<<2,1,fil);
                   4338:        fread(swingy,(32*8)<<2,1,fil);
                   4339:        fread(revolvesector,4<<1,1,fil);
                   4340:        fread(revolveang,4<<1,1,fil);
                   4341:        fread(&revolvecnt,2,1,fil);
                   4342:        fread(revolvex,(4*16)<<2,1,fil);
                   4343:        fread(revolvey,(4*16)<<2,1,fil);
                   4344:        fread(revolvepivotx,4<<2,1,fil);
                   4345:        fread(revolvepivoty,4<<2,1,fil);
                   4346:        fread(subwaytracksector,(4*128)<<1,1,fil);
                   4347:        fread(subwaynumsectors,4<<1,1,fil);
                   4348:        fread(&subwaytrackcnt,2,1,fil);
                   4349:        fread(subwaystop,(4*8)<<2,1,fil);
                   4350:        fread(subwaystopcnt,4<<2,1,fil);
                   4351:        fread(subwaytrackx1,4<<2,1,fil);
                   4352:        fread(subwaytracky1,4<<2,1,fil);
                   4353:        fread(subwaytrackx2,4<<2,1,fil);
                   4354:        fread(subwaytracky2,4<<2,1,fil);
                   4355:        fread(subwayx,4<<2,1,fil);
                   4356:        fread(subwaygoalstop,4<<2,1,fil);
                   4357:        fread(subwayvel,4<<2,1,fil);
                   4358:        fread(subwaypausetime,4<<2,1,fil);
                   4359:        fread(waterfountainwall,MAXPLAYERS<<1,1,fil);
                   4360:        fread(waterfountaincnt,MAXPLAYERS<<1,1,fil);
                   4361:        fread(slimesoundcnt,MAXPLAYERS<<1,1,fil);
                   4362: 
                   4363:                //Warning: only works if all pointers are in sector structures!
                   4364:        fread(animateptr,MAXANIMATES<<2,1,fil);
                   4365:        for(i=MAXANIMATES-1;i>=0;i--)
                   4366:                animateptr[i] = (long *)(animateptr[i]+((long)sector));
                   4367:        fread(animategoal,MAXANIMATES<<2,1,fil);
                   4368:        fread(animatevel,MAXANIMATES<<2,1,fil);
                   4369:        fread(animateacc,MAXANIMATES<<2,1,fil);
                   4370:        fread(&animatecnt,4,1,fil);
                   4371: 
                   4372:        fread(&totalclock,4,1,fil);
                   4373:        fread(&numframes,4,1,fil);
                   4374:        fread(&randomseed,4,1,fil);
                   4375:        fread(&numpalookups,2,1,fil);
                   4376: 
                   4377:        fread(&visibility,4,1,fil);
                   4378:        fread(&parallaxvisibility,4,1,fil);
                   4379:        fread(&parallaxtype,1,1,fil);
                   4380:        fread(&parallaxyoffs,4,1,fil);
                   4381:        fread(pskyoff,MAXPSKYTILES<<1,1,fil);
                   4382:        fread(&pskybits,2,1,fil);
                   4383: 
                   4384:        fclose(fil);
                   4385: 
                   4386:        for(i=connecthead;i>=0;i=connectpoint2[i]) initplayersprite((short)i);
                   4387: 
                   4388:        totalclock = lockclock;
                   4389:        ototalclock = lockclock;
                   4390: 
                   4391:        strcpy(getmessage,"Game loaded.");
                   4392:        getmessageleng = strlen(getmessage);
                   4393:        getmessagetimeoff = totalclock+360+(getmessageleng<<4);
                   4394:        return(0);
                   4395: }
                   4396: 
                   4397: savegame()
                   4398: {
                   4399:        long i;
                   4400:        FILE *fil;
                   4401: 
                   4402:        if ((fil = fopen("save0000.gam","wb")) == 0) return(-1);
                   4403: 
                   4404:        fwrite(&numplayers,2,1,fil);
                   4405:        fwrite(&myconnectindex,2,1,fil);
                   4406:        fwrite(&connecthead,2,1,fil);
                   4407:        fwrite(connectpoint2,MAXPLAYERS<<1,1,fil);
                   4408: 
                   4409:        fwrite(posx,MAXPLAYERS<<2,1,fil);
                   4410:        fwrite(posy,MAXPLAYERS<<2,1,fil);
                   4411:        fwrite(posz,MAXPLAYERS<<2,1,fil);
                   4412:        fwrite(horiz,MAXPLAYERS<<2,1,fil);
                   4413:        fwrite(zoom,MAXPLAYERS<<2,1,fil);
                   4414:        fwrite(hvel,MAXPLAYERS<<2,1,fil);
                   4415:        fwrite(ang,MAXPLAYERS<<1,1,fil);
                   4416:        fwrite(cursectnum,MAXPLAYERS<<1,1,fil);
                   4417:        fwrite(ocursectnum,MAXPLAYERS<<1,1,fil);
                   4418:        fwrite(playersprite,MAXPLAYERS<<1,1,fil);
                   4419:        fwrite(deaths,MAXPLAYERS<<1,1,fil);
                   4420:        fwrite(lastchaingun,MAXPLAYERS<<2,1,fil);
                   4421:        fwrite(health,MAXPLAYERS<<2,1,fil);
                   4422:        fwrite(numbombs,MAXPLAYERS<<1,1,fil);
                   4423:        fwrite(oflags,MAXPLAYERS<<1,1,fil);
                   4424:        fwrite(dimensionmode,MAXPLAYERS,1,fil);
                   4425:        fwrite(revolvedoorstat,MAXPLAYERS,1,fil);
                   4426:        fwrite(revolvedoorang,MAXPLAYERS<<1,1,fil);
                   4427:        fwrite(revolvedoorrotang,MAXPLAYERS<<1,1,fil);
                   4428:        fwrite(revolvedoorx,MAXPLAYERS<<2,1,fil);
                   4429:        fwrite(revolvedoory,MAXPLAYERS<<2,1,fil);
                   4430: 
                   4431:        fwrite(&numsectors,2,1,fil);
                   4432:        fwrite(sector,sizeof(sectortype)*numsectors,1,fil);
                   4433: 
                   4434:        fwrite(&numwalls,2,1,fil);
                   4435:        fwrite(wall,sizeof(walltype)*numwalls,1,fil);
                   4436: 
                   4437:                //Store all sprites (even holes) to preserve indeces
                   4438:        fwrite(sprite,sizeof(spritetype)*MAXSPRITES,1,fil);
                   4439:        fwrite(headspritesect,(MAXSECTORS+1)<<1,1,fil);
                   4440:        fwrite(prevspritesect,MAXSPRITES<<1,1,fil);
                   4441:        fwrite(nextspritesect,MAXSPRITES<<1,1,fil);
                   4442:        fwrite(headspritestat,(MAXSTATUS+1)<<1,1,fil);
                   4443:        fwrite(prevspritestat,MAXSPRITES<<1,1,fil);
                   4444:        fwrite(nextspritestat,MAXSPRITES<<1,1,fil);
                   4445: 
                   4446:        fwrite(&fvel,4,1,fil);
                   4447:        fwrite(&svel,4,1,fil);
                   4448:        fwrite(&avel,4,1,fil);
                   4449: 
                   4450:        fwrite(&locselectedgun,4,1,fil);
                   4451:        fwrite(&loc.fvel,1,1,fil);
                   4452:        fwrite(&oloc.fvel,1,1,fil);
                   4453:        fwrite(&loc.svel,1,1,fil);
                   4454:        fwrite(&oloc.svel,1,1,fil);
                   4455:        fwrite(&loc.avel,1,1,fil);
                   4456:        fwrite(&oloc.avel,1,1,fil);
                   4457:        fwrite(&loc.bits,2,1,fil);
                   4458:        fwrite(&oloc.bits,2,1,fil);
                   4459: 
                   4460:        fwrite(&locselectedgun2,4,1,fil);
                   4461:        fwrite(&loc2.fvel,sizeof(input),1,fil);
                   4462: 
                   4463:        fwrite(sync,sizeof(input)*MAXPLAYERS,1,fil);
                   4464:        fwrite(osync,sizeof(input)*MAXPLAYERS,1,fil);
                   4465: 
                   4466:        fwrite(boardfilename,80,1,fil);
                   4467:        fwrite(&screenpeek,2,1,fil);
                   4468:        fwrite(&oldmousebstatus,2,1,fil);
                   4469:        fwrite(&brightness,2,1,fil);
                   4470:        fwrite(&neartagsector,2,1,fil);
                   4471:        fwrite(&neartagwall,2,1,fil);
                   4472:        fwrite(&neartagsprite,2,1,fil);
                   4473:        fwrite(&lockclock,4,1,fil);
                   4474:        fwrite(&neartagdist,4,1,fil);
                   4475:        fwrite(&neartaghitdist,4,1,fil);
                   4476: 
                   4477:        fwrite(turnspritelist,16<<1,1,fil);
                   4478:        fwrite(&turnspritecnt,2,1,fil);
                   4479:        fwrite(warpsectorlist,16<<1,1,fil);
                   4480:        fwrite(&warpsectorcnt,2,1,fil);
                   4481:        fwrite(xpanningsectorlist,16<<1,1,fil);
                   4482:        fwrite(&xpanningsectorcnt,2,1,fil);
                   4483:        fwrite(ypanningwalllist,64<<1,1,fil);
                   4484:        fwrite(&ypanningwallcnt,2,1,fil);
                   4485:        fwrite(floorpanninglist,64<<1,1,fil);
                   4486:        fwrite(&floorpanningcnt,2,1,fil);
                   4487:        fwrite(dragsectorlist,16<<1,1,fil);
                   4488:        fwrite(dragxdir,16<<1,1,fil);
                   4489:        fwrite(dragydir,16<<1,1,fil);
                   4490:        fwrite(&dragsectorcnt,2,1,fil);
                   4491:        fwrite(dragx1,16<<2,1,fil);
                   4492:        fwrite(dragy1,16<<2,1,fil);
                   4493:        fwrite(dragx2,16<<2,1,fil);
                   4494:        fwrite(dragy2,16<<2,1,fil);
                   4495:        fwrite(dragfloorz,16<<2,1,fil);
                   4496:        fwrite(&swingcnt,2,1,fil);
                   4497:        fwrite(swingwall,(32*5)<<1,1,fil);
                   4498:        fwrite(swingsector,32<<1,1,fil);
                   4499:        fwrite(swingangopen,32<<1,1,fil);
                   4500:        fwrite(swingangclosed,32<<1,1,fil);
                   4501:        fwrite(swingangopendir,32<<1,1,fil);
                   4502:        fwrite(swingang,32<<1,1,fil);
                   4503:        fwrite(swinganginc,32<<1,1,fil);
                   4504:        fwrite(swingx,(32*8)<<2,1,fil);
                   4505:        fwrite(swingy,(32*8)<<2,1,fil);
                   4506:        fwrite(revolvesector,4<<1,1,fil);
                   4507:        fwrite(revolveang,4<<1,1,fil);
                   4508:        fwrite(&revolvecnt,2,1,fil);
                   4509:        fwrite(revolvex,(4*16)<<2,1,fil);
                   4510:        fwrite(revolvey,(4*16)<<2,1,fil);
                   4511:        fwrite(revolvepivotx,4<<2,1,fil);
                   4512:        fwrite(revolvepivoty,4<<2,1,fil);
                   4513:        fwrite(subwaytracksector,(4*128)<<1,1,fil);
                   4514:        fwrite(subwaynumsectors,4<<1,1,fil);
                   4515:        fwrite(&subwaytrackcnt,2,1,fil);
                   4516:        fwrite(subwaystop,(4*8)<<2,1,fil);
                   4517:        fwrite(subwaystopcnt,4<<2,1,fil);
                   4518:        fwrite(subwaytrackx1,4<<2,1,fil);
                   4519:        fwrite(subwaytracky1,4<<2,1,fil);
                   4520:        fwrite(subwaytrackx2,4<<2,1,fil);
                   4521:        fwrite(subwaytracky2,4<<2,1,fil);
                   4522:        fwrite(subwayx,4<<2,1,fil);
                   4523:        fwrite(subwaygoalstop,4<<2,1,fil);
                   4524:        fwrite(subwayvel,4<<2,1,fil);
                   4525:        fwrite(subwaypausetime,4<<2,1,fil);
                   4526:        fwrite(waterfountainwall,MAXPLAYERS<<1,1,fil);
                   4527:        fwrite(waterfountaincnt,MAXPLAYERS<<1,1,fil);
                   4528:        fwrite(slimesoundcnt,MAXPLAYERS<<1,1,fil);
                   4529: 
                   4530:                //Warning: only works if all pointers are in sector structures!
                   4531:        for(i=MAXANIMATES-1;i>=0;i--)
                   4532:                animateptr[i] = (long *)(animateptr[i]-((long)sector));
                   4533:        fwrite(animateptr,MAXANIMATES<<2,1,fil);
                   4534:        for(i=MAXANIMATES-1;i>=0;i--)
                   4535:                animateptr[i] = (long *)(animateptr[i]+((long)sector));
                   4536:        fwrite(animategoal,MAXANIMATES<<2,1,fil);
                   4537:        fwrite(animatevel,MAXANIMATES<<2,1,fil);
                   4538:        fwrite(animateacc,MAXANIMATES<<2,1,fil);
                   4539:        fwrite(&animatecnt,4,1,fil);
                   4540: 
                   4541:        fwrite(&totalclock,4,1,fil);
                   4542:        fwrite(&numframes,4,1,fil);
                   4543:        fwrite(&randomseed,4,1,fil);
                   4544:        fwrite(&numpalookups,2,1,fil);
                   4545: 
                   4546:        fwrite(&visibility,4,1,fil);
                   4547:        fwrite(&parallaxvisibility,4,1,fil);
                   4548:        fwrite(&parallaxtype,1,1,fil);
                   4549:        fwrite(&parallaxyoffs,4,1,fil);
                   4550:        fwrite(pskyoff,MAXPSKYTILES<<1,1,fil);
                   4551:        fwrite(&pskybits,2,1,fil);
                   4552: 
                   4553:        fclose(fil);
                   4554: 
                   4555:        strcpy(getmessage,"Game saved.");
                   4556:        getmessageleng = strlen(getmessage);
                   4557:        getmessagetimeoff = totalclock+360+(getmessageleng<<4);
                   4558:        return(0);
                   4559: }
                   4560: 
                   4561: faketimerhandler()
                   4562: {
                   4563:        short other, packbufleng;
                   4564:        long i, j, k, l;
                   4565: 
                   4566:        if ((totalclock < ototalclock+TICSPERFRAME) || (ready2send == 0)) return;
                   4567:        ototalclock += TICSPERFRAME;
                   4568: 
                   4569:        getpackets(); if (getoutputcirclesize() >= 16) return;
                   4570:        getinput();
                   4571: 
                   4572:                //MASTER (or 1 player game)
                   4573:        if ((myconnectindex == connecthead) || (option[4] == 0))
                   4574:        {
                   4575:                fsync[myconnectindex].fvel = loc.fvel;
                   4576:                fsync[myconnectindex].svel = loc.svel;
                   4577:                fsync[myconnectindex].avel = loc.avel;
                   4578:                fsync[myconnectindex].bits = loc.bits;
                   4579: 
                   4580:                if (option[4] != 0)
                   4581:                {
                   4582:                        packbuf[0] = 0;
                   4583:                        j = ((numplayers+1)>>1)+1;
                   4584:                        for(k=1;k<j;k++) packbuf[k] = 0;
                   4585:                        k = (1<<3);
                   4586:                        for(i=connecthead;i>=0;i=connectpoint2[i])
                   4587:                        {
                   4588:                                l = 0;
                   4589:                                if (fsync[i].fvel != osync[i].fvel) packbuf[j++] = fsync[i].fvel, l |= 1;
                   4590:                                if (fsync[i].svel != osync[i].svel) packbuf[j++] = fsync[i].svel, l |= 2;
                   4591:                                if (fsync[i].avel != osync[i].avel) packbuf[j++] = fsync[i].avel, l |= 4;
                   4592:                                if (fsync[i].bits != osync[i].bits)
                   4593:                                {
                   4594:                                        packbuf[j++] = (fsync[i].bits&255);
                   4595:                                        packbuf[j++] = ((fsync[i].bits>>8)&255);
                   4596:                                        l |= 8;
                   4597:                                }
                   4598:                                packbuf[k>>3] |= (l<<(k&7));
                   4599:                                k += 4;
                   4600: 
                   4601:                                osync[i].fvel = fsync[i].fvel;
                   4602:                                osync[i].svel = fsync[i].svel;
                   4603:                                osync[i].avel = fsync[i].avel;
                   4604:                                osync[i].bits = fsync[i].bits;
                   4605:                        }
                   4606: 
                   4607:                        while (syncvalhead != syncvaltail)
                   4608:                        {
                   4609:                                packbuf[j] = (char)(syncval[syncvaltail]&255);
                   4610:                                packbuf[j+1] = (char)((syncval[syncvaltail]>>8)&255);
                   4611:                                j += 2;
                   4612:                                syncvaltail = ((syncvaltail+1)&(MOVEFIFOSIZ-1));
                   4613:                        }
                   4614: 
                   4615:                        for(i=connectpoint2[connecthead];i>=0;i=connectpoint2[i])
                   4616:                                sendpacket(i,packbuf,j);
                   4617:                }
                   4618:                else if (numplayers == 2)
                   4619:                {
                   4620:                        if (keystatus[0xb5] > 0)
                   4621:                        {
                   4622:                                keystatus[0xb5] = 0;
                   4623:                                locselectedgun2++; if (locselectedgun2 >= 3) locselectedgun2 = 0;
                   4624:                        }
                   4625: 
                   4626:                                //Second player on 1 computer mode
                   4627:                        loc2.fvel = min(max(fvel2,-128+8),127-8);
                   4628:                        loc2.svel = min(max(svel2,-128+8),127-8);
                   4629:                        loc2.avel = min(max(avel2,-128+16),127-16);
                   4630:                        loc2.bits = (locselectedgun2<<13);
                   4631:                        loc2.bits |= keystatus[0x45];                  //Stand high
                   4632:                        loc2.bits |= (keystatus[0x47]<<1);             //Stand low
                   4633:                        loc2.bits |= (1<<8);                           //Run
                   4634:                        loc2.bits |= (keystatus[0x49]<<2);             //Look up
                   4635:                        loc2.bits |= (keystatus[0x37]<<3);             //Look down
                   4636:                        loc2.bits |= (keystatus[0x50]<<10);            //Space
                   4637:                        loc2.bits |= (keystatus[0x52]<<11);            //Shoot
                   4638: 
                   4639:                        other = connectpoint2[myconnectindex];
                   4640:                        if (other < 0) other = connecthead;
                   4641: 
                   4642:                        fsync[other].fvel = loc2.fvel;
                   4643:                        fsync[other].svel = loc2.svel;
                   4644:                        fsync[other].avel = loc2.avel;
                   4645:                        fsync[other].bits = loc2.bits;
                   4646:                }
                   4647:                movethings();  //Move EVERYTHING (you too!)
                   4648:        }
                   4649:        else                        //I am a SLAVE
                   4650:        {
                   4651:                packbuf[0] = 1; packbuf[1] = 0; j = 2;
                   4652:                if (loc.fvel != oloc.fvel) packbuf[j++] = loc.fvel, oloc.fvel = loc.fvel, packbuf[1] |= 1;
                   4653:                if (loc.svel != oloc.svel) packbuf[j++] = loc.svel, oloc.svel = loc.svel, packbuf[1] |= 2;
                   4654:                if (loc.avel != oloc.avel) packbuf[j++] = loc.avel, oloc.avel = loc.avel, packbuf[1] |= 4;
                   4655:                if ((loc.bits^oloc.bits)&0x00ff) packbuf[j++] = (loc.bits&255), packbuf[1] |= 8;
                   4656:                if ((loc.bits^oloc.bits)&0xff00) packbuf[j++] = ((loc.bits>>8)&255), packbuf[1] |= 16;
                   4657:                oloc.bits = loc.bits;
                   4658:                sendpacket(connecthead,packbuf,j);
                   4659:        }
                   4660: }
                   4661: 
                   4662: getpackets()
                   4663: {
                   4664:        long i, j, k, l;
                   4665:        short other, packbufleng, movecnt;
                   4666: 
                   4667:        if (option[4] == 0) return;
                   4668: 
                   4669:        movecnt = 0;
                   4670:        while ((packbufleng = getpacket(&other,packbuf)) > 0)
                   4671:        {
                   4672:                switch(packbuf[0])
                   4673:                {
                   4674:                        case 0:  //[0] (receive master sync buffer)
                   4675:                                j = ((numplayers+1)>>1)+1; k = (1<<3);
                   4676:                                for(i=connecthead;i>=0;i=connectpoint2[i])
                   4677:                                {
                   4678:                                        l = (packbuf[k>>3]>>(k&7));
                   4679:                                        if (l&1) fsync[i].fvel = packbuf[j++];
                   4680:                                        if (l&2) fsync[i].svel = packbuf[j++];
                   4681:                                        if (l&4) fsync[i].avel = packbuf[j++];
                   4682:                                        if (l&8)
                   4683:                                        {
                   4684:                                                fsync[i].bits = ((short)packbuf[j])+(((short)packbuf[j+1])<<8);
                   4685:                                                j += 2;
                   4686:                                        }
                   4687:                                        k += 4;
                   4688:                                }
                   4689:                                while (j != packbufleng)
                   4690:                                {
                   4691:                                        othersyncval[othersyncvalhead] = ((long)packbuf[j]);
                   4692:                                        othersyncval[othersyncvalhead] += (((long)packbuf[j+1])<<8);
                   4693:                                        j += 2;
                   4694:                                        othersyncvalhead = ((othersyncvalhead+1)&(MOVEFIFOSIZ-1));
                   4695:                                }
                   4696: 
                   4697:                                if ((syncvalhead != syncvaltail) && (othersyncvalhead != syncvaltail))
                   4698:                                {
                   4699:                                        syncstat = 0;
                   4700:                                        do
                   4701:                                        {
                   4702:                                                syncstat |= (syncval[syncvaltail]^othersyncval[syncvaltail]);
                   4703:                                                syncvaltail = ((syncvaltail+1)&(MOVEFIFOSIZ-1));
                   4704: 
                   4705:                                        } while ((syncvalhead != syncvaltail) && (othersyncvalhead != syncvaltail));
                   4706:                                }
                   4707: 
                   4708:                                movethings();        //Move all players and sprites
                   4709:                                movecnt++;
                   4710:                                break;
                   4711:                        case 1:  //[1] (receive slave sync buffer)
                   4712:                                j = 2; k = packbuf[1];
                   4713:                                if (k&1) fsync[other].fvel = packbuf[j++];
                   4714:                                if (k&2) fsync[other].svel = packbuf[j++];
                   4715:                                if (k&4) fsync[other].avel = packbuf[j++];
                   4716:                                if (k&8) fsync[other].bits = ((fsync[other].bits&0xff00)|((short)packbuf[j++]));
                   4717:                                if (k&16) fsync[other].bits = ((fsync[other].bits&0x00ff)|(((short)packbuf[j++])<<8));
                   4718:                                break;
                   4719:                        case 2:
                   4720:                                getmessageleng = packbufleng-1;
                   4721:                                for(j=getmessageleng-1;j>=0;j--) getmessage[j] = packbuf[j+1];
                   4722:                                getmessagetimeoff = totalclock+360+(getmessageleng<<4);
                   4723:                                break;
                   4724:                        case 3:
                   4725:                                wsay("getstuff.wav",4096L,63L,63L);
                   4726:                                break;
                   4727:                        case 5:
                   4728:                                playerreadyflag[other] = packbuf[1];
                   4729:                                if ((other == connecthead) && (packbuf[1] == 2))
                   4730:                                        sendpacket(connecthead,packbuf,2);
                   4731:                                break;
                   4732:                        case 255:  //[255] (logout)
                   4733:                                keystatus[1] = 1;
                   4734:                                break;
                   4735:                }
                   4736:        }
                   4737:        if ((myconnectindex != connecthead) && ((movecnt&1) == 0))
                   4738:        {
                   4739:                if (rand()&1) ototalclock += (TICSPERFRAME>>1);
                   4740:                                        else ototalclock -= (TICSPERFRAME>>1);
                   4741:        }
                   4742: }
                   4743: 
                   4744: drawoverheadmap(long cposx, long cposy, long czoom, short cang)
                   4745: {
                   4746:        long i, j, k, l, x1, y1, x2, y2, x3, y3, x4, y4, ox, oy, xoff, yoff;
                   4747:        long dax, day, cosang, sinang, xspan, yspan, sprx, spry;
                   4748:        long xrepeat, yrepeat, z1, z2, startwall, endwall, tilenum, daang;
                   4749:        long xvect, yvect, xvect2, yvect2;
                   4750:        char col;
                   4751:        walltype *wal, *wal2;
                   4752:        spritetype *spr;
                   4753: 
                   4754:        xvect = sintable[(-cang)&2047] * czoom;
                   4755:        yvect = sintable[(1536-cang)&2047] * czoom;
                   4756:        xvect2 = mulscale16(xvect,yxaspect);
                   4757:        yvect2 = mulscale16(yvect,yxaspect);
                   4758: 
                   4759:                //Draw red lines
                   4760:        for(i=0;i<numsectors;i++)
                   4761:        {
                   4762:                startwall = sector[i].wallptr;
                   4763:                endwall = sector[i].wallptr + sector[i].wallnum;
                   4764: 
                   4765:                z1 = sector[i].ceilingz; z2 = sector[i].floorz;
                   4766: 
                   4767:                for(j=startwall,wal=&wall[startwall];j<endwall;j++,wal++)
                   4768:                {
                   4769:                        k = wal->nextwall; if (k < 0) continue;
                   4770: 
                   4771:                        if ((show2dwall[j>>3]&(1<<(j&7))) == 0) continue;
                   4772:                        if ((k > j) && ((show2dwall[k>>3]&(1<<(k&7))) > 0)) continue;
                   4773: 
                   4774:                        if (sector[wal->nextsector].ceilingz == z1)
                   4775:                                if (sector[wal->nextsector].floorz == z2)
                   4776:                                        if (((wal->cstat|wall[wal->nextwall].cstat)&(16+32)) == 0) continue;
                   4777: 
                   4778:                        col = 152;
                   4779: 
                   4780:                        if (dimensionmode[screenpeek] == 2)
                   4781:                        {
                   4782:                                if (sector[i].floorz != sector[i].ceilingz)
                   4783:                                        if (sector[wal->nextsector].floorz != sector[wal->nextsector].ceilingz)
                   4784:                                                if (((wal->cstat|wall[wal->nextwall].cstat)&(16+32)) == 0)
                   4785:                                                        if (sector[i].floorz == sector[wal->nextsector].floorz) continue;
                   4786:                                if (sector[i].floorpicnum != sector[wal->nextsector].floorpicnum) continue;
                   4787:                                if (sector[i].floorshade != sector[wal->nextsector].floorshade) continue;
                   4788:                                col = 12;
                   4789:                        }
                   4790: 
                   4791:                        ox = wal->x-cposx; oy = wal->y-cposy;
                   4792:                        x1 = dmulscale16(ox,xvect,-oy,yvect)+(xdim<<11);
                   4793:                        y1 = dmulscale16(oy,xvect2,ox,yvect2)+(ydim<<11);
                   4794: 
                   4795:                        wal2 = &wall[wal->point2];
                   4796:                        ox = wal2->x-cposx; oy = wal2->y-cposy;
                   4797:                        x2 = dmulscale16(ox,xvect,-oy,yvect)+(xdim<<11);
                   4798:                        y2 = dmulscale16(oy,xvect2,ox,yvect2)+(ydim<<11);
                   4799: 
                   4800:                        drawline256(x1,y1,x2,y2,col);
                   4801:                }
                   4802:        }
                   4803: 
                   4804:                //Draw sprites
                   4805:        k = playersprite[screenpeek];
                   4806:        for(i=0;i<numsectors;i++)
                   4807:                for(j=headspritesect[i];j>=0;j=nextspritesect[j])
                   4808:                        if ((show2dsprite[j>>3]&(1<<(j&7))) > 0)
                   4809:                        {
                   4810:                                spr = &sprite[j]; if (spr->cstat&0x8000) continue;
                   4811:                                col = 56;
                   4812:                                if (spr->cstat&1) col = 248;
                   4813:                                if (j == k) col = 31;
                   4814: 
                   4815:                                k = statrate[spr->statnum];
                   4816:                                sprx = spr->x;
                   4817:                                spry = spr->y;
                   4818:                                if (k >= 0)
                   4819:                                {
                   4820:                                        switch(k)
                   4821:                                        {
                   4822:                                                case 0: l = smoothratio; break;
                   4823:                                                case 1: l = (smoothratio>>1)+(((nummoves-j)&1)<<15); break;
                   4824:                                                case 3: l = (smoothratio>>2)+(((nummoves-j)&3)<<14); break;
                   4825:                                                case 7: l = (smoothratio>>3)+(((nummoves-j)&7)<<13); break;
                   4826:                                                case 15: l = (smoothratio>>4)+(((nummoves-j)&15)<<12); break;
                   4827:                                        }
                   4828:                                        sprx = osprite[j].x+mulscale16(sprx-osprite[j].x,l);
                   4829:                                        spry = osprite[j].y+mulscale16(spry-osprite[j].y,l);
                   4830:                                }
                   4831: 
                   4832:                                switch (spr->cstat&48)
                   4833:                                {
                   4834:                                        case 0:
                   4835:                                                ox = sprx-cposx; oy = spry-cposy;
                   4836:                                                x1 = dmulscale16(ox,xvect,-oy,yvect);
                   4837:                                                y1 = dmulscale16(oy,xvect2,ox,yvect2);
                   4838: 
                   4839:                                                if (dimensionmode[screenpeek] == 1)
                   4840:                                                {
                   4841:                                                        ox = (sintable[(spr->ang+512)&2047]>>7);
                   4842:                                                        oy = (sintable[(spr->ang)&2047]>>7);
                   4843:                                                        x2 = dmulscale16(ox,xvect,-oy,yvect);
                   4844:                                                        y2 = dmulscale16(oy,xvect,ox,yvect);
                   4845: 
                   4846:                                                        if (j == playersprite[screenpeek])
                   4847:                                                        {
                   4848:                                                                x2 = 0L;
                   4849:                                                                y2 = -(czoom<<5);
                   4850:                                                        }
                   4851: 
                   4852:                                                        x3 = mulscale16(x2,yxaspect);
                   4853:                                                        y3 = mulscale16(y2,yxaspect);
                   4854: 
                   4855:                                                        drawline256(x1-x2+(xdim<<11),y1-y3+(ydim<<11),
                   4856:                                                                                        x1+x2+(xdim<<11),y1+y3+(ydim<<11),col);
                   4857:                                                        drawline256(x1-y2+(xdim<<11),y1+x3+(ydim<<11),
                   4858:                                                                                        x1+x2+(xdim<<11),y1+y3+(ydim<<11),col);
                   4859:                                                        drawline256(x1+y2+(xdim<<11),y1-x3+(ydim<<11),
                   4860:                                                                                        x1+x2+(xdim<<11),y1+y3+(ydim<<11),col);
                   4861:                                                }
                   4862:                                                else
                   4863:                                                {
                   4864:                                                        if (((gotsector[i>>3]&(1<<(i&7))) > 0) && (czoom > 96))
                   4865:                                                        {
                   4866:                                                                daang = (spr->ang-cang)&2047;
                   4867:                                                                if (j == playersprite[screenpeek]) { x1 = 0; y1 = 0; daang = 0; }
                   4868:                                                                rotatesprite((x1<<4)+(xdim<<15),(y1<<4)+(ydim<<15),mulscale16(czoom*spr->yrepeat,yxaspect),daang,spr->picnum,spr->shade,spr->pal,(spr->cstat&2)>>1,windowx1,windowy1,windowx2,windowy2);
                   4869:                                                        }
                   4870:                                                }
                   4871:                                                break;
                   4872:                                        case 16:
                   4873:                                                x1 = sprx; y1 = spry;
                   4874:                                                tilenum = spr->picnum;
                   4875:                                                xoff = (long)((signed char)((picanm[tilenum]>>8)&255))+((long)spr->xoffset);
                   4876:                                                if ((spr->cstat&4) > 0) xoff = -xoff;
                   4877:                                                k = spr->ang; l = spr->xrepeat;
                   4878:                                                dax = sintable[k&2047]*l; day = sintable[(k+1536)&2047]*l;
                   4879:                                                l = tilesizx[tilenum]; k = (l>>1)+xoff;
                   4880:                                                x1 -= mulscale16(dax,k); x2 = x1+mulscale16(dax,l);
                   4881:                                                y1 -= mulscale16(day,k); y2 = y1+mulscale16(day,l);
                   4882: 
                   4883:                                                ox = x1-cposx; oy = y1-cposy;
                   4884:                                                x1 = dmulscale16(ox,xvect,-oy,yvect);
                   4885:                                                y1 = dmulscale16(oy,xvect2,ox,yvect2);
                   4886: 
                   4887:                                                ox = x2-cposx; oy = y2-cposy;
                   4888:                                                x2 = dmulscale16(ox,xvect,-oy,yvect);
                   4889:                                                y2 = dmulscale16(oy,xvect2,ox,yvect2);
                   4890: 
                   4891:                                                drawline256(x1+(xdim<<11),y1+(ydim<<11),
                   4892:                                                                                x2+(xdim<<11),y2+(ydim<<11),col);
                   4893: 
                   4894:                                                break;
                   4895:                                        case 32:
                   4896:                                                if (dimensionmode[screenpeek] == 1)
                   4897:                                                {
                   4898:                                                        tilenum = spr->picnum;
                   4899:                                                        xoff = (long)((signed char)((picanm[tilenum]>>8)&255))+((long)spr->xoffset);
                   4900:                                                        yoff = (long)((signed char)((picanm[tilenum]>>16)&255))+((long)spr->yoffset);
                   4901:                                                        if ((spr->cstat&4) > 0) xoff = -xoff;
                   4902:                                                        if ((spr->cstat&8) > 0) yoff = -yoff;
                   4903: 
                   4904:                                                        k = spr->ang;
                   4905:                                                        cosang = sintable[(k+512)&2047]; sinang = sintable[k];
                   4906:                                                        xspan = tilesizx[tilenum]; xrepeat = spr->xrepeat;
                   4907:                                                        yspan = tilesizy[tilenum]; yrepeat = spr->yrepeat;
                   4908: 
                   4909:                                                        dax = ((xspan>>1)+xoff)*xrepeat; day = ((yspan>>1)+yoff)*yrepeat;
                   4910:                                                        x1 = sprx + dmulscale16(sinang,dax,cosang,day);
                   4911:                                                        y1 = spry + dmulscale16(sinang,day,-cosang,dax);
                   4912:                                                        l = xspan*xrepeat;
                   4913:                                                        x2 = x1 - mulscale16(sinang,l);
                   4914:                                                        y2 = y1 + mulscale16(cosang,l);
                   4915:                                                        l = yspan*yrepeat;
                   4916:                                                        k = -mulscale16(cosang,l); x3 = x2+k; x4 = x1+k;
                   4917:                                                        k = -mulscale16(sinang,l); y3 = y2+k; y4 = y1+k;
                   4918: 
                   4919:                                                        ox = x1-cposx; oy = y1-cposy;
                   4920:                                                        x1 = dmulscale16(ox,xvect,-oy,yvect);
                   4921:                                                        y1 = dmulscale16(oy,xvect2,ox,yvect2);
                   4922: 
                   4923:                                                        ox = x2-cposx; oy = y2-cposy;
                   4924:                                                        x2 = dmulscale16(ox,xvect,-oy,yvect);
                   4925:                                                        y2 = dmulscale16(oy,xvect2,ox,yvect2);
                   4926: 
                   4927:                                                        ox = x3-cposx; oy = y3-cposy;
                   4928:                                                        x3 = dmulscale16(ox,xvect,-oy,yvect);
                   4929:                                                        y3 = dmulscale16(oy,xvect2,ox,yvect2);
                   4930: 
                   4931:                                                        ox = x4-cposx; oy = y4-cposy;
                   4932:                                                        x4 = dmulscale16(ox,xvect,-oy,yvect);
                   4933:                                                        y4 = dmulscale16(oy,xvect2,ox,yvect2);
                   4934: 
                   4935:                                                        drawline256(x1+(xdim<<11),y1+(ydim<<11),
                   4936:                                                                                        x2+(xdim<<11),y2+(ydim<<11),col);
                   4937: 
                   4938:                                                        drawline256(x2+(xdim<<11),y2+(ydim<<11),
                   4939:                                                                                        x3+(xdim<<11),y3+(ydim<<11),col);
                   4940: 
                   4941:                                                        drawline256(x3+(xdim<<11),y3+(ydim<<11),
                   4942:                                                                                        x4+(xdim<<11),y4+(ydim<<11),col);
                   4943: 
                   4944:                                                        drawline256(x4+(xdim<<11),y4+(ydim<<11),
                   4945:                                                                                        x1+(xdim<<11),y1+(ydim<<11),col);
                   4946: 
                   4947:                                                }
                   4948:                                                break;
                   4949:                                }
                   4950:                        }
                   4951: 
                   4952:                //Draw white lines
                   4953:        for(i=0;i<numsectors;i++)
                   4954:        {
                   4955:                startwall = sector[i].wallptr;
                   4956:                endwall = sector[i].wallptr + sector[i].wallnum;
                   4957: 
                   4958:                k = -1;
                   4959:                for(j=startwall,wal=&wall[startwall];j<endwall;j++,wal++)
                   4960:                {
                   4961:                        if (wal->nextwall >= 0) continue;
                   4962: 
                   4963:                        if ((show2dwall[j>>3]&(1<<(j&7))) == 0) continue;
                   4964: 
                   4965:                        if (tilesizx[wal->picnum] == 0) continue;
                   4966:                        if (tilesizy[wal->picnum] == 0) continue;
                   4967: 
                   4968:                        if (j == k)
                   4969:                                { x1 = x2; y1 = y2; }
                   4970:                        else
                   4971:                        {
                   4972:                                ox = wal->x-cposx; oy = wal->y-cposy;
                   4973:                                x1 = dmulscale16(ox,xvect,-oy,yvect)+(xdim<<11);
                   4974:                                y1 = dmulscale16(oy,xvect2,ox,yvect2)+(ydim<<11);
                   4975:                        }
                   4976: 
                   4977:                        k = wal->point2; wal2 = &wall[k];
                   4978:                        ox = wal2->x-cposx; oy = wal2->y-cposy;
                   4979:                        x2 = dmulscale16(ox,xvect,-oy,yvect)+(xdim<<11);
                   4980:                        y2 = dmulscale16(oy,xvect2,ox,yvect2)+(ydim<<11);
                   4981: 
                   4982:                        drawline256(x1,y1,x2,y2,24);
                   4983:                }
                   4984:        }
                   4985: }
                   4986: 
                   4987:        //New movesprite using getzrange.  Note that I made the getzrange
                   4988:        //parameters global (&globhiz,&globhihit,&globloz,&globlohit) so they
                   4989:        //don't need to be passed everywhere.  Also this should make this
                   4990:        //movesprite function compatible with the older movesprite functions.
                   4991: movesprite(short spritenum, long dx, long dy, long dz, long ceildist, long flordist, char cliptype)
                   4992: {
                   4993:        long daz, zoffs, templong;
                   4994:        short retval, dasectnum, datempshort;
                   4995:        spritetype *spr;
                   4996: 
                   4997:        spr = &sprite[spritenum];
                   4998: 
                   4999:        if ((spr->cstat&128) == 0)
                   5000:                zoffs = -((tilesizy[spr->picnum]*spr->yrepeat)<<1);
                   5001:        else
                   5002:                zoffs = 0;
                   5003: 
                   5004:        dasectnum = spr->sectnum;  //Can't modify sprite sectors directly becuase of linked lists
                   5005:        daz = spr->z+zoffs;  //Must do this if not using the new centered centering (of course)
                   5006:        retval = clipmove(&spr->x,&spr->y,&daz,&dasectnum,dx,dy,
                   5007:                                                        ((long)spr->clipdist)<<2,ceildist,flordist,cliptype);
                   5008: 
                   5009:        if (dasectnum < 0) retval = -1;
                   5010: 
                   5011:        if ((dasectnum != spr->sectnum) && (dasectnum >= 0))
                   5012:                changespritesect(spritenum,dasectnum);
                   5013: 
                   5014:                //Set the blocking bit to 0 temporarly so getzrange doesn't pick up
                   5015:                //its own sprite
                   5016:        datempshort = spr->cstat; spr->cstat &= ~1;
                   5017:        getzrange(spr->x,spr->y,spr->z-1,spr->sectnum,
                   5018:                                 &globhiz,&globhihit,&globloz,&globlohit,
                   5019:                                 ((long)spr->clipdist)<<2,cliptype);
                   5020:        spr->cstat = datempshort;
                   5021: 
                   5022:        daz = spr->z+zoffs + dz;
                   5023:        if ((daz <= globhiz) || (daz > globloz))
                   5024:        {
                   5025:                if (retval != 0) return(retval);
                   5026:                return(16384+dasectnum);
                   5027:        }
                   5028:        spr->z = daz-zoffs;
                   5029:        return(retval);
                   5030: }
                   5031: 
                   5032: waitforeverybody()
                   5033: {
                   5034:        long i, j, oldtotalclock;
                   5035: 
                   5036:        if (numplayers < 2) return;
                   5037: 
                   5038:        if (myconnectindex == connecthead)
                   5039:        {
                   5040:                for(j=1;j<=2;j++)
                   5041:                {
                   5042:                        for(i=connectpoint2[connecthead];i>=0;i=connectpoint2[i])
                   5043:                                playerreadyflag[i] = 0;
                   5044:                        oldtotalclock = totalclock-8;
                   5045:                        do
                   5046:                        {
                   5047:                                getpackets();
                   5048:                                if (totalclock >= oldtotalclock+8)
                   5049:                                {
                   5050:                                        oldtotalclock = totalclock;
                   5051:                                        packbuf[0] = 5;
                   5052:                                        packbuf[1] = j;
                   5053:                                        for(i=connectpoint2[connecthead];i>=0;i=connectpoint2[i])
                   5054:                                                if (playerreadyflag[i] != j) sendpacket(i,packbuf,2);
                   5055:                                }
                   5056:                                for(i=connectpoint2[connecthead];i>=0;i=connectpoint2[i])
                   5057:                                        if (playerreadyflag[i] != j) break;
                   5058:                        } while (i >= 0);
                   5059:                }
                   5060:        }
                   5061:        else
                   5062:        {
                   5063:                playerreadyflag[connecthead] = 0;
                   5064:                while (playerreadyflag[connecthead] != 2)
                   5065:                {
                   5066:                        getpackets();
                   5067:                        if (playerreadyflag[connecthead] == 1)
                   5068:                        {
                   5069:                                playerreadyflag[connecthead] = 0;
                   5070:                                sendpacket(connecthead,packbuf,2);
                   5071:                        }
                   5072:                }
                   5073:        }
                   5074: }
                   5075: 
                   5076: getsyncstat()
                   5077: {
                   5078:        long i, j;
                   5079:        unsigned short crc;
                   5080:        spritetype *spr;
                   5081: 
                   5082:        crc = 0;
                   5083:        updatecrc16(crc,randomseed); updatecrc16(crc,randomseed>>8);
                   5084:        for(i=connecthead;i>=0;i=connectpoint2[i])
                   5085:        {
                   5086:                updatecrc16(crc,posx[i]); updatecrc16(crc,posx[i]>>8); updatecrc16(crc,posx[i]>>16); updatecrc16(crc,posx[i]>>24);
                   5087:                updatecrc16(crc,posy[i]); updatecrc16(crc,posy[i]>>8); updatecrc16(crc,posy[i]>>16); updatecrc16(crc,posy[i]>>24);
                   5088:                updatecrc16(crc,posz[i]); updatecrc16(crc,posz[i]>>8); updatecrc16(crc,posz[i]>>16); updatecrc16(crc,posz[i]>>24);
                   5089:                updatecrc16(crc,ang[i]); updatecrc16(crc,ang[i]>>8);
                   5090:                updatecrc16(crc,horiz[i]); updatecrc16(crc,horiz[i]>>8); updatecrc16(crc,horiz[i]>>16); updatecrc16(crc,horiz[i]>>24);
                   5091:                updatecrc16(crc,health[i]); updatecrc16(crc,health[i]>>8); updatecrc16(crc,health[i]>>16); updatecrc16(crc,health[i]>>24);
                   5092:                updatecrc16(crc,cursectnum[i]); updatecrc16(crc,cursectnum[i]>>8);
                   5093:        }
                   5094: 
                   5095:        for(i=7;i>=0;i--)
                   5096:                for(j=headspritestat[i];j>=0;j=nextspritestat[j])
                   5097:                {
                   5098:                        spr = &sprite[j];
                   5099:                        updatecrc16(crc,spr->x); updatecrc16(crc,spr->x>>8); updatecrc16(crc,spr->x>>16); updatecrc16(crc,spr->x>>24);
                   5100:                        updatecrc16(crc,spr->y); updatecrc16(crc,spr->y>>8); updatecrc16(crc,spr->y>>16); updatecrc16(crc,spr->y>>24);
                   5101:                        updatecrc16(crc,spr->z); updatecrc16(crc,spr->z>>8); updatecrc16(crc,spr->z>>16); updatecrc16(crc,spr->z>>24);
                   5102:                        updatecrc16(crc,spr->ang); updatecrc16(crc,spr->ang>>8);
                   5103:                }
                   5104:        return(crc);
                   5105: }
                   5106: 
                   5107: searchmap(short startsector)
                   5108: {
                   5109:        long i, j, dasect, splc, send, startwall, endwall;
                   5110:        short dapic;
                   5111:        walltype *wal;
                   5112: 
                   5113:        if ((startsector < 0) || (startsector >= numsectors)) return;
                   5114:        for(i=0;i<(MAXSECTORS>>3);i++) show2dsector[i] = 0;
                   5115:        for(i=0;i<(MAXWALLS>>3);i++) show2dwall[i] = 0;
                   5116:        for(i=0;i<(MAXSPRITES>>3);i++) show2dsprite[i] = 0;
                   5117: 
                   5118:        automapping = 0;
                   5119: 
                   5120:                //Search your area recursively & set all show2dsector/show2dwalls
                   5121:        tempshort[0] = startsector;
                   5122:        show2dsector[startsector>>3] |= (1<<(startsector&7));
                   5123:        dapic = sector[startsector].ceilingpicnum;
                   5124:        if (waloff[dapic] == 0) loadtile(dapic);
                   5125:        dapic = sector[startsector].floorpicnum;
                   5126:        if (waloff[dapic] == 0) loadtile(dapic);
                   5127:        for(splc=0,send=1;splc<send;splc++)
                   5128:        {
                   5129:                dasect = tempshort[splc];
                   5130:                startwall = sector[dasect].wallptr;
                   5131:                endwall = startwall + sector[dasect].wallnum;
                   5132:                for(i=startwall,wal=&wall[startwall];i<endwall;i++,wal++)
                   5133:                {
                   5134:                        show2dwall[i>>3] |= (1<<(i&7));
                   5135:                        dapic = wall[i].picnum;
                   5136:                        if (waloff[dapic] == 0) loadtile(dapic);
                   5137:                        dapic = wall[i].overpicnum;
                   5138:                        if (((dapic&0xfffff000) == 0) && (waloff[dapic] == 0)) loadtile(dapic);
                   5139: 
                   5140:                        j = wal->nextsector;
                   5141:                        if ((j >= 0) && ((show2dsector[j>>3]&(1<<(j&7))) == 0))
                   5142:                        {
                   5143:                                show2dsector[j>>3] |= (1<<(j&7));
                   5144: 
                   5145:                                dapic = sector[j].ceilingpicnum;
                   5146:                                if (waloff[dapic] == 0) loadtile(dapic);
                   5147:                                dapic = sector[j].floorpicnum;
                   5148:                                if (waloff[dapic] == 0) loadtile(dapic);
                   5149: 
                   5150:                                tempshort[send++] = (short)j;
                   5151:                        }
                   5152:                }
                   5153: 
                   5154:                for(i=headspritesect[dasect];i>=0;i=nextspritesect[i])
                   5155:                {
                   5156:                        show2dsprite[i>>3] |= (1<<(i&7));
                   5157:                        dapic = sprite[i].picnum;
                   5158:                        if (waloff[dapic] == 0) loadtile(dapic);
                   5159:                }
                   5160:        }
                   5161: }
                   5162: 
                   5163: setinterpolation(long *posptr)
                   5164: {
                   5165:        long i;
                   5166: 
                   5167:        if (numinterpolations >= MAXINTERPOLATIONS) return;
                   5168:        for(i=numinterpolations-1;i>=0;i--)
                   5169:                if (curipos[i] == posptr) return;
                   5170:        curipos[numinterpolations] = posptr;
                   5171:        oldipos[numinterpolations] = *posptr;
                   5172:        numinterpolations++;
                   5173: }
                   5174: 
                   5175: stopinterpolation(long *posptr)
                   5176: {
                   5177:        long i;
                   5178: 
                   5179:        for(i=numinterpolations-1;i>=startofdynamicinterpolations;i--)
                   5180:                if (curipos[i] == posptr)
                   5181:                {
                   5182:                        numinterpolations--;
                   5183:                        oldipos[i] = oldipos[numinterpolations];
                   5184:                        bakipos[i] = bakipos[numinterpolations];
                   5185:                        curipos[i] = curipos[numinterpolations];
                   5186:                }
                   5187: }
                   5188: 
                   5189: updateinterpolations()  //Stick at beginning of domovethings
                   5190: {
                   5191:        long i;
                   5192: 
                   5193:        for(i=numinterpolations-1;i>=0;i--) oldipos[i] = *curipos[i];
                   5194: }
                   5195: 
                   5196: dointerpolations()       //Stick at beginning of drawscreen
                   5197: {
                   5198:        long i, j, odelta, ndelta;
                   5199: 
                   5200:        ndelta = 0; j = 0;
                   5201:        for(i=numinterpolations-1;i>=0;i--)
                   5202:        {
                   5203:                bakipos[i] = *curipos[i];
                   5204:                odelta = ndelta; ndelta = (*curipos[i])-oldipos[i];
                   5205:                if (odelta != ndelta) j = mulscale16(ndelta,smoothratio);
                   5206:                *curipos[i] = oldipos[i]+j;
                   5207:        }
                   5208: }
                   5209: 
                   5210: restoreinterpolations()  //Stick at end of drawscreen
                   5211: {
                   5212:        long i;
                   5213: 
                   5214:        for(i=numinterpolations-1;i>=0;i--) *curipos[i] = bakipos[i];
                   5215: }
                   5216: 
                   5217: printext(long x, long y, char *buffer, short tilenum, char invisiblecol)
                   5218: {
                   5219:        long i;
                   5220:        char ch;
                   5221: 
                   5222:        for(i=0;buffer[i]!=0;i++)
                   5223:        {
                   5224:                ch = buffer[i];
                   5225:                rotatesprite((x-((8&15)<<3))<<16,(y-((8>>4)<<3))<<16,65536L,0,tilenum,0,0,8+16+64+128,x,y,x+7,y+7);
                   5226:                rotatesprite((x-((ch&15)<<3))<<16,(y-((ch>>4)<<3))<<16,65536L,0,tilenum,0,0,8+16+128,x,y,x+7,y+7);
                   5227:                x += 8;
                   5228:        }
                   5229: }
                   5230: 
                   5231: drawtilebackground (long thex, long they, short tilenum,
                   5232:                                                                  signed char shade, long cx1, long cy1,
                   5233:                                                                  long cx2, long cy2, char dapalnum)
                   5234: {
                   5235:        long x, y, xsiz, ysiz, tx1, ty1, tx2, ty2;
                   5236: 
                   5237:        xsiz = tilesizx[tilenum]; tx1 = cx1/xsiz; tx2 = cx2/xsiz;
                   5238:        ysiz = tilesizy[tilenum]; ty1 = cy1/ysiz; ty2 = cy2/ysiz;
                   5239: 
                   5240:        for(x=tx1;x<=tx2;x++)
                   5241:                for(y=ty1;y<=ty2;y++)
                   5242:                        rotatesprite(x*xsiz<<16,y*ysiz<<16,65536L,0,tilenum,shade,dapalnum,8+16+64+128,cx1,cy1,cx2,cy2);
                   5243: }

unix.superglobalmegacorp.com