#include "game.h"
#include "types.h"
#include "keyboard.h"
#include "control.h"
#include "function.h"
#include "mathutil.h"

#define PLAYERFRICTION 0xcb00 //0xda00

int32 turnheldtime; //MED
int32 lastcontroltime; //MED

#define TURBOTURNTIME (TICRATE/9)
#define NORMALTURN   6
#define PREAMBLETURN 3
#define NORMALKEYMOVE 40
#define MAXVEL       ((NORMALKEYMOVE*2)+10)
#define MAXSVEL      ((NORMALKEYMOVE*2)+10)
#define MAXANGVEL    50

void getinput(void)
{

    short j;
//MED
    ControlInfo info;
    int32 tics;
    boolean running;
    int32 turnamount;
    int32 keymove;
    int32 momx,momy;
    struct player_struct *p;

    p = &ps[myconnectindex];

    if( (p->gm&MODE_MENU) )
    {
        locvel = vel = 0;
        locsvel = svel = 0;
        locangvel = angvel = 0;
        locbits = 0L;
        return;
    }

    tics = totalclock-lastcontroltime;
    lastcontroltime = totalclock;

    CONTROL_GetMovementInput( &info );
    CONTROL_GetButtonInput();

    locbits =    BUTTON(gamefunc_Jump);
    locbits |=   BUTTON(gamefunc_Crouch)<<1;
    locbits |=   BUTTON(gamefunc_Fire)<<2;
    locbits |=   BUTTON(gamefunc_Look_Up)<<3;
    locbits |=   BUTTON(gamefunc_Look_Down)<<4;
    locbits |=   BUTTON(gamefunc_Run)<<5;
    locbits |=   BUTTON(gamefunc_Look_Left)<<6;
    locbits |=   BUTTON(gamefunc_Look_Right)<<7;
    j=0;
    if (BUTTON(gamefunc_Weapon_1))
       j = 1;
    if (BUTTON(gamefunc_Weapon_2))
       j = 2;
    if (BUTTON(gamefunc_Weapon_3))
       j = 3;
    if (BUTTON(gamefunc_Weapon_4))
       j = 4;
    if (BUTTON(gamefunc_Weapon_5))
       j = 5;
    if (BUTTON(gamefunc_Weapon_6))
       j = 6;
    if (BUTTON(gamefunc_Weapon_7))
       j = 7;
    if (BUTTON(gamefunc_Weapon_8))
       j = 8;
    if (BUTTON(gamefunc_Weapon_9))
       j = 9;
    if (BUTTON(gamefunc_Weapon_10))
       j = 10;
    locbits |=   j<<8;
    locbits |=   BUTTON(gamefunc_Transparent_Mode)<<12;
    locbits |=   BUTTON(gamefunc_Aim_Up)<<13;
    locbits |=   BUTTON(gamefunc_Aim_Down)<<14;
    locbits |=   BUTTON(gamefunc_Virtual_Mode)<<15;
//    locbits |=   BUTTON(gamefunc_)<<16;
    locbits |=   BUTTON(gamefunc_AutoRun)<<17;
    locbits |=   BUTTON(gamefunc_Center_View)<<18;
    locbits |=   BUTTON(gamefunc_Holster_Weapon)<<19;
    locbits |=   BUTTON(gamefunc_Inventory_Left)<<20;
    locbits |=   BUTTON(gamefunc_Pause)<<21;
    locbits |=   BUTTON(gamefunc_Map)<<22;
//    locbits |=   BUTTON(gamefunc_)<<23;
    locbits |=   BUTTON(gamefunc_Holo_Duke)<<24;
    locbits |=   BUTTON(gamefunc_Jetpack)<<25;
    locbits |=   BUTTON(gamefunc_Powerup_Toggle)<<26;
    locbits |=   BUTTON(gamefunc_Inventory_Right)<<27;
    locbits |=   BUTTON(gamefunc_TurnAround)<<28;
    locbits |=   BUTTON(gamefunc_Open)<<29;
    locbits |=   BUTTON(gamefunc_Inventory)<<30;
    locbits |=   BUTTON(gamefunc_Escape)<<31;

    running = BUTTON(gamefunc_Run);

    svel = vel = angvel = 0;

    if( BUTTON(gamefunc_Strafe) )
       svel = -info.dyaw>>6;
    else
       angvel = info.dyaw>>8;

    vel = -info.dz>>6;

    if (running)
       {
       turnamount = NORMALTURN<<1;
       keymove = NORMALKEYMOVE<<1;
       }
    else
       {
       turnamount = NORMALTURN;
       keymove = NORMALKEYMOVE;
       }

    if (BUTTON(gamefunc_Strafe))
    {
        if ( BUTTON(gamefunc_Turn_Left))
           {
           svel -= -keymove;
           }
        if ( BUTTON(gamefunc_Turn_Right))
           {
           svel -= keymove;
           }
    }
    else
    {
        if ( BUTTON(gamefunc_Turn_Left))
           {
           turnheldtime += tics;
           if (turnheldtime>=TURBOTURNTIME)
              {
              angvel -= turnamount;
              }
           else
              {
              angvel -= PREAMBLETURN;
              }
           }
        else if ( BUTTON(gamefunc_Turn_Right))
           {
           turnheldtime += tics;
           if (turnheldtime>=TURBOTURNTIME)
              {
              angvel += turnamount;
              }
           else
              {
              angvel += PREAMBLETURN;
              }
           }
        else
           {
           turnheldtime=0;
           }
    }

    if ( BUTTON( gamefunc_Strafe_Left ) )
        svel += keymove;

    if ( BUTTON( gamefunc_Strafe_Right ) )
        svel += -keymove;

    if ( BUTTON(gamefunc_Move_Forward) )
        vel += keymove;

    if ( BUTTON(gamefunc_Move_Backward) )
        vel += -keymove;

    if(vel < -MAXVEL) vel = -MAXVEL;
    if(vel > MAXVEL) vel = MAXVEL;
    if(svel < -MAXSVEL) svel = -MAXSVEL;
    if(svel > MAXSVEL) svel = MAXSVEL;
    if(angvel < -MAXANGVEL) angvel = -MAXANGVEL;
    if(angvel > MAXANGVEL) angvel = MAXANGVEL;

    momx = mulscale(vel,sintable[(p->ang+2560)&2047],9);
    momy = mulscale(vel,sintable[(p->ang+2048)&2047],9);

    momx += mulscale(svel,sintable[(p->ang+2048)&2047],9);
    momy += mulscale(svel,sintable[(p->ang+1536)&2047],9);

    if(ud.scroll_mode)
    {
        locvel = locsvel = locangvel = 0;
        locbits &= (1<<31);
    }
    else
    {
        locvel = momx;
        locsvel = momy;
        locangvel = angvel;
    }

    cheats();

}


