code:
//-------------------------------------------------------------------------
/*
Copyright (C) 1996, 2003 - 3D Realms Entertainment
Copyright (C) 2017-2019 Nuke.YKT

This file is part of Duke Nukem 3D version 1.5 - Atomic Edition

Duke Nukem 3D is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

Original Source: 1996 - Todd Replogle
Prepared for public release: 03/21/2003 - Charlie Wiederhold, 3D Realms
*/
//-------------------------------------------------------------------------

#include "types.h"
#include "develop.h"
#include "scriplib.h"
#include "file_lib.h"
#include "gamedefs.h"
#include "keyboard.h"
#include "util_lib.h"
#include "function.h"
#include "control.h"
#include "fx_man.h"
#include "sounds.h"
#include "config.h"
#include "sndcards.h"

#include "duke3d.h"

#include "lava.h"

#ifdef RRRA
#define VERSION "REL 1.0"
#define HEAD   "REDNECK RAMPAGE RIDES AGAIN(tm) "VERSION" - KENTUCKY BOURBON EDITION"
#define HEAD2  "REDNECK RAMPAGE RIDES AGAIN(tm) "VERSION" - KENTUCKY BOURBON EDITION"
#else
#define VERSION "REL 1.01"
#define HEAD   "REDNECK RAMPAGE(tm) "VERSION" - MOONSHINE"
#define HEAD2  "REDNECK RAMPAGE(tm) "VERSION" - MOONSHINE"
#endif

extern char firstdemofile[];
extern int32 numlumps;
extern char debug_on;
extern short inputloc;
extern int recfilep,totalreccnt;
extern char todd[];
extern char trees[];
extern char sixteen[];
extern FILE *frecfilep;

void main(int argc,char **argv)
{
    long i, j, k, l;
    int var_10;
#ifdef RRRA
    int playmve = 1;
#endif

    //copyprotect();

    todd[0] = 'T';
    sixteen[0] = 'D';
    trees[0] = 'I';

#ifdef RRRA
    CONFIG_GetSetupFilename();
    CONFIG_ReadSetup();
    {
        short i;
        char *c;
        i = 1;
        if (argc > 1)
        {
            while (i < argc)
            {
                c = argv[i];
                if (*c == '?')
                {
                    comlinehelp(argv);
                    exit(0);
                }

                if(*c == '/')
                {
                    c++;
                    switch(*c)
                    {
                        case 'n':
                        case 'N':
                            c++;
                            if(*c == 'i' || *c == 'I')
                            {
                                playmve = 0;
                            }
                            break;
                    }
                }
                i++;
            }
        }
    }

    if (CheckParm("MAP") || CheckParm("NET"))
        playmve = 0;
    if (playmve) {
        //sub_DACF0(257);
        //sub_A89C0("REDINT.MVE",argv[0],1);
    }
#else

    initcdrom();
#endif

    setvmode(0x03);

#ifdef RRRA
    printstr(0,0,"                                                                                ",31);
    printstr(40-(strlen(HEAD2)>>1)-3,0,HEAD2,31);

    ud.multimode = 1;
    printstr(0,1,"                    COPYRIGHT XATRIX ENTERTAINMENT 1998                         ",31);

    printstr(0,2,"                REDNECK RAMPAGE RIDES AGAIN VERSION "VERSION"                     ",31);
#else
    printstr(0,0,"                                                                                ",79);
    printstr(40-(strlen(HEAD2)>>1)-3,0,HEAD2,79);

    ud.multimode = 1;
    printstr(0,1,"                    COPYRIGHT XATRIX ENTERTAINMENT 1997                         ",79);

    printstr(0,2,"                      REDNECK RAMPAGE VERSION "VERSION"                          ",79);
#endif

    l = Z_AvailHeap();
    if(l < (3192000-350000))
    {
        puts("\n\nYou don't have enough free memory to run Redneck Rampage.");
#ifndef RRRA
        puts("The DOS \"mem\" command should report 6,800K (or 6.8 megs)");
        puts("'of total memory free'.\n");
        printf("Redneck Rampage requires %ld more bytes to run.\n",3192000-350000-l);
#endif
        exit(0);
    }

    printf("\n\n\n");

    {
        char c, *wd;
        wd = getenv("windir");
        if (wd)
        {
            puts("\n\nRedneck Rampage is not designed to run in a DOS box.");
            puts("\nDouble-click the \"Rampage\" shortcut instead to restart");
            puts("\nyour computer in MS-DOS mode and launch the game.");
            puts("\n");
            printf("Mash yer keyboard to quit\n");
            printf("or press C to continue\n");
            c = getch();
            if(c != 'C' && c != 'c')
                return;
        }
    }

    initgroupfile("redneck.grp");
    checkcommandline(argc, argv);
    RegisterShutdownFunction( Shutdown );

    Startup();

    if( eightytwofifty && numplayers > 1 && (MusicDevice != NumSoundCards) )
    {
        puts("\n=========================================================================");
        puts("WARNING: 8250 UART detected.");
        puts("Music is being disabled and lower quality sound is being set.  We apologize");
        puts("for this, but it is necessary to maintain high frame rates while trying to");
        puts("play the game on an 8250.  We suggest upgrading to a 16550 or better UART");
        puts("for maximum performance.  Press any key to continue.");
        puts("=========================================================================\n");

        while( !KB_KeyWaiting() );
    }

    if(numplayers > 1)
    {
        ud.multimode = numplayers;
        sendlogon();
    }
    else if(boardfilename[0] != 0)
    {
        ud.m_level_number = 7;
        ud.m_volume_number = 0;
        ud.warp_on = 1;
    }

    getnames();

    if(ud.multimode > 1)
    {
        playerswhenstarted = ud.multimode;

        if(ud.warp_on == 0)
        {
            ud.m_monsters_off = 1;
            ud.m_player_skill = 0;
        }
    }

    ud.last_level = -1;

   RTS_Init(ud.rtsname);
   if(numlumps) printf("Using .RTS file:%s\n",ud.rtsname);

   if (CONTROL_JoystickEnabled)
       CONTROL_CenterJoystick
          (
          CenterCenter,
          UpperLeft,
          LowerRight,
          CenterThrottle,
          CenterRudder
          );

    if (ud.warp_on > 1)
    {
        if (numplayers > 1)
        {
            printf("Attemptin' to load multiplayer slot #%ld.\n", ud.warp_on - 2);
            var_10 = loadplayer(-ud.warp_on + 1);
        }
        else
        {
            printf("Attemptin' to load single player slot #%ld.\n", ud.warp_on - 2);
            var_10 = loadplayer(ud.warp_on - 2);
        }
        if (var_10 == -1)
        {
            printf("Error loadin' slot # %ld.\n", ud.warp_on - 2);
            ud.warp_on = 0;
        }
    }

        puts("Loadin' palette/lookups.");

    if( setgamemode(ScreenMode,ScreenWidth,ScreenHeight) < 0 )
    {
        printf("\nVESA driver for ( %ld * %ld ) not found/supported!\n",xdim,ydim);
        vidoption = ScreenMode = 2;
        setgamemode(ScreenMode,ScreenWidth,ScreenHeight);
    }

    genspriteremaps();

#ifdef RRRA
    if (numplayers < 2)
        initcdrom();
#endif

#ifdef VOLUMEONE
        if(numplayers > 4 || ud.multimode > 4)
            gameexit(" The full version of Duke Nukem 3D supports 5 or more players.");
#endif

    setbrightness(ud.brightness>>2,&ps[myconnectindex].palette[0]);

    ESCESCAPE;

//    getpackets();

    MAIN_LOOP_RESTART:

    FX_StopAllSounds();
    clearsoundlocks();

#ifndef RRRA
    if(ud.warp_on == 0)
        Logo();
    else
#endif
        if(ud.warp_on == 1)
    {
        newgame(ud.m_volume_number,ud.m_level_number,ud.m_player_skill);
        enterlevel(MODE_GAME);
    }
    else vscrn();

    if( ud.warp_on == 0 && playback() )
    {
        goto MAIN_LOOP_RESTART;
    }

    ud.warp_on = 0;

    if (waitabort)
    {
        goto MAIN_LOOP_RESTART;
    }

    while ( !(ps[myconnectindex].gm&MODE_END) ) //The whole loop!!!!!!!!!!!!!!!!!!
    {
        if( ud.recstat == 2 || ud.multimode > 1 || ( ud.show_help == 0 && (ps[myconnectindex].gm&MODE_MENU) != MODE_MENU ) )
            if( ps[myconnectindex].gm&MODE_GAME )
                if( moveloop() ) continue;

        if( ps[myconnectindex].gm&MODE_EOL || ps[myconnectindex].gm&MODE_RESTART )
        {
            if( ps[myconnectindex].gm&MODE_EOL )
            {
                closedemowrite();

                ready2send = 0;

                i = ud.screen_size;
                ud.screen_size = 0;
                vscrn();
                ud.screen_size = i;
#ifdef RRRA
                if (playerswhenstarted > 1 && numplayers > 1)
                    dobonus(0);
                else
                    dobonus2(0);
#else
                dobonus(0);
#endif

                if(ud.eog)
                {
                    ud.eog = 0;
                    if(ud.multimode < 2)
                    {
                        ps[myconnectindex].gm = MODE_MENU;
                        cmenu(0);
                        probey = 0;
                        goto MAIN_LOOP_RESTART;
                    }
                    else
                    {
                        ud.m_level_number = 0;
                        ud.level_number = 0;
                    }
                }
            }

            if(numplayers > 1) ps[myconnectindex].gm = MODE_GAME;
            enterlevel(ps[myconnectindex].gm);
            continue;
        }

        cheats();
        nonsharedkeys();

        if( (ud.show_help == 0 && ud.multimode < 2 && !(ps[myconnectindex].gm&MODE_MENU) ) || ud.multimode > 1 || ud.recstat == 2)
            i = min(max((totalclock-ototalclock)*(65536L/TICSPERFRAME),0),65536);
        else
            i = 65536;

        if(ud.multimode < 2)
            if(torchcnt)
            dotorch();

        displayrooms(screenpeek,i);
        displayrest(i);

//        if( KB_KeyPressed(sc_F) )
//        {
//            KB_ClearKeyDown(sc_F);
//            addplayer();
//        }

        if(ps[myconnectindex].gm&MODE_DEMO)
            goto MAIN_LOOP_RESTART;

        if(debug_on) caches();

        checksync();
        nextpage();
    }

    gameexit(" ");
}

char opendemoread(char which_demo) // 0 = mine
{
    char *d = "demo_.dmo";
    char ver;
    short i;

    if(which_demo == 10)
        d[4] = 'x';
    else
        d[4] = '0' + which_demo;

     if(which_demo == 1 && firstdemofile[0] != 0)
     {
       if ((recfilep = kopen4load(firstdemofile,loadfromgrouponly)) == -1) return(0);
     }
     else
       if ((recfilep = kopen4load(d,loadfromgrouponly)) == -1) return(0);

     kread(recfilep,&ud.reccnt,sizeof(long));
     kread(recfilep,&ver,sizeof(char));
     if( (ver != BYTEVERSION) || (ud.reccnt < 1024) )
     {
        kclose(recfilep);
        return 0;
     }
         kread(recfilep,(char *)&ud.volume_number,sizeof(char));
         kread(recfilep,(char *)&ud.level_number,sizeof(char));
         kread(recfilep,(char *)&ud.player_skill,sizeof(char));
     kread(recfilep,(char *)&ud.m_coop,sizeof(char));
     kread(recfilep,(char *)&ud.m_ffire,sizeof(char));
     kread(recfilep,(short *)&ud.multimode,sizeof(short));
     kread(recfilep,(short *)&ud.m_monsters_off,sizeof(short));
     kread(recfilep,(int32 *)&ud.m_respawn_monsters,sizeof(int32));
     kread(recfilep,(int32 *)&ud.m_respawn_items,sizeof(int32));
     kread(recfilep,(int32 *)&ud.m_respawn_inventory,sizeof(int32));
     kread(recfilep,(int32 *)&ud.playerai,sizeof(int32));
     kread(recfilep,(char *)&ud.user_name[0][0],sizeof(ud.user_name),1);

     for(i=0;i<ud.multimode;i++)
        kread(recfilep,(char *)&ps[i].aim_mode,sizeof(char),1);
     ud.god = ud.cashman = ud.eog = ud.showallmap = 0;
     ud.clipping = ud.scrollmode = ud.overhead_on = 0;
     ud.showweapons =  ud.pause_on = ud.auto_run = 0;

         newgame(ud.volume_number,ud.level_number,ud.player_skill);
         return(1);
}

