Annotation of quake2/client/cl_input.c, revision 1.1

1.1     ! root        1: // cl.input.c  -- builds an intended movement command to send to the server
        !             2: 
        !             3: #include "client.h"
        !             4: 
        !             5: cvar_t *cl_nodelta;
        !             6: 
        !             7: extern unsigned        sys_frame_time;
        !             8: unsigned       frame_msec;
        !             9: unsigned       old_sys_frame_time;
        !            10: 
        !            11: /*
        !            12: ===============================================================================
        !            13: 
        !            14: KEY BUTTONS
        !            15: 
        !            16: Continuous button event tracking is complicated by the fact that two different
        !            17: input sources (say, mouse button 1 and the control key) can both press the
        !            18: same button, but the button should only be released when both of the
        !            19: pressing key have been released.
        !            20: 
        !            21: When a key event issues a button command (+forward, +attack, etc), it appends
        !            22: its key number as a parameter to the command so it can be matched up with
        !            23: the release.
        !            24: 
        !            25: state bit 0 is the current state of the key
        !            26: state bit 1 is edge triggered on the up to down transition
        !            27: state bit 2 is edge triggered on the down to up transition
        !            28: 
        !            29: 
        !            30: Key_Event (int key, qboolean down, unsigned time);
        !            31: 
        !            32:   +mlook src time
        !            33: 
        !            34: ===============================================================================
        !            35: */
        !            36: 
        !            37: 
        !            38: kbutton_t      in_klook;
        !            39: kbutton_t      in_left, in_right, in_forward, in_back;
        !            40: kbutton_t      in_lookup, in_lookdown, in_moveleft, in_moveright;
        !            41: kbutton_t      in_strafe, in_speed, in_use, in_attack;
        !            42: kbutton_t      in_up, in_down;
        !            43: 
        !            44: int                    in_impulse;
        !            45: 
        !            46: 
        !            47: void KeyDown (kbutton_t *b)
        !            48: {
        !            49:        int             k;
        !            50:        char    *c;
        !            51:        
        !            52:        c = Cmd_Argv(1);
        !            53:        if (c[0])
        !            54:                k = atoi(c);
        !            55:        else
        !            56:                k = -1;         // typed manually at the console for continuous down
        !            57: 
        !            58:        if (k == b->down[0] || k == b->down[1])
        !            59:                return;         // repeating key
        !            60:        
        !            61:        if (!b->down[0])
        !            62:                b->down[0] = k;
        !            63:        else if (!b->down[1])
        !            64:                b->down[1] = k;
        !            65:        else
        !            66:        {
        !            67:                Com_Printf ("Three keys down for a button!\n");
        !            68:                return;
        !            69:        }
        !            70:        
        !            71:        if (b->state & 1)
        !            72:                return;         // still down
        !            73: 
        !            74:        // save timestamp
        !            75:        c = Cmd_Argv(2);
        !            76:        b->downtime = atoi(c);
        !            77:        if (!b->downtime)
        !            78:                b->downtime = sys_frame_time - 100;
        !            79: 
        !            80:        b->state |= 1 + 2;      // down + impulse down
        !            81: }
        !            82: 
        !            83: void KeyUp (kbutton_t *b)
        !            84: {
        !            85:        int             k;
        !            86:        char    *c;
        !            87:        unsigned        uptime;
        !            88: 
        !            89:        c = Cmd_Argv(1);
        !            90:        if (c[0])
        !            91:                k = atoi(c);
        !            92:        else
        !            93:        { // typed manually at the console, assume for unsticking, so clear all
        !            94:                b->down[0] = b->down[1] = 0;
        !            95:                b->state = 4;   // impulse up
        !            96:                return;
        !            97:        }
        !            98: 
        !            99:        if (b->down[0] == k)
        !           100:                b->down[0] = 0;
        !           101:        else if (b->down[1] == k)
        !           102:                b->down[1] = 0;
        !           103:        else
        !           104:                return;         // key up without coresponding down (menu pass through)
        !           105:        if (b->down[0] || b->down[1])
        !           106:                return;         // some other key is still holding it down
        !           107: 
        !           108:        if (!(b->state & 1))
        !           109:                return;         // still up (this should not happen)
        !           110: 
        !           111:        // save timestamp
        !           112:        c = Cmd_Argv(2);
        !           113:        uptime = atoi(c);
        !           114:        if (uptime)
        !           115:                b->msec += uptime - b->downtime;
        !           116:        else
        !           117:                b->msec += 10;
        !           118: 
        !           119:        b->state &= ~1;         // now up
        !           120:        b->state |= 4;          // impulse up
        !           121: }
        !           122: 
        !           123: void IN_KLookDown (void) {KeyDown(&in_klook);}
        !           124: void IN_KLookUp (void) {KeyUp(&in_klook);}
        !           125: void IN_UpDown(void) {KeyDown(&in_up);}
        !           126: void IN_UpUp(void) {KeyUp(&in_up);}
        !           127: void IN_DownDown(void) {KeyDown(&in_down);}
        !           128: void IN_DownUp(void) {KeyUp(&in_down);}
        !           129: void IN_LeftDown(void) {KeyDown(&in_left);}
        !           130: void IN_LeftUp(void) {KeyUp(&in_left);}
        !           131: void IN_RightDown(void) {KeyDown(&in_right);}
        !           132: void IN_RightUp(void) {KeyUp(&in_right);}
        !           133: void IN_ForwardDown(void) {KeyDown(&in_forward);}
        !           134: void IN_ForwardUp(void) {KeyUp(&in_forward);}
        !           135: void IN_BackDown(void) {KeyDown(&in_back);}
        !           136: void IN_BackUp(void) {KeyUp(&in_back);}
        !           137: void IN_LookupDown(void) {KeyDown(&in_lookup);}
        !           138: void IN_LookupUp(void) {KeyUp(&in_lookup);}
        !           139: void IN_LookdownDown(void) {KeyDown(&in_lookdown);}
        !           140: void IN_LookdownUp(void) {KeyUp(&in_lookdown);}
        !           141: void IN_MoveleftDown(void) {KeyDown(&in_moveleft);}
        !           142: void IN_MoveleftUp(void) {KeyUp(&in_moveleft);}
        !           143: void IN_MoverightDown(void) {KeyDown(&in_moveright);}
        !           144: void IN_MoverightUp(void) {KeyUp(&in_moveright);}
        !           145: 
        !           146: void IN_SpeedDown(void) {KeyDown(&in_speed);}
        !           147: void IN_SpeedUp(void) {KeyUp(&in_speed);}
        !           148: void IN_StrafeDown(void) {KeyDown(&in_strafe);}
        !           149: void IN_StrafeUp(void) {KeyUp(&in_strafe);}
        !           150: 
        !           151: void IN_AttackDown(void) {KeyDown(&in_attack);}
        !           152: void IN_AttackUp(void) {KeyUp(&in_attack);}
        !           153: 
        !           154: void IN_UseDown (void) {KeyDown(&in_use);}
        !           155: void IN_UseUp (void) {KeyUp(&in_use);}
        !           156: 
        !           157: void IN_Impulse (void) {in_impulse=atoi(Cmd_Argv(1));}
        !           158: 
        !           159: /*
        !           160: ===============
        !           161: CL_KeyState
        !           162: 
        !           163: Returns the fraction of the frame that the key was down
        !           164: ===============
        !           165: */
        !           166: float CL_KeyState (kbutton_t *key)
        !           167: {
        !           168:        float           val;
        !           169:        int                     msec;
        !           170: 
        !           171:        key->state &= 1;                // clear impulses
        !           172: 
        !           173:        msec = key->msec;
        !           174:        key->msec = 0;
        !           175: 
        !           176:        if (key->state)
        !           177:        {       // still down
        !           178:                msec += sys_frame_time - key->downtime;
        !           179:                key->downtime = sys_frame_time;
        !           180:        }
        !           181: 
        !           182: #if 0
        !           183:        if (msec)
        !           184:        {
        !           185:                Com_Printf ("%i ", msec);
        !           186:        }
        !           187: #endif
        !           188: 
        !           189:        val = (float)msec / frame_msec;
        !           190:        if (val < 0)
        !           191:                val = 0;
        !           192:        if (val > 1)
        !           193:                val = 1;
        !           194: 
        !           195:        return val;
        !           196: }
        !           197: 
        !           198: 
        !           199: 
        !           200: 
        !           201: //==========================================================================
        !           202: 
        !           203: cvar_t *cl_upspeed;
        !           204: cvar_t *cl_forwardspeed;
        !           205: cvar_t *cl_sidespeed;
        !           206: 
        !           207: cvar_t *cl_yawspeed;
        !           208: cvar_t *cl_pitchspeed;
        !           209: 
        !           210: cvar_t *cl_run;
        !           211: 
        !           212: cvar_t *cl_anglespeedkey;
        !           213: 
        !           214: 
        !           215: /*
        !           216: ================
        !           217: CL_AdjustAngles
        !           218: 
        !           219: Moves the local angle positions
        !           220: ================
        !           221: */
        !           222: void CL_AdjustAngles (void)
        !           223: {
        !           224:        float   speed;
        !           225:        float   up, down;
        !           226:        
        !           227:        if (in_speed.state & 1)
        !           228:                speed = cls.frametime * cl_anglespeedkey->value;
        !           229:        else
        !           230:                speed = cls.frametime;
        !           231: 
        !           232:        if (!(in_strafe.state & 1))
        !           233:        {
        !           234:                cl.viewangles[YAW] -= speed*cl_yawspeed->value*CL_KeyState (&in_right);
        !           235:                cl.viewangles[YAW] += speed*cl_yawspeed->value*CL_KeyState (&in_left);
        !           236:        }
        !           237:        if (in_klook.state & 1)
        !           238:        {
        !           239:                cl.viewangles[PITCH] -= speed*cl_pitchspeed->value * CL_KeyState (&in_forward);
        !           240:                cl.viewangles[PITCH] += speed*cl_pitchspeed->value * CL_KeyState (&in_back);
        !           241:        }
        !           242:        
        !           243:        up = CL_KeyState (&in_lookup);
        !           244:        down = CL_KeyState(&in_lookdown);
        !           245:        
        !           246:        cl.viewangles[PITCH] -= speed*cl_pitchspeed->value * up;
        !           247:        cl.viewangles[PITCH] += speed*cl_pitchspeed->value * down;
        !           248: }
        !           249: 
        !           250: /*
        !           251: ================
        !           252: CL_BaseMove
        !           253: 
        !           254: Send the intended movement message to the server
        !           255: ================
        !           256: */
        !           257: void CL_BaseMove (usercmd_t *cmd)
        !           258: {      
        !           259:        CL_AdjustAngles ();
        !           260:        
        !           261:        memset (cmd, 0, sizeof(*cmd));
        !           262:        
        !           263:        VectorCopy (cl.viewangles, cmd->angles);
        !           264:        if (in_strafe.state & 1)
        !           265:        {
        !           266:                cmd->sidemove += cl_sidespeed->value * CL_KeyState (&in_right);
        !           267:                cmd->sidemove -= cl_sidespeed->value * CL_KeyState (&in_left);
        !           268:        }
        !           269: 
        !           270:        cmd->sidemove += cl_sidespeed->value * CL_KeyState (&in_moveright);
        !           271:        cmd->sidemove -= cl_sidespeed->value * CL_KeyState (&in_moveleft);
        !           272: 
        !           273:        cmd->upmove += cl_upspeed->value * CL_KeyState (&in_up);
        !           274:        cmd->upmove -= cl_upspeed->value * CL_KeyState (&in_down);
        !           275: 
        !           276:        if (! (in_klook.state & 1) )
        !           277:        {       
        !           278:                cmd->forwardmove += cl_forwardspeed->value * CL_KeyState (&in_forward);
        !           279:                cmd->forwardmove -= cl_forwardspeed->value * CL_KeyState (&in_back);
        !           280:        }       
        !           281: 
        !           282: //
        !           283: // adjust for speed key / running
        !           284: //
        !           285:        if ( (in_speed.state & 1) ^ (int)(cl_run->value) )
        !           286:        {
        !           287:                cmd->forwardmove *= 2;
        !           288:                cmd->sidemove *= 2;
        !           289:                cmd->upmove *= 2;
        !           290:        }       
        !           291: }
        !           292: 
        !           293: void CL_ClampPitch (void)
        !           294: {
        !           295:        float   pitch;
        !           296: 
        !           297:        pitch = SHORT2ANGLE(cl.frame.playerstate.pmove.delta_angles[PITCH]);
        !           298:        if (pitch > 180)
        !           299:                pitch -= 360;
        !           300:        if (cl.viewangles[PITCH] + pitch > 89)
        !           301:                cl.viewangles[PITCH] = 89 - pitch;
        !           302:        if (cl.viewangles[PITCH] + pitch < -89)
        !           303:                cl.viewangles[PITCH] = -89 - pitch;
        !           304: }
        !           305: 
        !           306: /*
        !           307: ==============
        !           308: CL_FinishMove
        !           309: ==============
        !           310: */
        !           311: void CL_FinishMove (usercmd_t *cmd)
        !           312: {
        !           313:        int             ms;
        !           314:        int             i;
        !           315: 
        !           316: //
        !           317: // figure button bits
        !           318: //     
        !           319:        if ( in_attack.state & 3 )
        !           320:                cmd->buttons |= BUTTON_ATTACK;
        !           321:        in_attack.state &= ~2;
        !           322:        
        !           323:        if (in_use.state & 3)
        !           324:                cmd->buttons |= BUTTON_USE;
        !           325:        in_use.state &= ~2;
        !           326: 
        !           327:        if (anykeydown && cls.key_dest == key_game)
        !           328:                cmd->buttons |= BUTTON_ANY;
        !           329: 
        !           330:        // send milliseconds of time to apply the move
        !           331:        ms = cls.frametime * 1000;
        !           332:        if (ms > 250)
        !           333:                ms = 100;               // time was unreasonable
        !           334:        cmd->msec = ms;
        !           335: 
        !           336:        CL_ClampPitch ();
        !           337:        for (i=0 ; i<3 ; i++)
        !           338:                cmd->angles[i] = ANGLE2SHORT(cl.viewangles[i]);
        !           339: 
        !           340:        cmd->impulse = in_impulse;
        !           341:        in_impulse = 0;
        !           342: 
        !           343: // send the ambient light level at the player's current position
        !           344:        cmd->lightlevel = (byte)cl_lightlevel->value;
        !           345: }
        !           346: 
        !           347: /*
        !           348: =================
        !           349: CL_CreateCmd
        !           350: =================
        !           351: */
        !           352: usercmd_t CL_CreateCmd (void)
        !           353: {
        !           354:        usercmd_t       cmd;
        !           355: 
        !           356:        frame_msec = sys_frame_time - old_sys_frame_time;
        !           357:        if (frame_msec < 1)
        !           358:                frame_msec = 1;
        !           359:        if (frame_msec > 200)
        !           360:                frame_msec = 200;
        !           361:        
        !           362:        // get basic movement from keyboard
        !           363:        CL_BaseMove (&cmd);
        !           364: 
        !           365:        // allow mice or other external controllers to add to the move
        !           366:        IN_Move (&cmd);
        !           367: 
        !           368:        CL_FinishMove (&cmd);
        !           369: 
        !           370:        old_sys_frame_time = sys_frame_time;
        !           371: 
        !           372: //cmd.impulse = cls.framecount;
        !           373: 
        !           374:        return cmd;
        !           375: }
        !           376: 
        !           377: 
        !           378: void IN_CenterView (void)
        !           379: {
        !           380:        cl.viewangles[PITCH] = -SHORT2ANGLE(cl.frame.playerstate.pmove.delta_angles[PITCH]);
        !           381: }
        !           382: 
        !           383: /*
        !           384: ============
        !           385: CL_InitInput
        !           386: ============
        !           387: */
        !           388: void CL_InitInput (void)
        !           389: {
        !           390:        Cmd_AddCommand ("centerview",IN_CenterView);
        !           391: 
        !           392:        Cmd_AddCommand ("+moveup",IN_UpDown);
        !           393:        Cmd_AddCommand ("-moveup",IN_UpUp);
        !           394:        Cmd_AddCommand ("+movedown",IN_DownDown);
        !           395:        Cmd_AddCommand ("-movedown",IN_DownUp);
        !           396:        Cmd_AddCommand ("+left",IN_LeftDown);
        !           397:        Cmd_AddCommand ("-left",IN_LeftUp);
        !           398:        Cmd_AddCommand ("+right",IN_RightDown);
        !           399:        Cmd_AddCommand ("-right",IN_RightUp);
        !           400:        Cmd_AddCommand ("+forward",IN_ForwardDown);
        !           401:        Cmd_AddCommand ("-forward",IN_ForwardUp);
        !           402:        Cmd_AddCommand ("+back",IN_BackDown);
        !           403:        Cmd_AddCommand ("-back",IN_BackUp);
        !           404:        Cmd_AddCommand ("+lookup", IN_LookupDown);
        !           405:        Cmd_AddCommand ("-lookup", IN_LookupUp);
        !           406:        Cmd_AddCommand ("+lookdown", IN_LookdownDown);
        !           407:        Cmd_AddCommand ("-lookdown", IN_LookdownUp);
        !           408:        Cmd_AddCommand ("+strafe", IN_StrafeDown);
        !           409:        Cmd_AddCommand ("-strafe", IN_StrafeUp);
        !           410:        Cmd_AddCommand ("+moveleft", IN_MoveleftDown);
        !           411:        Cmd_AddCommand ("-moveleft", IN_MoveleftUp);
        !           412:        Cmd_AddCommand ("+moveright", IN_MoverightDown);
        !           413:        Cmd_AddCommand ("-moveright", IN_MoverightUp);
        !           414:        Cmd_AddCommand ("+speed", IN_SpeedDown);
        !           415:        Cmd_AddCommand ("-speed", IN_SpeedUp);
        !           416:        Cmd_AddCommand ("+attack", IN_AttackDown);
        !           417:        Cmd_AddCommand ("-attack", IN_AttackUp);
        !           418:        Cmd_AddCommand ("+use", IN_UseDown);
        !           419:        Cmd_AddCommand ("-use", IN_UseUp);
        !           420:        Cmd_AddCommand ("impulse", IN_Impulse);
        !           421:        Cmd_AddCommand ("+klook", IN_KLookDown);
        !           422:        Cmd_AddCommand ("-klook", IN_KLookUp);
        !           423: 
        !           424:        cl_nodelta = Cvar_Get ("cl_nodelta", "0", 0);
        !           425: }
        !           426: 
        !           427: 
        !           428: 
        !           429: /*
        !           430: =================
        !           431: CL_SendCmd
        !           432: =================
        !           433: */
        !           434: void CL_SendCmd (void)
        !           435: {
        !           436:        sizebuf_t       buf;
        !           437:        byte            data[128];
        !           438:        int                     i;
        !           439:        usercmd_t       *cmd, *oldcmd;
        !           440:        usercmd_t       nullcmd;
        !           441:        int                     checksumIndex;
        !           442: 
        !           443:        // build a command even if not connected
        !           444: 
        !           445:        // save this command off for prediction
        !           446:        i = cls.netchan.outgoing_sequence & (CMD_BACKUP-1);
        !           447:        cmd = &cl.cmds[i];
        !           448:        cl.cmd_time[i] = cls.realtime;  // for netgraph ping calculation
        !           449: 
        !           450:        *cmd = CL_CreateCmd ();
        !           451: 
        !           452:        cl.cmd = *cmd;
        !           453: 
        !           454:        if (cls.state == ca_disconnected || cls.state == ca_connecting)
        !           455:                return;
        !           456: 
        !           457:        if ( cls.state == ca_connected)
        !           458:        {
        !           459:                if (cls.netchan.message.cursize || curtime - cls.netchan.last_sent > 1000 )
        !           460:                        Netchan_Transmit (&cls.netchan, 0, buf.data);   
        !           461:                return;
        !           462:        }
        !           463: 
        !           464:        // send a userinfo update if needed
        !           465:        if (userinfo_modified)
        !           466:        {
        !           467:                userinfo_modified = false;
        !           468:                MSG_WriteByte (&cls.netchan.message, clc_userinfo);
        !           469:                MSG_WriteString (&cls.netchan.message, Cvar_Userinfo() );
        !           470:        }
        !           471: 
        !           472:        SZ_Init (&buf, data, sizeof(data));
        !           473: 
        !           474:        if (cmd->buttons && cl.cinematictime > 0 && !cl.attractloop 
        !           475:                && cls.realtime - cl.cinematictime > 1000)
        !           476:        {       // skip the rest of the cinematic
        !           477:                SCR_FinishCinematic ();
        !           478:        }
        !           479: 
        !           480:        // begin a client move command
        !           481:        MSG_WriteByte (&buf, clc_move);
        !           482: 
        !           483:        // save the position for a checksum byte
        !           484:        checksumIndex = buf.cursize;
        !           485:        MSG_WriteByte (&buf, 0);
        !           486: 
        !           487:        // let the server know what the last frame we
        !           488:        // got was, so the next message can be delta compressed
        !           489:        if (cl_nodelta->value || !cl.frame.valid || cls.demowaiting)
        !           490:                MSG_WriteLong (&buf, -1);       // no compression
        !           491:        else
        !           492:                MSG_WriteLong (&buf, cl.frame.serverframe);
        !           493: 
        !           494:        // send this and the previous cmds in the message, so
        !           495:        // if the last packet was dropped, it can be recovered
        !           496:        i = (cls.netchan.outgoing_sequence-2) & (CMD_BACKUP-1);
        !           497:        cmd = &cl.cmds[i];
        !           498:        memset (&nullcmd, 0, sizeof(nullcmd));
        !           499:        MSG_WriteDeltaUsercmd (&buf, &nullcmd, cmd);
        !           500:        oldcmd = cmd;
        !           501: 
        !           502:        i = (cls.netchan.outgoing_sequence-1) & (CMD_BACKUP-1);
        !           503:        cmd = &cl.cmds[i];
        !           504:        MSG_WriteDeltaUsercmd (&buf, oldcmd, cmd);
        !           505:        oldcmd = cmd;
        !           506: 
        !           507:        i = (cls.netchan.outgoing_sequence) & (CMD_BACKUP-1);
        !           508:        cmd = &cl.cmds[i];
        !           509:        MSG_WriteDeltaUsercmd (&buf, oldcmd, cmd);
        !           510: 
        !           511:        // calculate a checksum over the move commands
        !           512:        buf.data[checksumIndex] = COM_BlockSequenceCheckByte(
        !           513:                buf.data + checksumIndex + 1, buf.cursize - checksumIndex - 1,
        !           514:                cls.netchan.outgoing_sequence);
        !           515: 
        !           516:        //
        !           517:        // deliver the message
        !           518:        //
        !           519:        Netchan_Transmit (&cls.netchan, buf.cursize, buf.data); 
        !           520: }
        !           521: 
        !           522: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.