#include "client.h"
cvar_t *cl_nodelta;
extern unsigned sys_frame_time;
unsigned frame_msec;
unsigned old_sys_frame_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;
if(k == b->down[0] || k == b->down[1])
return;
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;
c = Cmd_Argv(2);
b->downtime = atoi(c);
if(!b->downtime)
b->downtime = sys_frame_time - 100;
b->state |= 1 + 2; }
void KeyUp(kbutton_t *b) {
int k;
char *c;
unsigned uptime;
c = Cmd_Argv(1);
if(c[0])
k = atoi(c);
else { b->down[0] = b->down[1] = 0;
b->state = 4; return;
}
if(b->down[0] == k)
b->down[0] = 0;
else if(b->down[1] == k)
b->down[1] = 0;
else
return; if(b->down[0] || b->down[1])
return;
if(!(b->state & 1))
return;
c = Cmd_Argv(2);
uptime = atoi(c);
if(uptime)
b->msec += uptime - b->downtime;
else
b->msec += 10;
b->state &= ~1; b->state |= 4; }
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)); }
float CL_KeyState(kbutton_t *key) {
float val;
int msec;
key->state &= 1;
msec = key->msec;
key->msec = 0;
if(key->state) { msec += sys_frame_time - key->downtime;
key->downtime = sys_frame_time;
}
#if 0#endif
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;
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;
}
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);
}
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;
}
void CL_FinishMove(usercmd_t *cmd) {
int ms;
int i;
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;
ms = cls.frametime * 1000;
if(ms > 250)
ms = 100; 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;
cmd->lightlevel = (byte)cl_lightlevel->value;
}
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;
CL_BaseMove(&cmd);
IN_Move(&cmd);
CL_FinishMove(&cmd);
old_sys_frame_time = sys_frame_time;
return cmd;
}
void IN_CenterView(void) { cl.viewangles[PITCH] = -SHORT2ANGLE(cl.frame.playerstate.pmove.delta_angles[PITCH]); }
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);
}
void CL_SendCmd(void) {
sizebuf_t buf;
byte data[128];
int i;
usercmd_t *cmd, *oldcmd;
usercmd_t nullcmd;
int checksumIndex;
i = cls.netchan.outgoing_sequence & (CMD_BACKUP - 1);
cmd = &cl.cmds[i];
cl.cmd_time[i] = cls.realtime;
*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;
}
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) { SCR_FinishCinematic();
}
MSG_WriteByte(&buf, clc_move);
checksumIndex = buf.cursize;
MSG_WriteByte(&buf, 0);
if(cl_nodelta->value || !cl.frame.valid || cls.demowaiting)
MSG_WriteLong(&buf, -1); else
MSG_WriteLong(&buf, cl.frame.serverframe);
i = (cls.netchan.outgoing_sequence - 2) & (CMD_BACKUP - 1);
cmd = &cl.cmds[i];
memset(&nullcmd, 0, sizeof(nullcmd));
MSG_WriteDeltaUsercmd(&buf, &nullcmd, cmd);
oldcmd = cmd;
i = (cls.netchan.outgoing_sequence - 1) & (CMD_BACKUP - 1);
cmd = &cl.cmds[i];
MSG_WriteDeltaUsercmd(&buf, oldcmd, cmd);
oldcmd = cmd;
i = (cls.netchan.outgoing_sequence) & (CMD_BACKUP - 1);
cmd = &cl.cmds[i];
MSG_WriteDeltaUsercmd(&buf, oldcmd, cmd);
buf.data[checksumIndex] = COM_BlockSequenceCRCByte(buf.data + checksumIndex + 1, buf.cursize - checksumIndex - 1,
cls.netchan.outgoing_sequence);
Netchan_Transmit(&cls.netchan, buf.cursize, buf.data);
}