void opendemowrite(void)
{
    char *d = "demo1.dmo";
    long dummylong = 0;
    char ver;
    short i;

    if(ud.recstat == 2) kclose(recfilep);

    ver = BYTEVERSION;

    if ((frecfilep = fopen(d,"wb")) == NULL) return;
    fwrite(&dummylong,4,1,frecfilep);
    fwrite(&ver,sizeof(char),1,frecfilep);
    fwrite((char *)&ud.volume_number,sizeof(char),1,frecfilep);
    fwrite((char *)&ud.level_number,sizeof(char),1,frecfilep);
    fwrite((char *)&ud.player_skill,sizeof(char),1,frecfilep);
    fwrite((char *)&ud.m_coop,sizeof(char),1,frecfilep);
    fwrite((char *)&ud.m_ffire,sizeof(char),1,frecfilep);
    fwrite((short *)&ud.multimode,sizeof(short),1,frecfilep);
    fwrite((short *)&ud.m_monsters_off,sizeof(short),1,frecfilep);
    fwrite((int32 *)&ud.m_respawn_monsters,sizeof(int32),1,frecfilep);
    fwrite((int32 *)&ud.m_respawn_items,sizeof(int32),1,frecfilep);
    fwrite((int32 *)&ud.m_respawn_inventory,sizeof(int32),1,frecfilep);
    fwrite((int32 *)&ud.playerai,sizeof(int32),1,frecfilep);
    fwrite((char *)&ud.user_name[0][0],sizeof(ud.user_name),1,frecfilep);

    for(i=0;i<ud.multimode;i++)
        fwrite((char *)&ps[i].aim_mode,sizeof(char),1,frecfilep);

    totalreccnt = 0;
    ud.reccnt = 0;
}

void record(void)
{
    short i;

    for(i=connecthead;i>=0;i=connectpoint2[i])
         {
         copybufbyte(&sync[i],&recsync[ud.reccnt],sizeof(input));
                 ud.reccnt++;
                 totalreccnt++;
                 if (ud.reccnt >= RECSYNCBUFSIZ)
                 {
              dfwrite(recsync,sizeof(input)*ud.multimode,ud.reccnt/ud.multimode,frecfilep);
                          ud.reccnt = 0;
                 }
         }
}

void closedemowrite(void)
{
         if (ud.recstat == 1)
         {
        if (ud.reccnt > 0)
        {
            dfwrite(recsync,sizeof(input)*ud.multimode,ud.reccnt/ud.multimode,frecfilep);
        }

        fseek(frecfilep,SEEK_SET,0L);
        fwrite(&totalreccnt,sizeof(long),1,frecfilep);
        ud.recstat = ud.m_recstat = 0;
        fclose(frecfilep);
    }
}

char which_demo = 1;

char in_menu = 0;

// extern long syncs[];
long playback(void)
{
    long i,j,k,l,t;
    short p;
    char foundemo;

    if( ready2send ) return 0;

    foundemo = 0;

    RECHECK:

    in_menu = ps[myconnectindex].gm&MODE_MENU;

    pub = NUMPAGES;
    pus = NUMPAGES;

    flushperms();

    if(numplayers < 2) foundemo = opendemoread(which_demo);

    if(foundemo == 0)
    {
        if(which_demo > 1)
        {
            which_demo = 1;
            goto RECHECK;
        }
        for(t=0;t<63;t+=7) palto(0,0,0,t);
        drawbackground();
        menus();
        ps[myconnectindex].palette = palette;
        nextpage();
        for(t=63;t>0;t-=7) palto(0,0,0,t);
        ud.reccnt = 0;
    }
    else
    {
        ud.recstat = 2;
        which_demo++;
        if(which_demo == 10) which_demo = 1;
        enterlevel(MODE_DEMO);
    }

    if(foundemo == 0 || in_menu || KB_KeyWaiting() || ud.multimode > 1)
    {
        FX_StopAllSounds();
        clearsoundlocks();
        ps[myconnectindex].gm |= MODE_MENU;
    }

    ready2send = 0;
    i = 0;

    KB_FlushKeyboardQueue();

    k = 0;

    while (ud.reccnt > 0 || foundemo == 0)
    {
        if(foundemo) while ( totalclock >= (lockclock+TICSPERFRAME) )
        {
            if ((i == 0) || (i >= RECSYNCBUFSIZ))
            {
                i = 0;
                l = min(ud.reccnt,RECSYNCBUFSIZ);
                kdfread(recsync,sizeof(input)*ud.multimode,l/ud.multimode,recfilep);
            }

            for(j=connecthead;j>=0;j=connectpoint2[j])
            {
               copybufbyte(&recsync[i],&inputfifo[movefifoend[j]&(MOVEFIFOSIZ-1)][j],sizeof(input));
               movefifoend[j]++;
               i++;
               ud.reccnt--;
            }
            domovethings();
        }

        if(foundemo == 0)
            drawbackground();
        else
        {
            nonsharedkeys();

            j = min(max((totalclock-lockclock)*(65536/TICSPERFRAME),0),65536);
            displayrooms(screenpeek,j);
            displayrest(j);

            if(ud.multimode > 1 && ps[myconnectindex].gm )
                getpackets();
        }

        if( (ps[myconnectindex].gm&MODE_MENU) && (ps[myconnectindex].gm&MODE_EOL) )
            goto RECHECK;

        if (KB_KeyPressed(sc_Escape))
        {
            KB_ClearKeyDown(sc_Escape);
            FX_StopAllSounds();
            clearsoundlocks();
            ps[myconnectindex].gm |= MODE_MENU;
            cmenu(0);
            intomenusounds();
        }

        if(ps[myconnectindex].gm&MODE_TYPE)
        {
            typemode();
            if((ps[myconnectindex].gm&MODE_TYPE) != MODE_TYPE)
                ps[myconnectindex].gm = MODE_MENU;
        }
        else
        {
            menus();
            if( ud.multimode > 1 )
            {
                ControlInfo noshareinfo;
                CONTROL_GetInput( &noshareinfo );
                if( BUTTON(gamefunc_SendMessage) )
                {
                    KB_FlushKeyboardQueue();
                    CONTROL_ClearButton( gamefunc_SendMessage );
                    ps[myconnectindex].gm = MODE_TYPE;
                    typebuf[0] = 0;
                    inputloc = 0;
                }
            }
        }

        operatefta();

        if(ud.last_camsprite != ud.camerasprite)
        {
            ud.last_camsprite = ud.camerasprite;
            ud.camera_time = totalclock+(TICRATE*2);
        }

        getpackets();
        nextpage();

        if( ps[myconnectindex].gm==MODE_END || ps[myconnectindex].gm==MODE_GAME )
        {
            kclose(recfilep);
            return 0;
        }
    }
    kclose(recfilep);
    if(ps[myconnectindex].gm&MODE_MENU) goto RECHECK;
    return 1;
}

char moveloop()
{
    long i;

    if (numplayers > 1)
        while (fakemovefifoplc < movefifoend[myconnectindex]) fakedomovethings();

    getpackets();

    if (numplayers < 2) bufferjitter = 0;
    while (movefifoend[myconnectindex]-movefifoplc > bufferjitter)
    {
        for(i=connecthead;i>=0;i=connectpoint2[i])
            if (movefifoplc == movefifoend[i]) break;
        if (i >= 0) break;
        if( domovethings() ) return 1;
    }
    return 0;
}

void fakedomovethingscorrect(void)
{
     long i;
     struct player_struct *p;

     if (numplayers < 2) return;

     i = ((movefifoplc-1)&(MOVEFIFOSIZ-1));
     p = &ps[myconnectindex];

     if (p->posx == myxbak[i] && p->posy == myybak[i] && p->posz == myzbak[i]
          && p->horiz == myhorizbak[i] && p->ang == myangbak[i]) return;

     myx = p->posx; omyx = p->oposx; myxvel = p->posxv;
     myy = p->posy; omyy = p->oposy; myyvel = p->posyv;
     myz = p->posz; omyz = p->oposz; myzvel = p->poszv;
     myang = p->ang; omyang = p->oang;
     mycursectnum = p->cursectnum;
     myhoriz = p->horiz; omyhoriz = p->ohoriz;
     myhorizoff = p->horizoff; omyhorizoff = p->ohorizoff;
     myjumpingcounter = p->jumping_counter;
     myjumpingtoggle = p->jumping_toggle;
     myonground = p->on_ground;
     myhardlanding = p->hard_landing;
     myreturntocenter = p->return_to_center;

     fakemovefifoplc = movefifoplc;
     while (fakemovefifoplc < movefifoend[myconnectindex])
          fakedomovethings();

}

