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

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

unix.superglobalmegacorp.com

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