526 lines · 12.0 KB · C
RawDownload
// cl.input.c  -- builds an intended movement command to send to the server #include <u.h>#include <libc.h>#include <stdio.h>#include "dat.h"#include "fns.h" cvar_t	*cl_nodelta; unsigned	frame_msec;unsigned	old_sys_frame_time; /*=============================================================================== KEY BUTTONS Continuous button event tracking is complicated by the fact that two differentinput sources (say, mouse button 1 and the control key) can both press thesame button, but the button should only be released when both of thepressing key have been released. When a key event issues a button command (+forward, +attack, etc), it appendsits key number as a parameter to the command so it can be matched up withthe release. state bit 0 is the current state of the keystate bit 1 is edge triggered on the up to down transitionstate bit 2 is edge triggered on the down to up transition  Key_Event (int key, qboolean down, unsigned time);   +mlook src time ===============================================================================*/  kbutton_t	in_klook;kbutton_t	in_left, in_right, in_forward, in_back;kbutton_t	in_lookup, in_lookdown, in_moveleft, in_moveright;kbutton_t	in_strafe, in_speed, in_use, in_attack;kbutton_t	in_up, in_down; int			in_impulse;  void KeyDown (kbutton_t *b){	int		k;	char	*c;		c = Cmd_Argv(1);	if (c[0])		k = atoi(c);	else		k = -1;		// typed manually at the console for continuous down 	if (k == b->down[0] || k == b->down[1])		return;		// repeating key		if (!b->down[0])		b->down[0] = k;	else if (!b->down[1])		b->down[1] = k;	else	{		Com_Printf ("Three keys down for a button!\n");		return;	}		if (b->state & 1)		return;		// still down 	// save timestamp	c = Cmd_Argv(2);	b->downtime = atoi(c);	if (!b->downtime)		b->downtime = sys_frame_time - 100; 	b->state |= 1 + 2;	// down + impulse down} void KeyUp (kbutton_t *b){	int		k;	char	*c;	unsigned	uptime; 	c = Cmd_Argv(1);	if (c[0])		k = atoi(c);	else	{ // typed manually at the console, assume for unsticking, so clear all		b->down[0] = b->down[1] = 0;		b->state = 4;	// impulse up		return;	} 	if (b->down[0] == k)		b->down[0] = 0;	else if (b->down[1] == k)		b->down[1] = 0;	else		return;		// key up without coresponding down (menu pass through)	if (b->down[0] || b->down[1])		return;		// some other key is still holding it down 	if (!(b->state & 1))		return;		// still up (this should not happen) 	// save timestamp	c = Cmd_Argv(2);	uptime = atoi(c);	if (uptime)		b->msec += uptime - b->downtime;	else		b->msec += 10; 	b->state &= ~1;		// now up	b->state |= 4; 		// impulse up} void IN_KLookDown (void) {KeyDown(&in_klook);}void IN_KLookUp (void) {KeyUp(&in_klook);}void IN_UpDown(void) {KeyDown(&in_up);}void IN_UpUp(void) {KeyUp(&in_up);}void IN_DownDown(void) {KeyDown(&in_down);}void IN_DownUp(void) {KeyUp(&in_down);}void IN_LeftDown(void) {KeyDown(&in_left);}void IN_LeftUp(void) {KeyUp(&in_left);}void IN_RightDown(void) {KeyDown(&in_right);}void IN_RightUp(void) {KeyUp(&in_right);}void IN_ForwardDown(void) {KeyDown(&in_forward);}void IN_ForwardUp(void) {KeyUp(&in_forward);}void IN_BackDown(void) {KeyDown(&in_back);}void IN_BackUp(void) {KeyUp(&in_back);}void IN_LookupDown(void) {KeyDown(&in_lookup);}void IN_LookupUp(void) {KeyUp(&in_lookup);}void IN_LookdownDown(void) {KeyDown(&in_lookdown);}void IN_LookdownUp(void) {KeyUp(&in_lookdown);}void IN_MoveleftDown(void) {KeyDown(&in_moveleft);}void IN_MoveleftUp(void) {KeyUp(&in_moveleft);}void IN_MoverightDown(void) {KeyDown(&in_moveright);}void IN_MoverightUp(void) {KeyUp(&in_moveright);} void IN_SpeedDown(void) {KeyDown(&in_speed);}void IN_SpeedUp(void) {KeyUp(&in_speed);}void IN_StrafeDown(void) {KeyDown(&in_strafe);}void IN_StrafeUp(void) {KeyUp(&in_strafe);} void IN_AttackDown(void) {KeyDown(&in_attack);}void IN_AttackUp(void) {KeyUp(&in_attack);} void IN_UseDown (void) {KeyDown(&in_use);}void IN_UseUp (void) {KeyUp(&in_use);} void IN_Impulse (void) {in_impulse=atoi(Cmd_Argv(1));} /*===============CL_KeyState Returns the fraction of the frame that the key was down===============*/float CL_KeyState (kbutton_t *key){	float		val;	int			msec; 	key->state &= 1;		// clear impulses 	msec = key->msec;	key->msec = 0; 	if (key->state)	{	// still down		msec += sys_frame_time - key->downtime;		key->downtime = sys_frame_time;	} /*	if (msec)	{		Com_Printf ("%i ", msec);	}*/ 	val = (float)msec / frame_msec;	if (val < 0)		val = 0;	if (val > 1)		val = 1; 	return val;}    //========================================================================== cvar_t	*cl_upspeed;cvar_t	*cl_forwardspeed;cvar_t	*cl_sidespeed; cvar_t	*cl_yawspeed;cvar_t	*cl_pitchspeed; cvar_t	*cl_run; cvar_t	*cl_anglespeedkey;  /*================CL_AdjustAngles Moves the local angle positions================*/void CL_AdjustAngles (void){	float	speed;	float	up, down;		if (in_speed.state & 1)		speed = cls.frametime * cl_anglespeedkey->value;	else		speed = cls.frametime; 	if (!(in_strafe.state & 1))	{		cl.viewangles[YAW] -= speed*cl_yawspeed->value*CL_KeyState (&in_right);		cl.viewangles[YAW] += speed*cl_yawspeed->value*CL_KeyState (&in_left);	}	if (in_klook.state & 1)	{		cl.viewangles[PITCH] -= speed*cl_pitchspeed->value * CL_KeyState (&in_forward);		cl.viewangles[PITCH] += speed*cl_pitchspeed->value * CL_KeyState (&in_back);	}		up = CL_KeyState (&in_lookup);	down = CL_KeyState(&in_lookdown);		cl.viewangles[PITCH] -= speed*cl_pitchspeed->value * up;	cl.viewangles[PITCH] += speed*cl_pitchspeed->value * down;} /*================CL_BaseMove Send the intended movement message to the server================*/void CL_BaseMove (usercmd_t *cmd){		CL_AdjustAngles ();		memset (cmd, 0, sizeof(*cmd));		VectorCopy (cl.viewangles, cmd->angles);	if (in_strafe.state & 1)	{		cmd->sidemove += cl_sidespeed->value * CL_KeyState (&in_right);		cmd->sidemove -= cl_sidespeed->value * CL_KeyState (&in_left);	} 	cmd->sidemove += cl_sidespeed->value * CL_KeyState (&in_moveright);	cmd->sidemove -= cl_sidespeed->value * CL_KeyState (&in_moveleft); 	cmd->upmove += cl_upspeed->value * CL_KeyState (&in_up);	cmd->upmove -= cl_upspeed->value * CL_KeyState (&in_down); 	if (! (in_klook.state & 1) )	{			cmd->forwardmove += cl_forwardspeed->value * CL_KeyState (&in_forward);		cmd->forwardmove -= cl_forwardspeed->value * CL_KeyState (&in_back);	}	 //// adjust for speed key / running//	if ( (in_speed.state & 1) ^ (int)(cl_run->value) )	{		cmd->forwardmove *= 2;		cmd->sidemove *= 2;		cmd->upmove *= 2;	}	} void CL_ClampPitch (void){	float	pitch; 	pitch = SHORT2ANGLE(cl.frame.playerstate.pmove.delta_angles[PITCH]);	if (pitch > 180)		pitch -= 360;	if (cl.viewangles[PITCH] + pitch > 89)		cl.viewangles[PITCH] = 89 - pitch;	if (cl.viewangles[PITCH] + pitch < -89)		cl.viewangles[PITCH] = -89 - pitch;} /*==============CL_FinishMove==============*/void CL_FinishMove (usercmd_t *cmd){	int		ms;	int		i; //// figure button bits//		if ( in_attack.state & 3 )		cmd->buttons |= BUTTON_ATTACK;	in_attack.state &= ~2;		if (in_use.state & 3)		cmd->buttons |= BUTTON_USE;	in_use.state &= ~2; 	if (anykeydown && cls.key_dest == key_game)		cmd->buttons |= BUTTON_ANY; 	// send milliseconds of time to apply the move	ms = cls.frametime * 1000;	if (ms > 250)		ms = 100;		// time was unreasonable	cmd->msec = ms; 	CL_ClampPitch ();	for (i=0 ; i<3 ; i++)		cmd->angles[i] = ANGLE2SHORT(cl.viewangles[i]); 	cmd->impulse = in_impulse;	in_impulse = 0; // send the ambient light level at the player's current position	cmd->lightlevel = (byte)cl_lightlevel->value;} /*=================CL_CreateCmd=================*/usercmd_t CL_CreateCmd (void){	usercmd_t	cmd; 	frame_msec = sys_frame_time - old_sys_frame_time;	if (frame_msec < 1)		frame_msec = 1;	if (frame_msec > 200)		frame_msec = 200;		// get basic movement from keyboard	CL_BaseMove (&cmd); 	// allow mice or other external controllers to add to the move	IN_Move (&cmd); 	CL_FinishMove (&cmd); 	old_sys_frame_time = sys_frame_time; //cmd.impulse = cls.framecount; 	return cmd;}  void IN_CenterView (void){	cl.viewangles[PITCH] = -SHORT2ANGLE(cl.frame.playerstate.pmove.delta_angles[PITCH]);} /*============CL_InitInput============*/void CL_InitInput (void){	Cmd_AddCommand ("centerview",IN_CenterView); 	Cmd_AddCommand ("+moveup",IN_UpDown);	Cmd_AddCommand ("-moveup",IN_UpUp);	Cmd_AddCommand ("+movedown",IN_DownDown);	Cmd_AddCommand ("-movedown",IN_DownUp);	Cmd_AddCommand ("+left",IN_LeftDown);	Cmd_AddCommand ("-left",IN_LeftUp);	Cmd_AddCommand ("+right",IN_RightDown);	Cmd_AddCommand ("-right",IN_RightUp);	Cmd_AddCommand ("+forward",IN_ForwardDown);	Cmd_AddCommand ("-forward",IN_ForwardUp);	Cmd_AddCommand ("+back",IN_BackDown);	Cmd_AddCommand ("-back",IN_BackUp);	Cmd_AddCommand ("+lookup", IN_LookupDown);	Cmd_AddCommand ("-lookup", IN_LookupUp);	Cmd_AddCommand ("+lookdown", IN_LookdownDown);	Cmd_AddCommand ("-lookdown", IN_LookdownUp);	Cmd_AddCommand ("+strafe", IN_StrafeDown);	Cmd_AddCommand ("-strafe", IN_StrafeUp);	Cmd_AddCommand ("+moveleft", IN_MoveleftDown);	Cmd_AddCommand ("-moveleft", IN_MoveleftUp);	Cmd_AddCommand ("+moveright", IN_MoverightDown);	Cmd_AddCommand ("-moveright", IN_MoverightUp);	Cmd_AddCommand ("+speed", IN_SpeedDown);	Cmd_AddCommand ("-speed", IN_SpeedUp);	Cmd_AddCommand ("+attack", IN_AttackDown);	Cmd_AddCommand ("-attack", IN_AttackUp);	Cmd_AddCommand ("+use", IN_UseDown);	Cmd_AddCommand ("-use", IN_UseUp);	Cmd_AddCommand ("impulse", IN_Impulse);	Cmd_AddCommand ("+klook", IN_KLookDown);	Cmd_AddCommand ("-klook", IN_KLookUp); 	cl_nodelta = Cvar_Get ("cl_nodelta", "0", 0);}   /*=================CL_SendCmd=================*/void CL_SendCmd (void){	sizebuf_t	buf;	byte		data[128];	int			i;	usercmd_t	*cmd, *oldcmd;	usercmd_t	nullcmd;	int			checksumIndex; 	// build a command even if not connected 	// save this command off for prediction	i = cls.netchan.outgoing_sequence & (CMD_BACKUP-1);	cmd = &cl.cmds[i];	cl.cmd_time[i] = cls.realtime;	// for netgraph ping calculation 	*cmd = CL_CreateCmd (); 	cl.cmd = *cmd; 	if (cls.state == ca_disconnected || cls.state == ca_connecting)		return; 	if ( cls.state == ca_connected)	{		if (cls.netchan.message.cursize	|| curtime - cls.netchan.last_sent > 1000 )			Netchan_Transmit (&cls.netchan, 0, buf.data);			return;	} 	// send a userinfo update if needed	if (userinfo_modified)	{		CL_FixUpGender();		userinfo_modified = false;		MSG_WriteByte (&cls.netchan.message, clc_userinfo);		MSG_WriteString (&cls.netchan.message, Cvar_Userinfo() );	} 	SZ_Init (&buf, data, sizeof(data)); 	if (cmd->buttons && cl.cinematictime > 0 && !cl.attractloop 		&& cls.realtime - cl.cinematictime > 1000)	{	// skip the rest of the cinematic		SCR_FinishCinematic ();	} 	// begin a client move command	MSG_WriteByte (&buf, clc_move); 	// save the position for a checksum byte	checksumIndex = buf.cursize;	MSG_WriteByte (&buf, 0); 	// let the server know what the last frame we	// got was, so the next message can be delta compressed	if (cl_nodelta->value || !cl.frame.valid || cls.demowaiting)		MSG_WriteLong (&buf, -1);	// no compression	else		MSG_WriteLong (&buf, cl.frame.serverframe); 	// send this and the previous cmds in the message, so	// if the last packet was dropped, it can be recovered	i = (cls.netchan.outgoing_sequence-2) & (CMD_BACKUP-1);

Lines 1–500 of 526.

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t