void fakedomovethings(void)
{
        input *syn;
        struct player_struct *p;
        long i, j, k, doubvel, fz, cz, hz, lz, x, y;
        unsigned long sb_snum;
        short psect, psectlotag, tempsect, backcstat;
        char shrunk, spritebridge;

        syn = (input *)&inputfifo[fakemovefifoplc&(MOVEFIFOSIZ-1)][myconnectindex];

        p = &ps[myconnectindex];

        backcstat = sprite[p->i].cstat;
        sprite[p->i].cstat &= ~257;

        sb_snum = syn->bits;

        psect = mycursectnum;
        psectlotag = sector[psect].lotag;
        spritebridge = 0;

        shrunk = (sprite[p->i].yrepeat < 8);

        if( ud.clipping == 0 && ( sector[psect].floorpicnum == MIRROR || psect < 0 || psect >= MAXSECTORS) )
        {
            myx = omyx;
            myy = omyy;
        }
        else
        {
            omyx = myx;
            omyy = myy;
        }

        omyhoriz = myhoriz;
        omyhorizoff = myhorizoff;
        omyz = myz;
        omyang = myang;

        getzrange(myx,myy,myz,psect,&cz,&hz,&fz,&lz,163L,CLIPMASK0);

        j = getflorzofslope(psect,myx,myy);

        if( (lz&49152) == 16384 && psectlotag == 1 && klabs(myz-j) > PHEIGHT+(16<<8) )
            psectlotag = 0;

        if( p->aim_mode == 0 && myonground && psectlotag != 2 && (sector[psect].floorstat&2) )
        {
                x = myx+(sintable[(myang+512)&2047]>>5);
                y = myy+(sintable[myang&2047]>>5);
                tempsect = psect;
                updatesector(x,y,&tempsect);
                if (tempsect >= 0)
                {
                     k = getflorzofslope(psect,x,y);
                     if (psect == tempsect)
                          myhorizoff += mulscale16(j-k,160);
                     else if (klabs(getflorzofslope(tempsect,x,y)-k) <= (4<<8))
                          myhorizoff += mulscale16(j-k,160);
                }
        }
        if (myhorizoff > 0) myhorizoff -= ((myhorizoff>>3)+1);
        else if (myhorizoff < 0) myhorizoff += (((-myhorizoff)>>3)+1);

        if(hz >= 0 && (hz&49152) == 49152)
        {
                hz &= (MAXSPRITES-1);
                if (sprite[hz].statnum == 1 && sprite[hz].extra >= 0)
                {
                    hz = 0;
                    cz = getceilzofslope(psect,myx,myy);
                }
        }

        if(lz >= 0 && (lz&49152) == 49152)
        {
                 j = lz&(MAXSPRITES-1);
                 if ((sprite[j].cstat&33) == 33)
                 {
                        psectlotag = 0;
                        spritebridge = 1;
                 }
                 if(badguy(&sprite[j]) && sprite[j].xrepeat > 24 && klabs(sprite[p->i].z-sprite[j].z) < (84<<8) )
                 {
                    j = getangle( sprite[j].x-myx,sprite[j].y-myy);
                    myxvel -= sintable[(j+512)&2047]<<4;
                    myyvel -= sintable[j&2047]<<4;
                }
        }

        if( sprite[p->i].extra <= 0 )
        {
                 if( psectlotag == 2 )
                 {
                            if(p->on_warping_sector == 0)
                            {
                                     if( klabs(myz-fz) > (PHEIGHT>>1))
                                             myz += 348;
                            }
                            clipmove(&myx,&myy,&myz,&mycursectnum,0,0,164L,(4L<<8),(4L<<8),CLIPMASK0);
                 }

                 updatesector(myx,myy,&mycursectnum);
                 pushmove(&myx,&myy,&myz,&mycursectnum,128L,(4L<<8),(20L<<8),CLIPMASK0);

                myhoriz = 100;
                myhorizoff = 0;

                 goto ENDFAKEPROCESSINPUT;
        }

        doubvel = TICSPERFRAME;

        if(p->on_crane >= 0) goto FAKEHORIZONLY;

        if(p->one_eighty_count < 0) myang += 128;

        i = 40;

        if( psectlotag == 2)
        {
                 myjumpingcounter = 0;

#ifdef RRRA
                 if ( (sb_snum&1) && !(p->OnMotorcycle || p->OnBoat) )
#else
                 if ( sb_snum&1 )
#endif
                 {
                            if(myzvel > 0) myzvel = 0;
                            myzvel -= 348;
                            if(myzvel < -(256*6)) myzvel = -(256*6);
                 }
#ifdef RRRA
                 else if ( (sb_snum&(1<<1)) && !(p->OnMotorcycle || p->OnBoat) )
#else
                 else if (sb_snum&(1<<1))
#endif
                 {
                            if(myzvel < 0) myzvel = 0;
                            myzvel += 348;
                            if(myzvel > (256*6)) myzvel = (256*6);
                 }
                 else
                 {
                    if(myzvel < 0)
                    {
                        myzvel += 256;
                        if(myzvel > 0)
                            myzvel = 0;
                    }
                    if(myzvel > 0)
                    {
                        myzvel -= 256;
                        if(myzvel < 0)
                            myzvel = 0;
                    }
                }

                if(myzvel > 2048) myzvel >>= 1;

                 myz += myzvel;

                 if(myz > (fz-(15<<8)) )
                            myz += ((fz-(15<<8))-myz)>>1;

                 if(myz < (cz+(4<<8)) )
                 {
                            myz = cz+(4<<8);
                            myzvel = 0;
                 }
        }

        else if(p->jetpack_on)
        {
                 myonground = 0;
                 myjumpingcounter = 0;
                 myhardlanding = 0;

                 if(p->jetpack_on < 11)
                            myz -= (p->jetpack_on<<7); //Goin up

                 if(shrunk) j = 512;
                 else j = 2048;

#ifdef RRRA
                 if ((sb_snum&1) && !(p->OnMotorcycle || p->OnBoat))
#else
                 if (sb_snum&1)                            //A
#endif
                            myz -= j;
#ifdef RRRA
                 if ((sb_snum&(1<<1)) && !(p->OnMotorcycle || p->OnBoat))
#else
                 if (sb_snum&(1<<1))                       //Z
#endif
                            myz += j;

                 if(shrunk == 0 && ( psectlotag == 0 || psectlotag == 2 ) ) k = 32;
                 else k = 16;

                 if(myz > (fz-(k<<8)) )
                            myz += ((fz-(k<<8))-myz)>>1;
                 if(myz < (cz+(18<<8)) )
                            myz = cz+(18<<8);
        }
        else if( psectlotag != 2 )
        {
            if (psectlotag == 1 && p->spritebridge == 0)
            {
                 if(shrunk == 0) i = 34;
                 else i = 12;
            }
                 if(myz < (fz-(i<<8)) && (floorspace(psect)|ceilingspace(psect)) == 0 ) //falling
                 {
#ifdef RRRA
                            if( (sb_snum&3) == 0 && !(p->OnMotorcycle || p->OnBoat) && myonground && (sector[psect].floorstat&2) && myz >= (fz-(i<<8)-(16<<8) ) )
#else
                            if( (sb_snum&3) == 0 && myonground && (sector[psect].floorstat&2) && myz >= (fz-(i<<8)-(16<<8) ) )
#endif
                                     myz = fz-(i<<8);
                            else
                            {
                                     myonground = 0;

                                     myzvel += (gc+80);

                                     if(myzvel >= (4096+2048)) myzvel = (4096+2048);
                            }
                 }

                 else
                 {
                            if(psectlotag != 1 && psectlotag != 2 && myonground == 0 && myzvel > (6144>>1))
                                 myhardlanding = myzvel>>10;
                            myonground = 1;

                            if(i==40)
                            {
                                     //Smooth on the ground

                                     k = ((fz-(i<<8))-myz)>>1;
                                     if( klabs(k) < 256 ) k = 0;
                                     myz += k; // ((fz-(i<<8))-myz)>>1;
                                     myzvel -= 768; // 412;
                                     if(myzvel < 0) myzvel = 0;
                            }
                            else if(myjumpingcounter == 0)
                            {
                                myz += ((fz-(i<<7))-myz)>>1; //Smooth on the water
                                if(p->on_warping_sector == 0 && myz > fz-(16<<8))
                                {
                                    myz = fz-(16<<8);
                                    myzvel >>= 1;
                                }
                            }

#ifdef RRRA
                            if( (sb_snum&2) && !(p->OnMotorcycle || p->OnBoat) )
#else
                            if( sb_snum&2 )
#endif
                                     myz += (2048+768);

#ifdef RRRA
                            if( (sb_snum&1) == 0 && !(p->OnMotorcycle || p->OnBoat) && myjumpingtoggle == 1)
#else
                            if( (sb_snum&1) == 0 && myjumpingtoggle == 1)
#endif
                                     myjumpingtoggle = 0;

#ifdef RRRA
                            else if( (sb_snum&1) && !(p->OnMotorcycle || p->OnBoat) && myjumpingtoggle == 0 )
#else
                            else if( (sb_snum&1) && myjumpingtoggle == 0 )
#endif
                            {
                                     if( myjumpingcounter == 0 )
                                             if( (fz-cz) > (56<<8) )
                                             {
                                                myjumpingcounter = 1;
                                                myjumpingtoggle = 1;
                                             }
                            }
                 }

                 if(myjumpingcounter)
                 {
#ifdef RRRA
                            if( (sb_snum&1) == 0 && !(p->OnMotorcycle || p->OnBoat) && myjumpingtoggle == 1)
#else
                            if( (sb_snum&1) == 0 && myjumpingtoggle == 1)
#endif
                                     myjumpingtoggle = 0;

                            if( myjumpingcounter < (1024+256) )
                            {
                                     if(psectlotag == 1 && myjumpingcounter > 768)
                                     {
                                             myjumpingcounter = 0;
                                             myzvel = -512;
                                     }
                                     else
                                     {
                                             myzvel -= (sintable[(2048-128+myjumpingcounter)&2047])/12;
                                             myjumpingcounter += 180;

                                             myonground = 0;
                                     }
                            }
                            else
                            {
                                     myjumpingcounter = 0;
                                     myzvel = 0;
                            }
                 }

                 myz += myzvel;

                 if(myz < (cz+(4<<8)) )
                 {
                            myjumpingcounter = 0;
                            if(myzvel < 0) myxvel = myyvel = 0;
                            myzvel = 128;
                            myz = cz+(4<<8);
                 }

        }

        if ( p->fist_incs ||
                     p->transporter_hold > 2 ||
                     myhardlanding ||
                     p->access_incs > 0 ||
                     p->knee_incs > 0 ||
                     (p->curr_weapon == TRIPBOMB_WEAPON &&
                      p->kickback_pic > 1 &&
                      p->kickback_pic < 4 ) )
        {
                 doubvel = 0;
                 myxvel = 0;
                 myyvel = 0;
        }
        else if ( syn->avel )          //p->ang += syncangvel * constant
        {                         //ENGINE calculates angvel for you
            long tempang;

            tempang = syn->avel<<1;

            if(psectlotag == 2)
                myang += (tempang-(tempang>>3))*sgn(doubvel);
            else myang += (tempang)*sgn(doubvel);
            myang &= 2047;
        }

        if ( myxvel || myyvel || syn->fvel || syn->svel )
        {
                 if(p->steroids_amount > 0 && p->steroids_amount < 400)
                     doubvel <<= 1;

                 myxvel += ((syn->fvel*doubvel)<<6);
                 myyvel += ((syn->svel*doubvel)<<6);

#ifdef RRRA
                 if( ( p->curr_weapon == KNEE_WEAPON && p->kickback_pic > 10 && myonground ) || ( myonground && (sb_snum&2) && !(p->OnMotorcycle || p->OnBoat)) )
#else
                 if( ( p->curr_weapon == KNEE_WEAPON && p->kickback_pic > 10 && myonground ) || ( myonground && (sb_snum&2) ) )
#endif
                 {
                            myxvel = mulscale16(myxvel,rdnkfriction-0x2000);
                            myyvel = mulscale16(myyvel,rdnkfriction-0x2000);
                 }
                 else
                 {
                    if(psectlotag == 2)
                    {
                        myxvel = mulscale16(myxvel,rdnkfriction-0x1400);
                        myyvel = mulscale16(myyvel,rdnkfriction-0x1400);
                    }
                    else
                    {
                        myxvel = mulscale16(myxvel,rdnkfriction);
                        myyvel = mulscale16(myyvel,rdnkfriction);
                    }
                 }

                 if( abs(myxvel) < 2048 && abs(myyvel) < 2048 )
                     myxvel = myyvel = 0;

                 if( shrunk )
                 {
                     myxvel =
                         mulscale16(myxvel,(rdnkfriction)-(rdnkfriction>>1)+(rdnkfriction>>2));
                     myyvel =
                         mulscale16(myyvel,(rdnkfriction)-(rdnkfriction>>1)+(rdnkfriction>>2));
                 }
        }

FAKEHORIZONLY:
        if(psectlotag == 1 || spritebridge == 1) i = (4L<<8); else i = (20L<<8);

        clipmove(&myx,&myy,&myz,&mycursectnum,myxvel,myyvel,164L,4L<<8,i,CLIPMASK0);
        pushmove(&myx,&myy,&myz,&mycursectnum,164L,4L<<8,4L<<8,CLIPMASK0);

        if( p->jetpack_on == 0 && psectlotag != 1 && psectlotag != 2 && shrunk)
            myz += 30<<8;

        if ((sb_snum&(1<<18)) || myhardlanding)
            myreturntocenter = 9;

        if (sb_snum&(1<<13))
        {
                myreturntocenter = 9;
                if (sb_snum&(1<<5)) myhoriz += 6;
                myhoriz += 6;
        }
        else if (sb_snum&(1<<14))
        {
                myreturntocenter = 9;
                if (sb_snum&(1<<5)) myhoriz -= 6;
                myhoriz -= 6;
        }
#ifdef RRRA
        else if ((sb_snum&(1<<3)) && !(p->OnMotorcycle || p->OnBoat))
#else
        else if (sb_snum&(1<<3))
#endif
        {
                if (sb_snum&(1<<5)) myhoriz += 6;
                myhoriz += 6;
        }
#ifdef RRRA
        else if ((sb_snum&(1<<4)) && !(p->OnMotorcycle || p->OnBoat))
#else
        else if (sb_snum&(1<<4))
#endif
        {
                if (sb_snum&(1<<5)) myhoriz -= 6;
                myhoriz -= 6;
        }

        if (myreturntocenter > 0)
            if ((sb_snum&(1<<13)) == 0 && (sb_snum&(1<<14)) == 0)
        {
             myreturntocenter--;
             myhoriz += 33-(myhoriz/3);
        }

        if(p->aim_mode)
            myhoriz += syn->horz>>1;
        else
        {
            if( myhoriz > 95 && myhoriz < 105) myhoriz = 100;
            if( myhorizoff > -5 && myhorizoff < 5) myhorizoff = 0;
        }

        if (myhardlanding > 0)
        {
            myhardlanding--;
            myhoriz -= (myhardlanding<<4);
        }

        if (myhoriz > 299) myhoriz = 299;
        else if (myhoriz < -99) myhoriz = -99;

        if(p->knee_incs > 0)
        {
            myhoriz -= 48;
            myreturntocenter = 9;
        }

ENDFAKEPROCESSINPUT:

        myxbak[fakemovefifoplc&(MOVEFIFOSIZ-1)] = myx;
        myybak[fakemovefifoplc&(MOVEFIFOSIZ-1)] = myy;
        myzbak[fakemovefifoplc&(MOVEFIFOSIZ-1)] = myz;
        myangbak[fakemovefifoplc&(MOVEFIFOSIZ-1)] = myang;
        myhorizbak[fakemovefifoplc&(MOVEFIFOSIZ-1)] = myhoriz;
        fakemovefifoplc++;

        sprite[p->i].cstat = backcstat;
}