void processinput(short snum)
{
    long j, i, k, doubvel, fz, cz, hz, lz;
    char space,shrunk;
    unsigned long sb_snum;
    short psect, psectlotag,*kb;
    struct player_struct *p;

    sb_snum = sync[snum].syncbits;
    p = &ps[snum];
    kb = &p->kickback_pic;

    psect = p->cursectnum;

    psectlotag = sector[psect].lotag;

    space = ceilingspace(psect);
    shrunk = (sprite[p->i].yrepeat < 32);

    getzrange(p->posx,p->posy,p->posz,psect,&cz,&hz,&fz,&lz,163L,0);

    hittype[p->i].floorz = fz;
    hittype[p->i].ceilingz = cz;

    if( hz >= 0 && (hz&49152) == 49152)
    {
        hz &= (MAXSPRITES-1);

        if(sprite[hz].statnum == 1 && sprite[hz].extra >= 0)
            hz = -1;
        cz = sector[psect].ceilingz;
    }

    if(lz >= 0 && (lz&49152) == 49152)
    {
        j = lz&(MAXSPRITES-1);

        {
            if(sprite[j].picnum == APLAYER && j != p->i)
                fz += (16<<8);
            if( (sprite[j].cstat&33) == 33 && psectlotag == 1)
            {
                psectlotag = 0;
                p->footprintcount = 0;
                p->on_waterbridge = 1;
            }
            else
                p->on_waterbridge = 0;
        }
    }

    p->onmovingsector = 0;

    if(p->over_shoulder_on && p->over_shoulder_on < (1024+512))
        p->over_shoulder_on += 256;

    // Delete the health properly.

    if(sprite[p->i].extra > 0)
    {
        sprite[p->i].extra -= p->extra_extra8>>8;

        j = sprite[p->i].extra-p->last_extra;

        if(j < 0)
        {
            p->extra_extra8 = 0;
            PUS;
            j += mulscale(krand(),j,18);
            if(p->shield_amount > 0)
            {
                sprite[p->i].extra = p->last_extra;
                if(j < -4)
                {
                    sprite[p->i].extra += j>>2;
                    j -= (j>>2);
                }
                p->shield_amount += j;
                if(p->shield_amount < 0)
                    p->shield_amount = 0;
            }
        }
        else if(j > 0)
        {
            PUS;
            if( sprite[p->i].extra > max_player_health )
                sprite[p->i].extra = max_player_health;
        }
    }
    else
    {
        sprite[p->i].extra = 0;
        p->shield_amount = 0;
    }
    p->last_extra = sprite[p->i].extra;

    if(klabs(p->status_wack) < 2)
    {
        if(p->status_wack != 0)
            PUS;
        p->status_wack = 0;
    }
    else
    {
        p->status_wack >>= 1;
        PUS;
    }

    if(p->flaming > 0)
    {
        p->flaming--;
        p->extra_extra8 += 48;
        if(rnd(8))
            spritesound(FLESH_BURNING,p->i);
    }
    else p->flaming = 0;

    if(p->select_dir)
    {
        if(psectlotag != 15 || (sb_snum&(1<<31)) )
            p->select_dir = 0;
        else
        {
            if(sync[snum].syncvel > 127)
            {
                p->select_dir = 0;
                activatewarpelevators(p->i,-1);
            }
            else if(sync[snum].syncvel <= -127)
            {
                p->select_dir = 0;
                activatewarpelevators(p->i,1);
            }
            return;
        }
    }

    if( sprite[p->i].extra <= 0 )
    {
        if(p->dead_flag == 0)
        {
            p->dead_flag = -(krand()&511)-1;
            p->jetpack_on = 0;
            p->holoduke_on = -1;

            stopsound(DUKE_JETPACK_IDLE);
            PUS;

            if( (sprite[p->i].cstat&32768) == 0)
                sprite[p->i].cstat = 0;

            if(numplayers > 1 && sprite[hittype[p->i].owner].picnum == APLAYER)
            {
                if(p->i == hittype[p->i].owner)
                    ps[sprite[hittype[p->i].owner].yvel].frag--;
                else ps[sprite[hittype[p->i].owner].yvel].frag++;
                PUS;
            }
        }

        if(p->suck_sprite >= 0)
        {
            p->ang = sprite[p->suck_sprite].ang+1024;

            if( dist(&sprite[p->i],&sprite[p->suck_sprite]) < 2048 )
                sprite[p->i].xvel = -256;
            else sprite[p->i].xvel = 0;

            p->bobcounter += 8;
            k = p->bobcounter;
        }
        else if( psectlotag == 2)
        {
            if(p->on_warping_sector == 0)
            {
                if( klabs(p->posz-fz) > (PHEIGHT>>1))
                    p->posz += 348;
            }
            else
            {
                sprite[p->i].z -= 512;
                sprite[p->i].zvel = -348;
            }

            clipmove(&p->posx,&p->posy,
                &p->posz,&p->cursectnum,
                0,0,164L,(4L<<8),(4L<<8),0);

            p->bobcounter += 32;
            k = p->bobcounter;
        }

        p->oposx = p->posx;
        p->oposy = p->posy;
        p->oposz = p->posz;
        p->oang = p->ang;

        changespritesect(p->i,p->cursectnum);
        pushmove(&p->posx,&p->posy,&p->posz,&p->cursectnum,128L,(4L<<8),(20L<<8),0);

        if( fz > cz+(16<<8) )
            p->rotscrnang = p->dead_flag+(((fz-p->posz)>>6)&2047);

        if(sync[snum].syncangvel)
        {
            p->ang += sync[snum].syncangvel;
            hittype[p->i].owner = p->i;
        }

        p->on_warping_sector = 0;

        return;
    }

    if(p->transporter_hold > 0)
    {
        p->transporter_hold--;
        if(p->transporter_hold == 1 && p->on_warping_sector)
            p->transporter_hold = 2;
    }
    if(p->transporter_hold < 0)
        p->transporter_hold++;

    if(p->newowner >= 0)
    {
        i = p->newowner;
        p->posx = SX;
        p->posy = SY;
        p->posz = SZ;
        p->ang =  SA;
        p->posxv = p->posyv = sprite[p->i].xvel = 0;
        return;
    }

    if(p->cheat_phase > 0)
        sb_snum &= (0xffffffff-3);

    doubvel = TICSPERFRAME;

    if(sb_snum&(1<<6))
        p->look_ang -= 192;

    else if(sb_snum&(1<<7))
        p->look_ang += 192;

    p->rotscrnang -= (p->rotscrnang>>2);
    p->look_ang -= (p->look_ang>>2);

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

    if( p->bobcounter == 0 )
    {
        if( (p->weapon_sway&2047) > (1024+96) )
            p->weapon_sway -= 96;
        else if( (p->weapon_sway&2047) < (1024-96) )
            p->weapon_sway += 96;
    }
    else p->weapon_sway = p->bobcounter;

    sprite[p->i].xvel = ( (p->posx-p->oposx)+(p->posy-p->oposy) )>>1;

    if(p->on_ground)
        p->bobcounter += sprite[p->i].xvel;

    p->oposx = p->posx;
    p->oposy = p->posy;
    p->oposz = p->posz;
    p->oang = p->ang;

    if(p->one_eighty_count < 0)
    {
        p->one_eighty_count += 128;
        p->ang += 128;
    }

    if(p->steroids_amount > 0 && p->steroids_amount < 400)
        doubvel <<= 1;

    if( psectlotag != 2 && psectlotag != 1 && p->jp_safety == 0 && p->jetpack_on == 0 && p->jetpack_amount)
        if( p->poszv > 4096 && (fz-p->posz) < (PHEIGHT<<1))
        {
            p->jp_safety = 1;
            p->jetpack_on = 1;

//            spritesound(DUKE_JETPACK_IDLE,p->i);
        }

    if(p->jp_safety && p->jetpack_on)
    {
        if(p->jp_safety < 8)
        {
            p->jp_safety++;
            p->poszv >>= 1;
        }
        else
        {
            p->jetpack_on = 0;
            p->jp_safety = 0;
            stopsound(DUKE_JETPACK_IDLE);
        }
    }

    // Shrinking code

    if(shrunk)
        psectlotag = 1;

    if (p->auto_run && !(sb_snum&(1<<5) ))     //Lt. shift doubles forward velocity
        doubvel <<= 1;

    if( psectlotag == 2)
    {
        p->flaming = 0;
        doubvel >>= 1;
        p->jumping_counter = 0;

        if ( sb_snum&1 )
            p->posz -= 1024;
        else if (sb_snum&(1<<1))
            p->posz += 1024;
        else
        {
            p->bobcounter += 32;
            k = sintable[(p->bobcounter<<1)&2047];
            p->poszv += k>>8;
            p->poszv = p->poszv>>1;
        }

        p->posz += p->poszv;

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

        if(p->posz < (cz+(4<<8)) )
        {
            p->posz = cz+(4<<8);
            p->poszv = 0;
        }
    }

    else if(p->jetpack_on)
    {

        p->on_ground = 0;

        p->jumping_counter = 0;

        if(p->jetpack_on < 11)
        {
            p->jetpack_on++;
            p->posz -= (p->jetpack_on<<7); //Goin up
        }
//        else if(!FX_SoundActive(SoundOwner[DUKE_JETPACK_IDLE].voice))
            spritesound(DUKE_JETPACK_IDLE,p->i);

        if ( sb_snum&1 )                            //A (soar high)
        {
            p->posz -= 2048;
            p->crack_time = 999;
        }

        if (sb_snum&(1<<1))                            //Z (soar low)
        {
            p->posz += 2048+512;
            p->crack_time = 999;
        }

        if(psectlotag == 0 || psectlotag == 2)
            k = 64;
        else k = 16;

        if(p->posz > (fz-(k<<8)) )
            p->posz += ((fz-(k<<8))-p->posz)>>1;

        if(p->posz < (cz+(18<<8)) )
            p->posz = cz+(18<<8);
    }
    else if( psectlotag != 2 )
    {
        p->airleft = 62<<5; //Aprox twenty seconds.
        if(p->scuba_on == 128)
        {
            p->scuba_on = 0;
            PUS;
        }
        if( space == 0 && p->bodysuit_on == 128 )
        {
            p->bodysuit_on = 0;
            PUS;
        }

        if( psectlotag == 1 )
        {
            if(p->dummyplayersprite == -1 && shrunk == 0)
                p->dummyplayersprite =
                    spawn(p->i,PLAYERONWATER);

            i = 34;

            k = klabs(sintable[(p->bobcounter>>1)&2047]);
            p->posz += k>>6;

            if(shrunk == 0)
            {
                if(p->on_ground == 1)
                {
                    p->footprintcount = 16;
                    if(sector[p->cursectnum].floorpicnum == FLOORSLIME)
                        p->footprintpal = 8;
                    else p->footprintpal = 0;
                }
            }
        }
        else
        {
            i = 40;

            if(p->footprintcount > 0 && p->on_ground)
            {
                for(j=headspritesect[psect];j>=0;j=nextspritesect[j])
                    if(sprite[j].picnum == FOOTPRINTS)
                        if (klabs(sprite[j].x-p->posx) < 384)
                            if (klabs(sprite[j].y-p->posy) < 384)
                                break;
                if(j < 0)
                {
                    p->footprintcount--;
                    j = spawn(p->i,FOOTPRINTS);
                    sprite[j].pal = p->footprintpal;
                }
            }
        }

        if(p->posz < (fz-(i<<8)) ) //falling
        {

            p->on_ground = 0;

            if( space == 0 )
                p->poszv += GC;
            else p->poszv += GC/6;

            if(p->poszv >= (4096+2048))
                p->poszv = (4096+2048);
        }

        else //hit the ground
        {
            if(p->on_ground == 0 && p->poszv > (6144>>1))
                p->hard_landing = p->poszv>>10;

            p->on_ground = 1;

            if(i==40)
            {
                //Smooth on the ground
                p->posz += ((fz-(i<<8))-p->posz)>>1;
                if(p->poszv > 0)
                    p->poszv -= 412;
                else p->poszv = 0;
            }
            else
                p->posz +=
                    ((fz-(i<<8))-p->posz)/3; //Smooth on the water

            p->on_warping_sector = 0;

            if( sb_snum&2 )
            {
                p->posz += (2048+768);
                p->crack_time = 999;
            }

            if( (sb_snum&1) == 0 && p->jumping_toggle == 1)
                p->jumping_toggle = 0;

            else if( (sb_snum&1) && p->jumping_toggle == 0 )
            {
                if( p->jumping_counter == 0 )
                    if( (fz-cz) > (56<<8) )
                    {
                        p->jumping_counter = 1;
                        p->jumping_toggle = 1;
                    }
            }

            if(shrunk)
                p->posz += 2048;

        }

        if(p->jumping_counter)
        {
            if( (sb_snum&1) == 0 && p->jumping_toggle == 1)
                p->jumping_toggle = 0;

            if( p->jumping_counter < (1024+256) )
            {
                if(psectlotag == 1 && p->jumping_counter > 768)
                {
                    p->jumping_counter = 0;
                    p->poszv = -512;
                }
                else
                {
                    if( space == 0 )
                    {
                        p->poszv -= (sintable[(2048-128+p->jumping_counter)&2047])/12;
                        p->jumping_counter += 190;
                    }
                    else
                    {
                        p->jumping_counter += 80;
                        p->poszv -= (sintable[p->jumping_counter&2047])>>6;
                    }
                    p->on_ground = 0;
                }
            }
            else
            {
                p->jumping_counter = 0;
                p->poszv = 0;
            }
        }

        p->posz += p->poszv;

        if(p->posz < (cz+(12<<8)) )
        {
            p->jumping_counter = 0;
            p->poszv = 128;
            p->posz = cz+(12<<8);
        }
    }

    //Do the quick lefts and rights

    if(p->fist_incs || p->transporter_hold > 2 || p->hard_landing || p->access_incs > 0 || p->knee_incs > 0 ||
        (p->current_weapon == HANDHOLDINGLASER && p->kickback_pic > 1 && p->kickback_pic < 4 ) )
    {
        doubvel = 0;
        p->posxv = 0;
        p->posyv = 0;
    }
    else if ( sync[snum].syncangvel )          //p->ang += syncangvel * constant
    {                         //ENGINE calculates angvel for you

        p->angvel = sync[snum].syncangvel*doubvel;

        p->ang += p->angvel;

        p->ang = (p->ang+2048)&2047;

        p->crack_time = 999;
    }

    if ( p->posxv || p->posyv || sync[snum].syncvel || sync[snum].syncsvel )
    {
        p->crack_time = 999;

        k = sintable[p->bobcounter&2047]>>12;
        if( k == 1 || k == 3 )
        {
            if(p->walking_snd_toggle == 0 && p->on_ground && shrunk == 0)
            {
                switch( psectlotag )
                {
                    case 0:

                        if(lz >= 0 && (lz&(MAXSPRITES-1))==49152 )
                            j = sprite[lz&(MAXSPRITES-1)].picnum;
                        else j = sector[psect].floorpicnum;

                        switch(j)
                        {
                            case PANNEL1:
                            case PANNEL2:
                                spritesound(DUKE_WALKINDUCTS,p->i);
                                p->walking_snd_toggle = 1;
                                break;
                        }
                        break;

                    case 1:
                        spritesound(DUKE_ONWATER,p->i);
                        p->walking_snd_toggle = 1;
                        break;
                }
            }
        }
        else p->walking_snd_toggle = 0;

        if(p->current_weapon == KNEE && p->kickback_pic && p->on_ground)
            doubvel = 0;

        p->posxv += ((sync[snum].syncvel*doubvel)<<6);
        p->posyv += ((sync[snum].syncsvel*doubvel)<<6);

        if( p->on_ground && (sb_snum&2) ) // Crawling
        {
            p->posxv = mulscale(p->posxv,PLAYERFRICTION-0x2000,16);
            p->posyv = mulscale(p->posyv,PLAYERFRICTION-0x2000,16);
        }
        else
        {
            p->posxv = mulscale(p->posxv,PLAYERFRICTION,16);
            p->posyv = mulscale(p->posyv,PLAYERFRICTION,16);
        }

        if( abs(p->posxv) < 12800 && abs(p->posyv) < 12800 )
            p->posxv = p->posyv = 0;
        else
            if( abs(p->posxv) > (12800<<6) && abs(p->posyv) > (12800<<6) )
                if( psectlotag != 2 && p->on_ground )
                    p->posz += (klabs(sintable[p->bobcounter&2047])/10);

        if( shrunk )
        {
            p->posxv >>= 2;
            p->posyv >>= 2;
        }

        if(p->horiz > (100-35) && p->horiz < (100+35) )
            p->horiz += 33-(p->horiz/3);
    }

    HORIZONLY:

        if(psectlotag == 1)
            i = (4L<<8);
        else i = (20L<<8);

        if(sector[p->cursectnum].lotag == 2)
            k = 0;
        else k = 1;

        if(ud.clip == 0)
            j = clipmove(&p->posx,&p->posy,
                &p->posz,&p->cursectnum,
                p->posxv,p->posyv,164L,(4L<<8),i,0);
        else
        {
            p->posx += p->posxv>>14;
            p->posy += p->posyv>>14;
            j = 0;
        }

        if(j)
            p->bobcounter = 0;

        setsprite(p->i,p->posx,p->posy,p->posz+PHEIGHT);
        if(k && sector[p->cursectnum].lotag == 2)
        {
            p->inven_icon = 2;
            PUS;
        }

        if( psectlotag < 3 )
        {
            psect = sprite[p->i].sectnum;
            if( sector[psect].lotag == 31)
                if( sprite[sector[psect].hitag].xvel && temp_data[sector[psect].hitag][0] == 0)
            {
                p->pals[0] = 64;
                p->pals[1] = 64;
                p->pals[2] = 64;
                p->pals_time = totalclock + 32;

                sprite[p->i].extra = 0;
                sprite[p->i].cstat |= 32768;
                sprite[p->i].z = sector[sprite[p->i].sectnum].floorz-(8<<8);
                guts(&sprite[p->i],JIBS1,8);
                return;
            }
        }

        if( klabs(fz-cz) < (8<<8) || pushmove(&p->posx,&p->posy,&p->posz,&p->cursectnum,128L,(4L<<8),i,0) < 0)
        {
            p->pals[0] = 64;
            p->pals[1] = 64;
            p->pals[2] = 64;
            p->pals_time = totalclock + 32;

            sprite[p->i].extra = -1000;
            sprite[p->i].cstat |= 32768;
            guts(&sprite[p->i],JIBS1,20);
            PUS;
            return;
        }

        if( sb_snum&(1<<5) )
            checkplayerhurtwall(p,j);

        if (p->cursectnum != sprite[p->i].sectnum)
           changespritesect(p->i,p->cursectnum);

        if( sb_snum&(1<<18) || p->hard_landing)
            p->return_to_center = 8;

        if( sb_snum&(1<<13) )
        {
//            if(p->jumping_counter == 0)
            p->return_to_center = 8;

            if( sb_snum&(1<<5) ) p->horiz += 8;
            p->horiz += 8;
        }

        else if( sb_snum&(1<<14) )
        {
  //          if(p->jumping_counter == 0)
            p->return_to_center = 8;

            if( sb_snum&(1<<5) ) p->horiz -= 12;
            p->horiz -= 12;
        }

        else if( sb_snum&(1<<3) )
        {
            if( sb_snum&(1<<5) )
                p->horiz += 16;
            p->horiz += 16;
        }

        else if( sb_snum&(1<<4) )
        {
            if( sb_snum&(1<<5) )
                p->horiz -= 16;
            p->horiz -= 16;
        }

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

        if(p->hard_landing > 0)
        {
            p->hard_landing--;
            p->horiz -= p->hard_landing*10;
        }

        if(p->horiz > 199) p->horiz = 199;
        else if(p->horiz < 0) p->horiz = 0;

    //Shooting code/changes

    if( p->show_empty_weapon > 0)
        p->show_empty_weapon--;
    if(p->show_empty_weapon == 1)
    {
        addweapon(p,p->last_full_weapon,1);
        return;
    }

    if( doincrements(p) ) return;
    i = p->weapon_pos;

    if( (i&127) && (i&127) != 6)
    {
        if( (i&128) ) //Down
            p->weapon_pos++;
        else
            p->weapon_pos--;

        if( i == 131 )
        {
            if( p->current_weapon == KNEE )
                p->kickback_pic = 1;

        }
    }
    else if(p->last_weapon >= 0)
    {
        p->weapon_pos = 129;
        p->last_weapon = -1;
    }

    // HACKS

    if( p->current_weapon == SHRINKER)
    {
        if( p->ammo_c_amount[p->togweapon9] > 0 )
            p->random_club_frame += 64; // Glowing
        else p->random_club_frame = 0;
    }

    if(p->rapid_fire_hold == 1)
    {
        if( sb_snum&(1<<2) ) return;
        p->rapid_fire_hold = 0;
    }

    if( sb_snum&(1<<2) && !(p->weapon_pos&127) )
        p->weapon_pos = 129;

    if( p->last_weapon == -1 && p->current_weapon == PHOTON )
    {
        if(p->random_club_frame > 0)
            p->random_club_frame--;
        else p->random_club_frame = 0;
    }

    if( shrunk == 0 && (sb_snum&(1<<2)) && (*kb) == 0 && p->last_weapon == -1 && (p->weapon_pos&127) > 2)
    {
        switch(p->current_weapon)
        {
            case HEAVYHBOMB:
                p->hbomb_hold_delay = 0;
                if( p->ammo_h_amount[p->togweapon4] > 0 )
                    (*kb)=1;
                break;
            case HANDREMOTE:
                p->hbomb_hold_delay = 0;
                (*kb) = 1;
                break;

            case SHOTSPARK1:
                if(p->ammo_amount[p->togweapon2] > 0)
                {
                    p->ammo_amount[p->togweapon2]--;
                    PUS;
                    (*kb) = 1;
                }
                break;

            case PHOTON:

                if(p->ammo_bat_amount[p->togweapon3] > 0)
                    if(p->togweapon3 == 0 || p->random_club_frame == 0)
                    {
                        p->random_club_frame = 30;
                        (*kb)=2;
                        PUS;
                    }
                break;

            case HANDHOLDINGLASER:
                if(p->ammo_hl_amount[p->togweapon7] > 0)
                {
                    long sx,sy,sz;
                    short sect,hw;

                    hitscan(p->posx,p->posy,p->posz-(4<<8),p->cursectnum,
                        sintable[(p->ang+512)&2047],
                        sintable[p->ang&2047],
                        0,&sect,&hw,(short *)&j,&sx,&sy,&sz);

                    if(sect < 0 || j >= 0)
                        break;

                    j = headspritesect[sect];
                    while(j >= 0)
                    {
                        if( sprite[j].picnum == HANDLASER &&
                            klabs(sprite[j].z-sz) < (12<<8) && ((sprite[j].x-sx)*(sprite[j].x-sx)+(sprite[j].y-sy)*(sprite[j].y-sy))
                                < (256*256) )
                                    break;
                        j = nextspritesect[j];
                    }

                    if(j == -1 && hw >= 0)
                        if( ( wall[hw].nextsector >= 0 && sector[wall[hw].nextsector].lotag <= 2 ) || ( wall[hw].nextsector == -1 && sector[sect].lotag <= 2 ) )
                            if( ( (sx-p->posx)*(sx-p->posx) +
                                  (sy-p->posy)*(sy-p->posy) ) < (256*256) )
                        {
                            p->ammo_hl_amount[p->togweapon7]--;
                            PUS;
                            (*kb) = 1;
                        }
                }
                break;

            case RPG:
                if(p->ammo_r_amount[0] > 0)
                    (*kb) = 1;
                break;
            case ALIENWEAPON:
                (*kb) = 1;
                break;
            case SHRINKER:
                if(p->ammo_c_amount[p->togweapon9] > 0)
                {
                    (*kb) = 1;
                    spritesound(SHRINKER_FIRE,p->i);
                }
                break;
            case CATAKILLER:
                if(p->ammo_f_amount[p->togweapon8] > 0)
                    (*kb) = 1;
                break;
            case USERWEAPON:
                (*kb) = 1;
                break;
            case KNEE:
                (*kb) = 1;
                break;
        }
    }

    else if((*kb))
    {
        switch(p->current_weapon)
        {
            case USERWEAPON:
                if( (*kb)/(ud.uw_framerate) < ud.uw_numframes )
                {
                    if( (*kb) == ud.uw_shootframe )
                        shoot(i,ud.uw_bullet);
                    (*kb)++;
                }
                else
                {
                    p->rapid_fire_hold = ud.uw_rapid_on;
                    *kb = 0;
                }
                break;
            case ALIENWEAPON:
                if((*kb) > 8 && (*kb) < 12)
                    shoot(p->i,ALIENWEAPON);
                if( (*kb) > 14 )
                    *kb = 0;
                else (*kb)++;
                break;
            case HEAVYHBOMB:

                if( (*kb) == 6 && (sb_snum&(1<<2)) )
                {
                    p->rapid_fire_hold = 1;
                    break;
                }
                (*kb)++;
                if((*kb)==12)
                {
                    p->ammo_h_amount[p->togweapon4]--;
                    PUS;

                    k = (hits(i) > 768);

                    k = EGS(p->cursectnum,
                        p->posx+(sintable[(p->ang+512)&2047]>>7)*k,
                        p->posy+(sintable[p->ang&2047]>>7)*k,
                        p->posz+(4<<8),HEAVYHBOMB,-16,9,9,
                        p->ang,140+(p->hbomb_hold_delay<<5),((100-p->horiz-32+p->hbomb_hold_delay)*24),p->i,1);

                    if(p->togweapon4)
                    {
                        sprite[k].extra <<= 4;
                        sprite[k].clipdist = 32;
                        sprite[k].pal = 21;
                    }

                    p->hbomb_on = 1;
                }
                else if( (*kb) < 12 && (sb_snum&(1<<2)) )
                    p->hbomb_hold_delay++;
                else if( (*kb) > 19 )
                {
                    p->current_weapon = HANDREMOTE;
                    (*kb)=0;
                    p->weapon_pos = 129;
                }

                break;

            case HANDREMOTE:

                (*kb)++;

                if((*kb) == 2)
                {
                    p->hbomb_on = 0;
                    spritesound(PIPEBOMB_ARMING,p->i);
                }

                if((*kb) == 10)
                {
                    (*kb) = 0;
                    checkavailweapon(p);
                }
                break;

            case SHOTSPARK1:
                if( (*kb)==1)
                {
                    shoot(p->i,SHOTSPARK1);

                    if(p->togweapon2)
                        spritesound(PISTOL_POWER,p->i);
                    else
                        spritesound(PISTOL_NORMAL,p->i);

                    lastvisinc = totalclock+32;
                    p->visibility = 0;
                }
                else if((*kb) == 2)
                    spawn(p->i,SHELL);

                (*kb)++;

                if((*kb) >= 5)
                {
                    if( (p->ammo_amount[p->togweapon2]%12) || (p->ammo_amount[p->togweapon2] <= 0) )
                    {
                        (*kb)=0;
                        checkavailweapon(p);
                    }
                    else
                    {
                        switch((*kb))
                        {
                            case 8:
                                spritesound(EJECT_CLIP,p->i);
                                break;
                            case 11:
                                spritesound(INSERT_CLIP,p->i);
                                break;
                        }
                    }
                }

                if((*kb) == 27)
                {
                    (*kb) = 0;
                    checkavailweapon(p);
                }

                break;

            case PHOTON:

                (*kb)++;

                if((*kb) >= 6)
                {
                    (*kb) = 0;
                    checkavailweapon(p);
                }

                if((*kb)==3)
                {
                    if(p->togweapon3)
                    {
                        shoot(p->i,PHOTON);
                        spritesound(PHOTON_NORMAL,p->i);
                    }
                    else
                    {
                        k = shoot(p->i,FIRELASER);
                        spritesound(PHOTON_POWERUP,p->i);
                        sprite[k].pal = 1;
                    }

                    lastvisinc = totalclock+32;
                    p->visibility = 0;
                }

                break;

            case SHRINKER:
                if( (*kb) > 10)
                {
                    (*kb) = 0;
                    p->rapid_fire_hold = 1;
                    p->ammo_c_amount[p->togweapon9]--;
                    PUS;
                    shoot(p->i,SHRINKER);

                    p->visibility = 0;
                    lastvisinc = totalclock+32;

                    checkavailweapon(p);
                }
                else (*kb)++;
                break;

            case CATAKILLER:

                if( (*kb) < 17 )
                {
                    (*kb)++;
                    if(!p->togweapon8)
                    {
                        if( ((*kb)&3) == 0 )
                        {
                            p->ammo_f_amount[0]--;
                            PUS;
                            p->visibility = 0;
                            lastvisinc = totalclock+32;
                            shoot(p->i,CATAKILLER);
                        }
                    }
                    else if( (*kb) & 1 )
                    {
                        p->ammo_f_amount[1]--;
                        PUS;
                        p->visibility = 0;
                        lastvisinc = totalclock+32;
                        shoot(p->i,CATAKILLER);
                    }
                }
                else
                {
                    if( sb_snum&(1<<2))
                        *kb = 7;
                    else
                        *kb = 0;
                }

                checkavailweapon(p);

                break;
            case HANDHOLDINGLASER:

                if( (*kb) == 3 ) // && hits(p->i) < 512 )
                    shoot(p->i,HANDHOLDINGLASER);
                if((*kb) == 12)
                {
                    (*kb) = 0;
                    checkavailweapon(p);
                }
                else (*kb)++;

                break;
            case KNEE:
                if( *kb < 6 )
                {
                    p->look_ang-= 8;
                    p->horiz -= 16;
                    p->return_to_center = 8;
                }
                if( (p->weapon_pos&127) == 6)
                    (*kb)++;
                if( (*kb) == 7)
                    shoot(p->i,KNEE);
                else if( (*kb) == 14)
                {
                    *kb = 0;
                    p->rapid_fire_hold = 1;
                }

                checkavailweapon(p);

                break;

            case RPG:
                (*kb)++;
                if( (*kb) == 4 )
                {
                    p->ammo_r_amount[p->togweapon5]--;
                    checkavailweapon(p);
                    lastvisinc = totalclock+32;
                    p->visibility = 0;
                    shoot(p->i,RPG);
                    PUS;
                }
                else if(*kb == 12)
                    *kb = 0;
                break;
        }
    }
}