code:
//-------------------------------------------------------------------------
/*
Copyright (C) 1996, 2003 - 3D Realms Entertainment
Copyright (C) 2017-2019 Nuke.YKT

This file is part of Duke Nukem 3D version 1.5 - Atomic Edition

Duke Nukem 3D is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

Original Source: 1996 - Todd Replogle
Prepared for public release: 03/21/2003 - Charlie Wiederhold, 3D Realms
*/
//-------------------------------------------------------------------------

#include "types.h"
#include "develop.h"
#include "scriplib.h"
#include "file_lib.h"
#include "gamedefs.h"
#include "keyboard.h"
#include "util_lib.h"
#include "function.h"
#include "control.h"
#include "fx_man.h"
#include "sounds.h"
#include "config.h"
#include "sndcards.h"

#include "duke3d.h"

char everyothertime;
short vixenlevel = 0;
char domovethings(void)
{
    short i, j;
    char ch;

    for(i=connecthead;i>=0;i=connectpoint2[i])
        if( sync[i].bits&(1<<17) )
    {
        multiflag = 2;
        multiwhat = (sync[i].bits>>18)&1;
        multipos = (unsigned) (sync[i].bits>>19)&15;
        multiwho = i;

        if( multiwhat )
        {
            saveplayer( multipos );
            multiflag = 0;

            if(multiwho != myconnectindex)
            {
                strcpy(&fta_quotes[122],&ud.user_name[multiwho][0]);
                strcat(&fta_quotes[122]," SAVED A MULTIPLAYER GAME");
                FTA(122,&ps[myconnectindex]);
            }
            else
            {
                strcpy(&fta_quotes[122],"MULTIPLAYER GAME SAVED");
                FTA(122,&ps[myconnectindex]);
            }
            break;
        }
        else
        {
//            waitforeverybody();

            loadplayer( multipos );

            multiflag = 0;

            return 1;
        }
    }

    ud.camerasprite = -1;
    lockclock += TICSPERFRAME;

    if(earthquaketime > 0) earthquaketime--;
    if(user_quote_time > 0) user_quote_time--;
    if(rtsplaying > 0) rtsplaying--;

    if( show_shareware > 0 )
    {
        show_shareware--;
        if(show_shareware == 0)
        {
            pus = NUMPAGES;
            pub = NUMPAGES;
        }
    }

    everyothertime++;

    for(i=connecthead;i>=0;i=connectpoint2[i])
        copybufbyte(&inputfifo[movefifoplc&(MOVEFIFOSIZ-1)][i],&sync[i],sizeof(input));
    movefifoplc++;

    updateinterpolations();

    j = -1;
    for(i=connecthead;i>=0;i=connectpoint2[i])
     {
          if ((sync[i].bits&(1<<26)) == 0) { j = i; continue; }

          if (i == myconnectindex) gameexit(" ");
          if (screenpeek == i)
          {
                screenpeek = connectpoint2[i];
                if (screenpeek < 0) screenpeek = connecthead;
          }

          if (i == connecthead) connecthead = connectpoint2[connecthead];
          else connectpoint2[j] = connectpoint2[i];

          numplayers--;
          ud.multimode--;

          closedemowrite();

          pub = NUMPAGES;
          pus = NUMPAGES;
          vscrn();

          sprintf(buf,"%s is history!",ud.user_name[i]);

          quickkill(&ps[i]);
          deletesprite(ps[i].i);

          user_quote = buf;
          user_quote_time = 160;

          if(j < 0 && networkmode == 0 )
              gameexit( " \nThe 'MASTER/First player' just bit the bullet.  All\nplayers are returned from the game. This only happens in 5-8\nplayer mode as a different network scheme is used.");
      }

      if ((numplayers >= 2) && ((movefifoplc&7) == 7))
      {
            ch = (char)(randomseed&255);
            for(i=connecthead;i>=0;i=connectpoint2[i])
                 ch += ((ps[i].posx+ps[i].posy+ps[i].posz+ps[i].ang+ps[i].horiz)&255);
            syncval[myconnectindex][syncvalhead[myconnectindex]&(MOVEFIFOSIZ-1)] = ch;
            syncvalhead[myconnectindex]++;
      }

    if(ud.recstat == 1) record();

    if( ud.pause_on == 0 )
    {
        global_random = TRAND;
        movedummyplayers();//ST 13
    }

    for(i=connecthead;i>=0;i=connectpoint2[i])
    {
        cheatkeys(i);

        if( ud.pause_on == 0 )
        {
            processinput(i);
            checksectors(i);
        }
    }

    if( ud.pause_on == 0 )
    {
        movefta();//ST 2
        moveweapons();          //ST 5 (must be last)
        movetransports();       //ST 9

        moveplayers();          //ST 10
        movefallers();          //ST 12
        moveexplosions();       //ST 4

        moveactors();           //ST 1
        moveeffectors();        //ST 3

        movestandables();       //ST 6
        doanimations();
        movefx();               //ST 11

        if(numplayers < 2 && thunderon)
            thunder();
    }

    fakedomovethingscorrect();

    if( (everyothertime&1) == 0)
    {
        animatewalls();
        movecyclers();
        pan3dsound();
    }

    return 0;
}

void doorders(void)
{
    short i;

    setview(0,0,xdim-1,ydim-1);

    for(i=0;i<63;i+=7) palto(0,0,0,i);
    ps[myconnectindex].palette = palette;
    totalclock = 0;
    KB_FlushKeyboardQueue();
    rotatesprite(0,0,65536L,0,ORDERING,0,0,2+8+16+64, 0,0,xdim-1,ydim-1);
    nextpage(); for(i=63;i>0;i-=7) palto(0,0,0,i);
    totalclock = 0;while( !KB_KeyWaiting() ) getpackets();

    for(i=0;i<63;i+=7) palto(0,0,0,i);
    totalclock = 0;
    KB_FlushKeyboardQueue();
    rotatesprite(0,0,65536L,0,ORDERING+1,0,0,2+8+16+64, 0,0,xdim-1,ydim-1);
    nextpage(); for(i=63;i>0;i-=7) palto(0,0,0,i);
    totalclock = 0;while( !KB_KeyWaiting() ) getpackets();

    for(i=0;i<63;i+=7) palto(0,0,0,i);
    totalclock = 0;
    KB_FlushKeyboardQueue();
    rotatesprite(0,0,65536L,0,ORDERING+2,0,0,2+8+16+64, 0,0,xdim-1,ydim-1);
    nextpage(); for(i=63;i>0;i-=7) palto(0,0,0,i);
    totalclock = 0;while( !KB_KeyWaiting() ) getpackets();

    for(i=0;i<63;i+=7) palto(0,0,0,i);
    totalclock = 0;
    KB_FlushKeyboardQueue();
    rotatesprite(0,0,65536L,0,ORDERING+3,0,0,2+8+16+64, 0,0,xdim-1,ydim-1);
    nextpage(); for(i=63;i>0;i-=7) palto(0,0,0,i);
    totalclock = 0;while( !KB_KeyWaiting() ) getpackets();
}

#ifdef RRRA
void dobonus2(char bonusonly)
{
    short t, r, tinc,gfx_offset,bg_tile;
    long i, y,xfragtotal,yfragtotal,var24;
    short bonuscnt;

    var24 = 0;
    bonuscnt = 0;

    for(t=0;t<64;t++) palto(0,0,0,t);
    setview(0,0,xdim-1,ydim-1);
    clearview(0L);
    nextpage();
    flushperms();

    FX_StopAllSounds();
    clearsoundlocks();
    FX_SetReverb(0L);

    if (boardfilename[0] == 0 && numplayers < 2)
    {
        if ((ud.eog == 0 || ud.volume_number != 1) && ud.volume_number <= 1)
        {
            var24 = 1;
            MUSIC_StopSong();
            KB_FlushKeyboardQueue();
            ShowMapFrame();
        }
    }

    if(bonusonly) goto FRAGBONUS;

    FRAGBONUS:

    ps[myconnectindex].palette = palette;
    KB_FlushKeyboardQueue();
    totalclock = 0; tinc = 0;
    bonuscnt = 0;

    MUSIC_StopSong();

    if(playerswhenstarted > 1 && ud.coop != 1 )
    {
        if(!(MusicToggle == 0 || MusicDevice == NumSoundCards))
            sound(249);

        rotatesprite(0,0,65536L,0,MENUSCREEN,16,0,2+8+16+64+128,0,0,xdim-1,ydim-1);
        rotatesprite(160<<16,57<<16,16592L,0,THREEDEE,0,0,2+8,0,0,xdim-1,ydim-1);
        gametext(160,58,"MULTIPLAYER TOTALS",0);
        gametext(160,58+10,level_names[(ud.volume_number*7)+ud.last_level-1],0);

        gametext(160,175,"PRESS ANY KEY TO CONTINUE",0);

        t = 0;
        minitext(23,80,"   NAME                                           KILLS",8,2+8+16+128);
        for(i=0;i<playerswhenstarted;i++)
        {
            sprintf(tempbuf,"%-4ld",i+1);
            minitext(92+(i*23),80,tempbuf,0,2+8+16+128);
        }

        for(i=0;i<playerswhenstarted;i++)
        {
            xfragtotal = 0;
            sprintf(tempbuf,"%ld",i+1);

            minitext(30,90+t,tempbuf,0,2+8+16+128);
            minitext(38,90+t,ud.user_name[i],ps[i].palookup,2+8+16+128);

            for(y=0;y<playerswhenstarted;y++)
            {
                if(i == y)
                {
                    sprintf(tempbuf,"%-4ld",ps[y].fraggedself);
                    minitext(92+(y*23),90+t,tempbuf,0,2+8+16+128);
                    xfragtotal -= ps[y].fraggedself;
                }
                else
                {
                    sprintf(tempbuf,"%-4ld",frags[i][y]);
                    minitext(92+(y*23),90+t,tempbuf,0,2+8+16+128);
                    xfragtotal += frags[i][y];
                }

                if(myconnectindex == connecthead)
                {
                    sprintf(tempbuf,"stats %ld killed %ld %ld\n",i+1,y+1,frags[i][y]);
                    sendscore(tempbuf);
                }
            }

            sprintf(tempbuf,"%-4ld",xfragtotal);
            minitext(101+(8*23),90+t,tempbuf,0,2+8+16+128);

            t += 7;
        }

        for(y=0;y<playerswhenstarted;y++)
        {
            yfragtotal = 0;
            for(i=0;i<playerswhenstarted;i++)
            {
                if(i == y)
                    yfragtotal += ps[i].fraggedself;
                yfragtotal += frags[i][y];
            }
            sprintf(tempbuf,"%-4ld",yfragtotal);
            minitext(92+(y*23),96+(8*7),tempbuf,0,2+8+16+128);
        }

        minitext(45,96+(8*7),"DEATHS",0,2+8+16+128);
        nextpage();

        for(t=0;t<64;t++)
            palto(0,0,0,63-t);

        KB_FlushKeyboardQueue();
        while(KB_KeyWaiting()==0) getpackets();

        if( KB_KeyPressed( sc_F12 ) )
        {
            KB_ClearKeyDown( sc_F12 );
            screencapture("rdnk0000.pcx",0);
        }

        if(bonusonly || ud.multimode > 1) return;

        for(t=0;t<64;t++) palto(0,0,0,t);
    }

    if(bonusonly || ud.multimode > 1) return;

    if(!(MusicToggle == 0 || MusicDevice == NumSoundCards))
        sound(249);

    gfx_offset = (ud.volume_number&1)*5;
    bg_tile = RRTILE403;
    if (ud.volume_number == 0)
        bg_tile = ud.level_number+RRTILE403-1;
    else
        bg_tile = ud.level_number+RRTILE409-1;

    if (lastlevel || vixenlevel)
        bg_tile = RRTILE409+7;

    if (boardfilename[0])
    {
        if (!var24)
        {
            rotatesprite(0,0,65536L,0,403,0,0,2+8+16+64+128,0,0,xdim-1,ydim-1);
            endlvlmenutext(80,16,0,0,boardfilename);
        }
    }
    else if (!var24)
    {
        rotatesprite(0,0,65536L,0,bg_tile,0,0,2+8+16+64+128,0,0,xdim-1,ydim-1);
        if ((lastlevel && ud.volume_number == 2) || vixenlevel)
            endlvlmenutext(80,16,0,0,"CLOSE ENCOUNTERS");
        else if (turdlevel)
            endlvlmenutext(80,16,0,0,"SMELTING PLANT");
        else
            endlvlmenutext(80,16,0,0,level_names[(ud.volume_number*7)+ud.last_level-1]);
    }
    else
    {
        endlvlmenutext(80,16,0,0,level_names[(ud.volume_number*7)+ud.last_level-1]);
    }

    endlvlmenutext(15,192,0,0,"PRESS ANY KEY TO CONTINUE");
    KB_FlushKeyboardQueue();
    if (!var24)
    {
        nextpage();
        for(t=0;t<64;t++) palto(0,0,0,63-t);
    }
    bonuscnt = 0;
    totalclock = 0; tinc = 0;

    while( 1 )
    {
        if(ps[myconnectindex].gm&MODE_EOL)
        {
            if (boardfilename[0])
            {
                if (!var24)
                    rotatesprite(0,0,65536L,0,403,0,0,2+8+16+64+128,0,0,xdim-1,ydim-1);
            }
            else if (!var24)
                rotatesprite(0,0,65536L,0,bg_tile,0,0,2+8+16+64+128,0,0,xdim-1,ydim-1);

            if( totalclock > (1000000000L) && totalclock < (1000000320L) )
            {
                switch( ((unsigned long)totalclock>>4)%15 )
                {
                    case 0:
                        if(bonuscnt == 6)
                        {
                            bonuscnt++;
                            sound(425);
                            switch(rand()&3)
                            {
                                case 0:
                                    sound(195);
                                    break;
                                case 1:
                                    sound(196);
                                    break;
                                case 2:
                                    sound(197);
                                    break;
                                case 3:
                                    sound(199);
                                    break;
                            }
                        }
                    case 1:
                    case 4:
                    case 5:
                    case 2:
                    case 3:
                       break;
                }
            }
            else if( totalclock > (10240+120L) ) break;
            else
            {
                switch( (totalclock>>5)&3 )
                {
                    case 1:
                    case 3:
                        break;
                    case 2:
                        break;
                }
            }

            if (boardfilename[0])
            {
                if (!var24)
                {
                    rotatesprite(0,0,65536L,0,403,0,0,2+8+16+64+128,0,0,xdim-1,ydim-1);
                    endlvlmenutext(80,16,0,0,boardfilename);
                }
            }
            else if (!var24)
            {
                rotatesprite(0,0,65536L,0,bg_tile,0,0,2+8+16+64+128,0,0,xdim-1,ydim-1);
                if ((lastlevel && ud.volume_number == 2) || vixenlevel)
                    endlvlmenutext(80,16,0,0,"CLOSE ENCOUNTERS");
                else if (turdlevel)
                    endlvlmenutext(80,16,0,0,"SMELTING PLANT");
                else
                    endlvlmenutext(80,16,0,0,level_names[(ud.volume_number*7)+ud.last_level-1]);
            }
            else
            {
                endlvlmenutext(80,16,0,0,level_names[(ud.volume_number*7)+ud.last_level-1]);
            }

            endlvlmenutext(15,192,0,0,"PRESS ANY KEY TO CONTINUE");

            if( totalclock > (60*3) )
            {
                endlvlmenutext(30,48,0,0,"Yer Time:");
                endlvlmenutext(30,64,0,0,"Par time:");
                endlvlmenutext(30,80,0,0,"Xatrix Time:");
                if(bonuscnt == 0)
                    bonuscnt++;

                if( totalclock > (60*4) )
                {
                    if(bonuscnt == 1)
                    {
                        bonuscnt++;
                        sound(404);
                    }
                    sprintf(tempbuf,"%02ld : %02ld",
                        (ps[myconnectindex].player_par/(26*60))%60,
                        (ps[myconnectindex].player_par/26)%60);
                    endlvlmenutext(191,48,0,0,tempbuf);

                    if(!boardfilename[0])
                    {
                        sprintf(tempbuf,"%02ld : %02ld",
                            (partime[ud.volume_number*7+ud.last_level-1]/(26*60))%60,
                            (partime[ud.volume_number*7+ud.last_level-1]/26)%60);
                        endlvlmenutext(191,64,0,0,tempbuf);

                        sprintf(tempbuf,"%02ld : %02ld",
                            (designertime[ud.volume_number*7+ud.last_level-1]/(26*60))%60,
                            (designertime[ud.volume_number*7+ud.last_level-1]/26)%60);
                        endlvlmenutext(191,80,0,0,tempbuf);
                    }

                }
            }
            if( totalclock > (60*6) )
            {
                endlvlmenutext(30,112,0,0,"Varmints Killed:");
                endlvlmenutext(30,128,0,0,"Varmints Left:");

                if(bonuscnt == 2)
                    bonuscnt++;

                if( totalclock > (60*7) )
                {
                    if(bonuscnt == 3)
                    {
                        bonuscnt++;
                        sound(422);
                    }
                    sprintf(tempbuf,"%-3ld",ps[myconnectindex].actors_killed);
                    endlvlmenutext(231,112,0,0,tempbuf);
                    if(ud.player_skill > 3 )
                    {
                        sprintf(tempbuf,"N/A");
                        endlvlmenutext(231,128,0,0,tempbuf);
                    }
                    else
                    {
                        if( (ps[myconnectindex].max_actors_killed-ps[myconnectindex].actors_killed) < 0 )
                            sprintf(tempbuf,"%-3ld",0);
                        else sprintf(tempbuf,"%-3ld",ps[myconnectindex].max_actors_killed-ps[myconnectindex].actors_killed);
                        endlvlmenutext(231,128,0,0,tempbuf);
                    }
                }
            }
            if( totalclock > (60*9) )
            {
                endlvlmenutext(30,144,0,0,"Secrets Found:");
                endlvlmenutext(30,160,0,0,"Secrets Missed:");
                if(bonuscnt == 4) bonuscnt++;

                if( totalclock > (60*10) )
                {
                    if(bonuscnt == 5)
                    {
                        bonuscnt++;
                        sound(404);
                    }
                    sprintf(tempbuf,"%-3ld",ps[myconnectindex].secret_rooms);
                    endlvlmenutext(231,144,0,0,tempbuf);
                    if( ps[myconnectindex].secret_rooms > 0 )
                        sprintf(tempbuf,"%-3ld%",(100*ps[myconnectindex].secret_rooms/ps[myconnectindex].max_secret_rooms));
                    sprintf(tempbuf,"%-3ld",ps[myconnectindex].max_secret_rooms-ps[myconnectindex].secret_rooms);
                    endlvlmenutext(231,160,0,0,tempbuf);
                }
            }

            if(totalclock > 10240 && totalclock < 10240+10240)
                totalclock = 1024;

            if( KB_KeyWaiting() && totalclock > (60*2) )
            {
                if (var24)
                {
                    if (bonuscnt == 7)
                    {
                        bonuscnt++;
                        MUSIC_StopSong();
                        KB_FlushKeyboardQueue();
                        PlayMapAnim();
                    }
                    else if (bonuscnt == 8)
                    {
                        KB_FlushKeyboardQueue();
                        totalclock = 10361;
                        break;
                    }

                }
                if( KB_KeyPressed( sc_F12 ) )
                {
                    KB_ClearKeyDown( sc_F12 );
                    screencapture("rdnk0000.pcx",0);
                }

                if (var24)
                {
                    if( totalclock < (60*13) )
                    {
                        KB_FlushKeyboardQueue();
                        totalclock = (60*13);
                    }
                    else if( totalclock < (1000000000L))
                       totalclock = (1000000000L);
                }
                else
                {
                    if( totalclock < (60*13) )
                    {
                        KB_FlushKeyboardQueue();
                        totalclock = (60*13);
                    }
                    else if( totalclock < (1000000000L))
                       totalclock = (1000000000L);
                }
            }
        }
        else break;
        if (!var24 || bonuscnt)
            nextpage();
    }
    if (ud.eog)
    {
        for (t = 0; t < 64; t++) palto(0, 0, 0, t);
        clearview(0);
        nextpage();
        spritesound(35,ps[0].i);
        palto(0, 0, 0, 0);
        ps[myconnectindex].palette = palette;
        while (1)
        {
            int var40;
            switch ((totalclock >> 4) & 1)
            {
            case 0:
                rotatesprite(0,0,65536,0,0,RRTILE8677,0,2+8+16+64+128,0,0,xdim-1,ydim-1);
                nextpage();
                palto(0, 0, 0, 0);
                ps[myconnectindex].palette = palette;
                getpackets();
                break;
            case 1:
                rotatesprite(0,0,65536,0,0,RRTILE8677+1,0,2+8+16+64+128,0,0,xdim-1,ydim-1);
                nextpage();
                palto(0, 0, 0, 0);
                ps[myconnectindex].palette = palette;
                getpackets();
                break;
            }
            if (Sound[35].num == 0) break;
        }
    }
    if (word_119BE4)
    {
        word_119BE4 = 0;
        ud.m_volume_number = ud.volume_number = 1;
        ud.m_level_number = ud.level_number = 0;
        ud.eog = 0;
    }
    if (turdlevel)
        turdlevel = 0;
    if (vixenlevel)
        vixenlevel = 0;
}
#else
void dobonus(char bonusonly)
{
    short t, r, tinc,gfx_offset;
    long i, y,xfragtotal,yfragtotal;
    short bonuscnt;
    short bg_tile;

    bonuscnt = 0;

    for(t=0;t<64;t++) palto(0,0,0,t);
    setview(0,0,xdim-1,ydim-1);
    clearview(0L);
    nextpage();
    flushperms();

    FX_StopAllSounds();
    clearsoundlocks();
    FX_SetReverb(0L);

    if(bonusonly) goto FRAGBONUS;

    if(numplayers < 2 && ud.eog && ud.from_bonus == 0)
        switch(ud.volume_number)
    {
        case 0:
            MUSIC_StopSong();
            clearview(0L);
            nextpage();
            if(ud.lockout == 0)
            {
                playanm("turdmov.anm",5,5);
                KB_FlushKeyboardQueue();
                clearview(0L);
                nextpage();
            }
            ud.level_number = 0;
            ud.volume_number = 1;
            ud.eog = 0;

            for(t=0;t<64;t++) palto(0,0,0,t);

            KB_FlushKeyboardQueue();
            ps[myconnectindex].palette = palette;

            rotatesprite(0,0,65536L,0,1685,0,0,2+8+16+64,0,0,xdim-1,ydim-1);
            nextpage(); for(t=63;t>0;t--) palto(0,0,0,t);
            while( !KB_KeyWaiting() ) getpackets();
            for(t=0;t<64;t++) palto(0,0,0,t);
            MUSIC_StopSong();
            FX_StopAllSounds();
            clearsoundlocks();
            break;
        case 1:
            MUSIC_StopSong();
            clearview(0L);
            nextpage();

            if(ud.lockout == 0)
            {
                playanm("rr_outro.anm",5,4);
                KB_FlushKeyboardQueue();
                clearview(0L);
                nextpage();
            }
            lastlevel = 0;
            vixenlevel = 1;
            ud.level_number = 0;
            ud.volume_number = 0;

            for(t=0;t<64;t++) palto(0,0,0,t);
            setview(0,0,xdim-1,ydim-1);
            KB_FlushKeyboardQueue();
            ps[myconnectindex].palette = palette;
            rotatesprite(0,0,65536L,0,1685,0,0,2+8+16+64, 0,0,xdim-1,ydim-1);
            nextpage(); for(t=63;t>0;t--) palto(0,0,0,t);
            while( !KB_KeyWaiting() ) getpackets();
            for(t=0;t<64;t++) palto(0,0,0,t);

            break;

        case 2:
            KB_FlushKeyboardQueue();
            while( !KB_KeyWaiting() ) getpackets();

            FX_StopAllSounds();
            clearsoundlocks();
            KB_FlushKeyboardQueue();

            clearview(0L);
            nextpage();
            playanm("LNRDTEAM.ANM",4,3);
            KB_FlushKeyboardQueue();

            while( !KB_KeyWaiting() ) getpackets();

            FX_StopAllSounds();
            clearsoundlocks();

            KB_FlushKeyboardQueue();

            break;
    }

    FRAGBONUS:

    ps[myconnectindex].palette = palette;
    KB_FlushKeyboardQueue();
    totalclock = 0; tinc = 0;
    bonuscnt = 0;

    MUSIC_StopSong();
    FX_StopAllSounds();
    clearsoundlocks();

    if(playerswhenstarted > 1 && ud.coop != 1 )
    {
        if(!(MusicToggle == 0 || MusicDevice == NumSoundCards))
            sound(249);

        rotatesprite(0,0,65536L,0,MENUSCREEN,16,0,2+8+16+64+128,0,0,xdim-1,ydim-1);
        rotatesprite(160<<16,24<<16,23592L,0,INGAMEDUKETHREEDEE,0,0,2+8,0,0,xdim-1,ydim-1);
        gametext(160,58,"MULTIPLAYER TOTALS",0);
        gametext(160,58+10,level_names[(ud.volume_number*7)+ud.last_level-1],0);

        gametext(160,175,"PRESS ANY KEY TO CONTINUE",0);

        t = 0;
        minitext(23,80,"   NAME                                           KILLS",8,2+8+16+128);
        for(i=0;i<playerswhenstarted;i++)
        {
            sprintf(tempbuf,"%-4ld",i+1);
            minitext(92+(i*23),80,tempbuf,0,2+8+16+128);
        }

        for(i=0;i<playerswhenstarted;i++)
        {
            xfragtotal = 0;
            sprintf(tempbuf,"%ld",i+1);

            minitext(30,90+t,tempbuf,0,2+8+16+128);
            minitext(38,90+t,ud.user_name[i],ps[i].palookup,2+8+16+128);

            for(y=0;y<playerswhenstarted;y++)
            {
                if(i == y)
                {
                    sprintf(tempbuf,"%-4ld",ps[y].fraggedself);
                    minitext(92+(y*23),90+t,tempbuf,0,2+8+16+128);
                    xfragtotal -= ps[y].fraggedself;
                }
                else
                {
                    sprintf(tempbuf,"%-4ld",frags[i][y]);
                    minitext(92+(y*23),90+t,tempbuf,0,2+8+16+128);
                    xfragtotal += frags[i][y];
                }

                if(myconnectindex == connecthead)
                {
                    sprintf(tempbuf,"stats %ld killed %ld %ld\n",i+1,y+1,frags[i][y]);
                    sendscore(tempbuf);
                }
            }

            sprintf(tempbuf,"%-4ld",xfragtotal);
            minitext(101+(8*23),90+t,tempbuf,0,2+8+16+128);

            t += 7;
        }

        for(y=0;y<playerswhenstarted;y++)
        {
            yfragtotal = 0;
            for(i=0;i<playerswhenstarted;i++)
            {
                if(i == y)
                    yfragtotal += ps[i].fraggedself;
                yfragtotal += frags[i][y];
            }
            sprintf(tempbuf,"%-4ld",yfragtotal);
            minitext(92+(y*23),96+(8*7),tempbuf,0,2+8+16+128);
        }

        minitext(45,96+(8*7),"DEATHS",0,2+8+16+128);
        nextpage();

        for(t=0;t<64;t++)
            palto(0,0,0,63-t);

        KB_FlushKeyboardQueue();
        while(KB_KeyWaiting()==0) getpackets();

        if( KB_KeyPressed( sc_F12 ) )
        {
            KB_ClearKeyDown( sc_F12 );
            screencapture("rdnk0000.pcx",0);
        }

        if(bonusonly || ud.multimode > 1) return;

        for(t=0;t<64;t++) palto(0,0,0,t);
    }

    if(bonusonly || ud.multimode > 1) return;

    if(!(MusicToggle == 0 || MusicDevice == NumSoundCards))
        sound(249);

    gfx_offset = (ud.volume_number&1)*5;
    bg_tile = RRTILE403;
    if (ud.volume_number == 0)
        bg_tile = ud.level_number+RRTILE403-1;
    else
        bg_tile = ud.level_number+RRTILE409-1;

    if (lastlevel || vixenlevel)
        bg_tile = RRTILE409+7;

    if (boardfilename[0])
    {
        rotatesprite(0,0,65536L,0,403,0,0,2+8+16+64+128,0,0,xdim-1,ydim-1);
        endlvlmenutext(80,16,0,0,boardfilename);
    }
    else
    {
        rotatesprite(0,0,65536L,0,bg_tile,0,0,2+8+16+64+128,0,0,xdim-1,ydim-1);
        if ((lastlevel && ud.volume_number == 2) || vixenlevel)
            endlvlmenutext(80,16,0,0,"CLOSE ENCOUNTERS");
        else if (turdlevel)
            endlvlmenutext(80,16,0,0,"SMELTING PLANT");
        else
            endlvlmenutext(80,16,0,0,level_names[(ud.volume_number*7)+ud.last_level-1]);
    }

    endlvlmenutext(15,192,0,0,"PRESS ANY KEY TO CONTINUE");
    nextpage();
    KB_FlushKeyboardQueue();
    for(t=0;t<64;t++) palto(0,0,0,63-t);
    bonuscnt = 0;
    totalclock = 0; tinc = 0;

    while( 1 )
    {
        if(ps[myconnectindex].gm&MODE_EOL)
        {
            if (boardfilename[0])
                rotatesprite(0,0,65536L,0,403,0,0,2+8+16+64+128,0,0,xdim-1,ydim-1);
            else
                rotatesprite(0,0,65536L,0,bg_tile,0,0,2+8+16+64+128,0,0,xdim-1,ydim-1);

            if( totalclock > (1000000000L) && totalclock < (1000000320L) )
            {
                switch( ((unsigned long)totalclock>>4)%15 )
                {
                    case 0:
                        if(bonuscnt == 6)
                        {
                            bonuscnt++;
                            sound(425);
                            switch(rand()&3)
                            {
                                case 0:
                                    sound(195);
                                    break;
                                case 1:
                                    sound(196);
                                    break;
                                case 2:
                                    sound(197);
                                    break;
                                case 3:
                                    sound(199);
                                    break;
                            }
                        }
                    case 1:
                    case 4:
                    case 5:
                    case 2:
                    case 3:
                       break;
                }
            }
            else if( totalclock > (10240+120L) ) break;
            else
            {
                switch( (totalclock>>5)&3 )
                {
                    case 1:
                    case 3:
                        break;
                    case 2:
                        break;
                }
            }

            if (boardfilename[0])
            {
                rotatesprite(0,0,65536L,0,403,0,0,2+8+16+64+128,0,0,xdim-1,ydim-1);
                endlvlmenutext(80,16,0,0,boardfilename);
            }
            else
            {
                rotatesprite(0,0,65536L,0,bg_tile,0,0,2+8+16+64+128,0,0,xdim-1,ydim-1);
                if ((lastlevel && ud.volume_number == 2) || vixenlevel)
                    endlvlmenutext(80,16,0,0,"CLOSE ENCOUNTERS");
                else if (turdlevel)
                    endlvlmenutext(80,16,0,0,"SMELTING PLANT");
                else
                    endlvlmenutext(80,16,0,0,level_names[(ud.volume_number*7)+ud.last_level-1]);
            }

            endlvlmenutext(15,192,0,0,"PRESS ANY KEY TO CONTINUE");

            if( totalclock > (60*3) )
            {
                endlvlmenutext(30,48,0,0,"Yer Time:");
                endlvlmenutext(30,64,0,0,"Par time:");
                endlvlmenutext(30,80,0,0,"Xatrix Time:");
                if(bonuscnt == 0)
                    bonuscnt++;

                if( totalclock > (60*4) )
                {
                    if(bonuscnt == 1)
                    {
                        bonuscnt++;
                        sound(404);
                    }
                    sprintf(tempbuf,"%02ld : %02ld",
                        (ps[myconnectindex].player_par/(26*60))%60,
                        (ps[myconnectindex].player_par/26)%60);
                    endlvlmenutext(191,48,0,0,tempbuf);

                    if(!boardfilename[0])
                    {
                        sprintf(tempbuf,"%02ld : %02ld",
                            (partime[ud.volume_number*7+ud.last_level-1]/(26*60))%60,
                            (partime[ud.volume_number*7+ud.last_level-1]/26)%60);
                        endlvlmenutext(191,64,0,0,tempbuf);

                        sprintf(tempbuf,"%02ld : %02ld",
                            (designertime[ud.volume_number*7+ud.last_level-1]/(26*60))%60,
                            (designertime[ud.volume_number*7+ud.last_level-1]/26)%60);
                        endlvlmenutext(191,80,0,0,tempbuf);
                    }

                }
            }
            if( totalclock > (60*6) )
            {
                endlvlmenutext(30,112,0,0,"Varmints Killed:");
                endlvlmenutext(30,128,0,0,"Varmints Left:");

                if(bonuscnt == 2)
                    bonuscnt++;

                if( totalclock > (60*7) )
                {
                    if(bonuscnt == 3)
                    {
                        bonuscnt++;
                        sound(422);
                    }
                    sprintf(tempbuf,"%-3ld",ps[myconnectindex].actors_killed);
                    endlvlmenutext(231,112,0,0,tempbuf);
                    if(ud.player_skill > 3 )
                    {
                        sprintf(tempbuf,"N/A");
                        endlvlmenutext(231,128,0,0,tempbuf);
                    }
                    else
                    {
                        if( (ps[myconnectindex].max_actors_killed-ps[myconnectindex].actors_killed) < 0 )
                            sprintf(tempbuf,"%-3ld",0);
                        else sprintf(tempbuf,"%-3ld",ps[myconnectindex].max_actors_killed-ps[myconnectindex].actors_killed);
                        endlvlmenutext(231,128,0,0,tempbuf);
                    }
                }
            }
            if( totalclock > (60*9) )
            {
                endlvlmenutext(30,144,0,0,"Secrets Found:");
                endlvlmenutext(30,160,0,0,"Secrets Missed:");
                if(bonuscnt == 4) bonuscnt++;

                if( totalclock > (60*10) )
                {
                    if(bonuscnt == 5)
                    {
                        bonuscnt++;
                        sound(404);
                    }
                    sprintf(tempbuf,"%-3ld",ps[myconnectindex].secret_rooms);
                    endlvlmenutext(231,144,0,0,tempbuf);
                    if( ps[myconnectindex].secret_rooms > 0 )
                        sprintf(tempbuf,"%-3ld%",(100*ps[myconnectindex].secret_rooms/ps[myconnectindex].max_secret_rooms));
                    sprintf(tempbuf,"%-3ld",ps[myconnectindex].max_secret_rooms-ps[myconnectindex].secret_rooms);
                    endlvlmenutext(231,160,0,0,tempbuf);
                }
            }

            if(totalclock > 10240 && totalclock < 10240+10240)
                totalclock = 1024;

            if( KB_KeyWaiting() && totalclock > (60*2) )
            {
                if( KB_KeyPressed( sc_F12 ) )
                {
                    KB_ClearKeyDown( sc_F12 );
                    screencapture("rdnk0000.pcx",0);
                }

                if( totalclock < (60*13) )
                {
                    KB_FlushKeyboardQueue();
                    totalclock = (60*13);
                }
                else if( totalclock < (1000000000L))
                   totalclock = (1000000000L);
            }
        }
        else break;
        nextpage();
    }
    if (turdlevel)
        turdlevel = 0;
    if (vixenlevel)
        vixenlevel = 0;
}
#endif

void vglass(long x,long y,short a,short wn,short n)
{
    long z, zincs;
    short sect;

    sect = wall[wn].nextsector;
    if(sect == -1) return;
    zincs = ( sector[sect].floorz-sector[sect].ceilingz ) / n;

    for(z = sector[sect].ceilingz;z < sector[sect].floorz; z += zincs )
        EGS(sect,x,y,z-(TRAND&8191),GLASSPIECES+(z&(TRAND%3)),-32,36,36,a+128-(TRAND&255),16+(TRAND&31),0,-1,5);
}

void lotsofglass(short i,short wallnum,short n)
{
     long j, xv, yv, z, x1, y1;
     short sect, a;

     sect = -1;

     if(wallnum < 0)
     {
        for(j=n-1; j >= 0 ;j--)
        {
            a = SA-256+(TRAND&511)+1024;
            EGS(SECT,SX,SY,SZ,GLASSPIECES+(j%3),-32,36,36,a,32+(TRAND&63),1024-(TRAND&1023),i,5);
        }
        return;
     }

     j = n+1;

     x1 = wall[wallnum].x;
     y1 = wall[wallnum].y;

     xv = wall[wall[wallnum].point2].x-x1;
     yv = wall[wall[wallnum].point2].y-y1;

     x1 -= ksgn(yv);
     y1 += ksgn(xv);

     xv /= j;
     yv /= j;

     for(j=n;j>0;j--)
	 {
		  x1 += xv;
		  y1 += yv;

          updatesector(x1,y1,&sect);
          if(sect >= 0)
          {
              z = sector[sect].floorz-(TRAND&(klabs(sector[sect].ceilingz-sector[sect].floorz)));
              if( z < -(32<<8) || z > (32<<8) )
                  z = SZ-(32<<8)+(TRAND&((64<<8)-1));
              a = SA-1024;
              EGS(SECT,x1,y1,z,GLASSPIECES+(j%3),-32,36,36,a,32+(TRAND&63),-(TRAND&1023),i,5);
          }
	 }
}

void lotsofpopcorn(short i,short wallnum,short n)
{
     long j, xv, yv, z, x1, y1;
     short sect, a;

     sect = -1;

     if(wallnum < 0)
     {
        for(j=n-1; j >= 0 ;j--)
        {
            a = SA-256+(TRAND&511)+1024;
            EGS(SECT,SX,SY,SZ,POPCORN,-32,36,36,a,32+(TRAND&63),1024-(TRAND&1023),i,5);
        }
        return;
     }

     j = n+1;

     x1 = wall[wallnum].x;
     y1 = wall[wallnum].y;

     xv = wall[wall[wallnum].point2].x-x1;
     yv = wall[wall[wallnum].point2].y-y1;

     x1 -= ksgn(yv);
     y1 += ksgn(xv);

     xv /= j;
     yv /= j;

     for(j=n;j>0;j--)
     {
          x1 += xv;
          y1 += yv;

          updatesector(x1,y1,&sect);
          if(sect >= 0)
          {
              z = sector[sect].floorz-(TRAND&(klabs(sector[sect].ceilingz-sector[sect].floorz)));
              if( z < -(32<<8) || z > (32<<8) )
                  z = SZ-(32<<8)+(TRAND&((64<<8)-1));
              a = SA-1024;
              EGS(SECT,x1,y1,z,POPCORN,-32,36,36,a,32+(TRAND&63),-(TRAND&1023),i,5);
          }
     }
}

void spriteglass(short i,short n)
{
    long j, k, a, z;

    for(j=n;j>0;j--)
    {
        a = TRAND&2047;
        z = SZ-((TRAND&16)<<8);
        k = EGS(SECT,SX,SY,z,GLASSPIECES+(j%3),TRAND&15,36,36,a,32+(TRAND&63),-512-(TRAND&2047),i,5);
        sprite[k].pal = sprite[i].pal;
    }
}

void ceilingglass(short i,short sectnum,short n)
{
     long j, xv, yv, z, x1, y1;
     short a,s, startwall,endwall;

     startwall = sector[sectnum].wallptr;
     endwall = startwall+sector[sectnum].wallnum;

     for(s=startwall;s<(endwall-1);s++)
     {
         x1 = wall[s].x;
         y1 = wall[s].y;

         xv = (wall[s+1].x-x1)/(n+1);
         yv = (wall[s+1].y-y1)/(n+1);

         for(j=n;j>0;j--)
         {
              x1 += xv;
              y1 += yv;
              a = TRAND&2047;
              z = sector[sectnum].ceilingz+((TRAND&15)<<8);
              EGS(sectnum,x1,y1,z,GLASSPIECES+(j%3),-32,36,36,a,(TRAND&31),0,i,5);
          }
     }
}

void lotsofcolourglass(short i,short wallnum,short n)
{
     long j, xv, yv, z, x1, y1;
     short sect = -1, a, k;

     if(wallnum < 0)
     {
        for(j=n-1; j >= 0 ;j--)
        {
            a = TRAND&2047;
            k = EGS(SECT,SX,SY,SZ-(TRAND&(63<<8)),GLASSPIECES+(j%3),-32,36,36,a,32+(TRAND&63),1024-(TRAND&2047),i,5);
            sprite[k].pal = TRAND&15;
        }
        return;
     }

     j = n+1;
     x1 = wall[wallnum].x;
     y1 = wall[wallnum].y;

     xv = (wall[wall[wallnum].point2].x-wall[wallnum].x)/j;
     yv = (wall[wall[wallnum].point2].y-wall[wallnum].y)/j;

     for(j=n;j>0;j--)
         {
                  x1 += xv;
                  y1 += yv;

          updatesector(x1,y1,&sect);
          z = sector[sect].floorz-(TRAND&(klabs(sector[sect].ceilingz-sector[sect].floorz)));
          if( z < -(32<<8) || z > (32<<8) )
              z = SZ-(32<<8)+(TRAND&((64<<8)-1));
          a = SA-1024;
          k = EGS(SECT,x1,y1,z,GLASSPIECES+(j%3),-32,36,36,a,32+(TRAND&63),-(TRAND&2047),i,5);
          sprite[k].pal = TRAND&7;
         }
}

void SetupGameButtons( void )
{
   CONTROL_DefineFlag(gamefunc_Move_Forward,false);
   CONTROL_DefineFlag(gamefunc_Move_Backward,false);
   CONTROL_DefineFlag(gamefunc_Turn_Left,false);
   CONTROL_DefineFlag(gamefunc_Turn_Right,false);
   CONTROL_DefineFlag(gamefunc_Strafe,false);
   CONTROL_DefineFlag(gamefunc_Fire,false);
   CONTROL_DefineFlag(gamefunc_Open,false);
   CONTROL_DefineFlag(gamefunc_Run,false);
   CONTROL_DefineFlag(gamefunc_AutoRun,false);
   CONTROL_DefineFlag(gamefunc_Jump,false);
   CONTROL_DefineFlag(gamefunc_Crouch,false);
   CONTROL_DefineFlag(gamefunc_Look_Up,false);
   CONTROL_DefineFlag(gamefunc_Look_Down,false);
   CONTROL_DefineFlag(gamefunc_Look_Left,false);
   CONTROL_DefineFlag(gamefunc_Look_Right,false);
   CONTROL_DefineFlag(gamefunc_Strafe_Left,false);
   CONTROL_DefineFlag(gamefunc_Strafe_Right,false);
   CONTROL_DefineFlag(gamefunc_Aim_Up,false);
   CONTROL_DefineFlag(gamefunc_Aim_Down,false);
   CONTROL_DefineFlag(gamefunc_Weapon_1,false);
   CONTROL_DefineFlag(gamefunc_Weapon_2,false);
   CONTROL_DefineFlag(gamefunc_Weapon_3,false);
   CONTROL_DefineFlag(gamefunc_Weapon_4,false);
   CONTROL_DefineFlag(gamefunc_Weapon_5,false);
   CONTROL_DefineFlag(gamefunc_Weapon_6,false);
   CONTROL_DefineFlag(gamefunc_Weapon_7,false);
   CONTROL_DefineFlag(gamefunc_Weapon_8,false);
   CONTROL_DefineFlag(gamefunc_Weapon_9,false);
   CONTROL_DefineFlag(gamefunc_Weapon_10,false);
   CONTROL_DefineFlag(gamefunc_Inventory,false);
   CONTROL_DefineFlag(gamefunc_Inventory_Left,false);
   CONTROL_DefineFlag(gamefunc_Inventory_Right,false);
   CONTROL_DefineFlag(gamefunc_Holo_Duke,false);
   CONTROL_DefineFlag(gamefunc_Jetpack,false);
   CONTROL_DefineFlag(gamefunc_NightVision,false);
   CONTROL_DefineFlag(gamefunc_MedKit,false);
   CONTROL_DefineFlag(gamefunc_TurnAround,false);
   CONTROL_DefineFlag(gamefunc_SendMessage,false);
   CONTROL_DefineFlag(gamefunc_Map,false);
   CONTROL_DefineFlag(gamefunc_Shrink_Screen,false);
   CONTROL_DefineFlag(gamefunc_Enlarge_Screen,false);
   CONTROL_DefineFlag(gamefunc_Center_View,false);
   CONTROL_DefineFlag(gamefunc_Holster_Weapon,false);
   CONTROL_DefineFlag(gamefunc_Show_Opponents_Weapon,false);
   CONTROL_DefineFlag(gamefunc_Map_Follow_Mode,false);
   CONTROL_DefineFlag(gamefunc_See_Coop_View,false);
   CONTROL_DefineFlag(gamefunc_Mouse_Aiming,false);
   CONTROL_DefineFlag(gamefunc_Toggle_Crosshair,false);
   CONTROL_DefineFlag(gamefunc_Steroids,false);
   CONTROL_DefineFlag(gamefunc_Quick_Kick,false);
   CONTROL_DefineFlag(gamefunc_Next_Weapon,false);
   CONTROL_DefineFlag(gamefunc_Previous_Weapon,false);
}

#ifdef RRRA

void dobonus(char bonusonly)
{
    short t, r, tinc,gfx_offset,bg_tile;
    long i, y,xfragtotal,yfragtotal;
    short bonuscnt;

    bonuscnt = 0;

    for(t=0;t<64;t++) palto(0,0,0,t);
    setview(0,0,xdim-1,ydim-1);
    clearview(0L);
    nextpage();
    flushperms();

    FX_StopAllSounds();
    clearsoundlocks();
    FX_SetReverb(0L);

    if(bonusonly) goto FRAGBONUS;

    FRAGBONUS:

    ps[myconnectindex].palette = palette;
    KB_FlushKeyboardQueue();
    totalclock = 0; tinc = 0;
    bonuscnt = 0;

    MUSIC_StopSong();
    FX_StopAllSounds();
    clearsoundlocks();

    if(playerswhenstarted > 1 && ud.coop != 1 )
    {
        if(!(MusicToggle == 0 || MusicDevice == NumSoundCards))
            sound(249);

        rotatesprite(0,0,65536L,0,MENUSCREEN,16,0,2+8+16+64+128,0,0,xdim-1,ydim-1);
        rotatesprite(160<<16,24<<16,23592L,0,INGAMEDUKETHREEDEE,0,0,2+8,0,0,xdim-1,ydim-1);
        gametext(160,58,"MULTIPLAYER TOTALS",0);
        gametext(160,58+10,level_names[(ud.volume_number*7)+ud.last_level-1],0);

        gametext(160,175,"PRESS ANY KEY TO CONTINUE",0);

        t = 0;
        minitext(23,80,"   NAME                                           KILLS",8,2+8+16+128);
        for(i=0;i<playerswhenstarted;i++)
        {
            sprintf(tempbuf,"%-4ld",i+1);
            minitext(92+(i*23),80,tempbuf,0,2+8+16+128);
        }

        for(i=0;i<playerswhenstarted;i++)
        {
            xfragtotal = 0;
            sprintf(tempbuf,"%ld",i+1);

            minitext(30,90+t,tempbuf,0,2+8+16+128);
            minitext(38,90+t,ud.user_name[i],ps[i].palookup,2+8+16+128);

            for(y=0;y<playerswhenstarted;y++)
            {
                if(i == y)
                {
                    sprintf(tempbuf,"%-4ld",ps[y].fraggedself);
                    minitext(92+(y*23),90+t,tempbuf,0,2+8+16+128);
                    xfragtotal -= ps[y].fraggedself;
                }
                else
                {
                    sprintf(tempbuf,"%-4ld",frags[i][y]);
                    minitext(92+(y*23),90+t,tempbuf,0,2+8+16+128);
                    xfragtotal += frags[i][y];
                }

                if(myconnectindex == connecthead)
                {
                    sprintf(tempbuf,"stats %ld killed %ld %ld\n",i+1,y+1,frags[i][y]);
                    sendscore(tempbuf);
                }
            }

            sprintf(tempbuf,"%-4ld",xfragtotal);
            minitext(101+(8*23),90+t,tempbuf,0,2+8+16+128);

            t += 7;
        }

        for(y=0;y<playerswhenstarted;y++)
        {
            yfragtotal = 0;
            for(i=0;i<playerswhenstarted;i++)
            {
                if(i == y)
                    yfragtotal += ps[i].fraggedself;
                yfragtotal += frags[i][y];
            }
            sprintf(tempbuf,"%-4ld",yfragtotal);
            minitext(92+(y*23),96+(8*7),tempbuf,0,2+8+16+128);
        }

        minitext(45,96+(8*7),"DEATHS",0,2+8+16+128);
        nextpage();

        for(t=0;t<64;t++)
            palto(0,0,0,63-t);

        KB_FlushKeyboardQueue();
        while(KB_KeyWaiting()==0) getpackets();

        if( KB_KeyPressed( sc_F12 ) )
        {
            KB_ClearKeyDown( sc_F12 );
            screencapture("rdnk0000.pcx",0);
        }

        if(bonusonly || ud.multimode > 1) return;

        for(t=0;t<64;t++) palto(0,0,0,t);
    }

    if(bonusonly || ud.multimode > 1) return;

    if(!(MusicToggle == 0 || MusicDevice == NumSoundCards))
        sound(249);

    gfx_offset = (ud.volume_number&1)*5;
    bg_tile = RRTILE403;
    if (ud.volume_number == 0)
        bg_tile = ud.level_number+RRTILE403-1;
    else
        bg_tile = ud.level_number+RRTILE409-1;

    if (lastlevel || vixenlevel)
        bg_tile = RRTILE409+7;

    if (boardfilename[0])
    {
        rotatesprite(0,0,65536L,0,403,0,0,2+8+16+64+128,0,0,xdim-1,ydim-1);
        endlvlmenutext(80,16,0,0,boardfilename);
    }
    else
    {
        rotatesprite(0,0,65536L,0,bg_tile,0,0,2+8+16+64+128,0,0,xdim-1,ydim-1);
        if ((lastlevel && ud.volume_number == 2) || vixenlevel)
            endlvlmenutext(80,16,0,0,"CLOSE ENCOUNTERS");
        else if (turdlevel)
            endlvlmenutext(80,16,0,0,"SMELTING PLANT");
        else
            endlvlmenutext(80,16,0,0,level_names[(ud.volume_number*7)+ud.last_level-1]);
    }

    endlvlmenutext(15,192,0,0,"PRESS ANY KEY TO CONTINUE");
    nextpage();
    KB_FlushKeyboardQueue();
    for(t=0;t<64;t++) palto(0,0,0,63-t);
    bonuscnt = 0;
    totalclock = 0; tinc = 0;

    while( 1 )
    {
        if(ps[myconnectindex].gm&MODE_EOL)
        {
            if (boardfilename[0])
                rotatesprite(0,0,65536L,0,403,0,0,2+8+16+64+128,0,0,xdim-1,ydim-1);
            else
                rotatesprite(0,0,65536L,0,bg_tile,0,0,2+8+16+64+128,0,0,xdim-1,ydim-1);

            if( totalclock > (1000000000L) && totalclock < (1000000320L) )
            {
                switch( ((unsigned long)totalclock>>4)%15 )
                {
                    case 0:
                        if(bonuscnt == 6)
                        {
                            bonuscnt++;
                            sound(425);
                            switch(rand()&3)
                            {
                                case 0:
                                    sound(195);
                                    break;
                                case 1:
                                    sound(196);
                                    break;
                                case 2:
                                    sound(197);
                                    break;
                                case 3:
                                    sound(199);
                                    break;
                            }
                        }
                    case 1:
                    case 4:
                    case 5:
                    case 2:
                    case 3:
                       break;
                }
            }
            else if( totalclock > (10240+120L) ) break;
            else
            {
                switch( (totalclock>>5)&3 )
                {
                    case 1:
                    case 3:
                        break;
                    case 2:
                        break;
                }
            }

            if (boardfilename[0])
            {
                rotatesprite(0,0,65536L,0,403,0,0,2+8+16+64+128,0,0,xdim-1,ydim-1);
                endlvlmenutext(80,16,0,0,boardfilename);
            }
            else
            {
                rotatesprite(0,0,65536L,0,bg_tile,0,0,2+8+16+64+128,0,0,xdim-1,ydim-1);
                if ((lastlevel && ud.volume_number == 2) || vixenlevel)
                    endlvlmenutext(80,16,0,0,"CLOSE ENCOUNTERS");
                else if (turdlevel)
                    endlvlmenutext(80,16,0,0,"SMELTING PLANT");
                else
                    endlvlmenutext(80,16,0,0,level_names[(ud.volume_number*7)+ud.last_level-1]);
            }

            endlvlmenutext(15,192,0,0,"PRESS ANY KEY TO CONTINUE");

            if( totalclock > (60*3) )
            {
                endlvlmenutext(30,48,0,0,"Yer Time:");
                endlvlmenutext(30,64,0,0,"Par time:");
                endlvlmenutext(30,80,0,0,"Xatrix Time:");
                if(bonuscnt == 0)
                    bonuscnt++;

                if( totalclock > (60*4) )
                {
                    if(bonuscnt == 1)
                    {
                        bonuscnt++;
                        sound(404);
                    }
                    sprintf(tempbuf,"%02ld : %02ld",
                        (ps[myconnectindex].player_par/(26*60))%60,
                        (ps[myconnectindex].player_par/26)%60);
                    endlvlmenutext(191,48,0,0,tempbuf);

                    if(!boardfilename[0])
                    {
                        sprintf(tempbuf,"%02ld : %02ld",
                            (partime[ud.volume_number*7+ud.last_level-1]/(26*60))%60,
                            (partime[ud.volume_number*7+ud.last_level-1]/26)%60);
                        endlvlmenutext(191,64,0,0,tempbuf);

                        sprintf(tempbuf,"%02ld : %02ld",
                            (designertime[ud.volume_number*7+ud.last_level-1]/(26*60))%60,
                            (designertime[ud.volume_number*7+ud.last_level-1]/26)%60);
                        endlvlmenutext(191,80,0,0,tempbuf);
                    }

                }
            }
            if( totalclock > (60*6) )
            {
                endlvlmenutext(30,112,0,0,"Varmints Killed:");
                endlvlmenutext(30,128,0,0,"Varmints Left:");

                if(bonuscnt == 2)
                    bonuscnt++;

                if( totalclock > (60*7) )
                {
                    if(bonuscnt == 3)
                    {
                        bonuscnt++;
                        sound(422);
                    }
                    sprintf(tempbuf,"%-3ld",ps[myconnectindex].actors_killed);
                    endlvlmenutext(231,112,0,0,tempbuf);
                    if(ud.player_skill > 3 )
                    {
                        sprintf(tempbuf,"N/A");
                        endlvlmenutext(231,128,0,0,tempbuf);
                    }
                    else
                    {
                        if( (ps[myconnectindex].max_actors_killed-ps[myconnectindex].actors_killed) < 0 )
                            sprintf(tempbuf,"%-3ld",0);
                        else sprintf(tempbuf,"%-3ld",ps[myconnectindex].max_actors_killed-ps[myconnectindex].actors_killed);
                        endlvlmenutext(231,128,0,0,tempbuf);
                    }
                }
            }
            if( totalclock > (60*9) )
            {
                endlvlmenutext(30,144,0,0,"Secrets Found:");
                endlvlmenutext(30,160,0,0,"Secrets Missed:");
                if(bonuscnt == 4) bonuscnt++;

                if( totalclock > (60*10) )
                {
                    if(bonuscnt == 5)
                    {
                        bonuscnt++;
                        sound(404);
                    }
                    sprintf(tempbuf,"%-3ld",ps[myconnectindex].secret_rooms);
                    endlvlmenutext(231,144,0,0,tempbuf);
                    if( ps[myconnectindex].secret_rooms > 0 )
                        sprintf(tempbuf,"%-3ld%",(100*ps[myconnectindex].secret_rooms/ps[myconnectindex].max_secret_rooms));
                    sprintf(tempbuf,"%-3ld",ps[myconnectindex].max_secret_rooms-ps[myconnectindex].secret_rooms);
                    endlvlmenutext(231,160,0,0,tempbuf);
                }
            }

            if(totalclock > 10240 && totalclock < 10240+10240)
                totalclock = 1024;

            if( KB_KeyWaiting() && totalclock > (60*2) )
            {
                if( KB_KeyPressed( sc_F12 ) )
                {
                    KB_ClearKeyDown( sc_F12 );
                    screencapture("rdnk0000.pcx",0);
                }

                if( totalclock < (60*13) )
                {
                    KB_FlushKeyboardQueue();
                    totalclock = (60*13);
                }
                else if( totalclock < (1000000000L))
                   totalclock = (1000000000L);
            }
        }
        else break;
        nextpage();
    }
    if (turdlevel)
        turdlevel = 0;
    if (vixenlevel)
        vixenlevel = 0;
}
#endif

/*
===================
=
= GetTime
=
===================
*/

long GetTime(void)
   {
   return totalclock;
   }

/*
===================
=
= CenterCenter
=
===================
*/

void CenterCenter(void)
   {
   printf("Center the joystick and press a button\n");
   }

/*
===================
=
= UpperLeft
=
===================
*/

void UpperLeft(void)
   {
   printf("Move joystick to upper-left corner and press a button\n");
   }

/*
===================
=
= LowerRight
=
===================
*/

void LowerRight(void)
   {
   printf("Move joystick to lower-right corner and press a button\n");
   }

/*
===================
=
= CenterThrottle
=
===================
*/

void CenterThrottle(void)
   {
   printf("Center the throttle control and press a button\n");
   }

/*
===================
=
= CenterRudder
=
===================
*/

void CenterRudder(void)
{
   printf("Center the rudder control and press a button\n");
}

repo_name: orochi/nblood

license: mit