Пример #1
0
/*
 * @brief Sets the kick value based on recent events such as falling. Firing of
 * weapons may also set the kick value, and we factor that in here as well.
 */
static void G_ClientKickAngles(g_edict_t *ent) {
	int16_t *kick_angles = ent->client->ps.pm_state.kick_angles;

	vec3_t kick;
	UnpackAngles(kick_angles, kick);

	// add in any event-based feedback

	switch (ent->s.event) {
		case EV_CLIENT_LAND:
			kick[PITCH] += 2.5;
			break;
		case EV_CLIENT_FALL:
			kick[PITCH] += 5.0;
			break;
		case EV_CLIENT_FALL_FAR:
			kick[PITCH] += 10.0;
			break;
		default:
			break;
	}

	// and any velocity-based feedback

	vec_t forward = DotProduct(ent->locals.velocity, ent->client->locals.forward);
	kick[PITCH] += forward / 450.0;

	vec_t right = DotProduct(ent->locals.velocity, ent->client->locals.right);
	kick[ROLL] += right / 350.0;

	// now interpolate the kick angles towards neutral over time

	vec_t delta = VectorLength(kick);

	if (!delta) // no kick, we're done
		return;

	// we recover from kick at a rate based on the kick itself

	delta = 0.5 + delta * delta * gi.frame_seconds;

	int32_t i;
	for (i = 0; i < 3; i++) {

		// clear angles smaller than our delta to avoid oscillations
		if (fabs(kick[i]) <= delta) {
			kick[i] = 0.0;
		} else if (kick[i] > 0.0) {
			kick[i] -= delta;
		} else {
			kick[i] += delta;
		}

	}

	PackAngles(kick, kick_angles);
}
Пример #2
0
/*
 * @brief Adds view kick in the specified direction to the specified client.
 */
void G_ClientDamageKick(g_entity_t *ent, const vec3_t dir, const vec_t kick) {
	vec3_t old_kick_angles, kick_angles;

	UnpackAngles(ent->client->ps.pm_state.kick_angles, old_kick_angles);

	VectorClear(kick_angles);
	kick_angles[PITCH] = DotProduct(dir, ent->client->locals.forward) * kick * KICK_SCALE;
	kick_angles[ROLL] = DotProduct(dir, ent->client->locals.right) * kick * KICK_SCALE;

	//gi.Print("kicked %s from %s at %1.2f\n", vtos(kick_angles), vtos(dir), kick);
	VectorAdd(old_kick_angles, kick_angles, kick_angles);
	PackAngles(kick_angles, ent->client->ps.pm_state.kick_angles);
}
Пример #3
0
/*
 * @brief Accumulate this frame's movement-related inputs and assemble a movement
 * command to send to the server. This may be called several times for each
 * command that is transmitted if the client is running asynchronously.
 */
void Cl_Move(pm_cmd_t *cmd) {

	if (cmd->msec < 1) // save key states for next move
		return;

	// keyboard move forward / back
	cmd->forward += cl_forward_speed->value * cmd->msec * Cl_KeyState(&in_forward, cmd->msec);
	cmd->forward -= cl_forward_speed->value * cmd->msec * Cl_KeyState(&in_back, cmd->msec);

	// keyboard strafe left / right
	cmd->right += cl_right_speed->value * cmd->msec * Cl_KeyState(&in_move_right, cmd->msec);
	cmd->right -= cl_right_speed->value * cmd->msec * Cl_KeyState(&in_move_left, cmd->msec);

	// keyboard jump / crouch
	cmd->up += cl_up_speed->value * cmd->msec * Cl_KeyState(&in_up, cmd->msec);
	cmd->up -= cl_up_speed->value * cmd->msec * Cl_KeyState(&in_down, cmd->msec);

	// keyboard turn left / right
	cl.angles[YAW] -= cl_yaw_speed->value * cmd->msec * Cl_KeyState(&in_right, cmd->msec);
	cl.angles[YAW] += cl_yaw_speed->value * cmd->msec * Cl_KeyState(&in_left, cmd->msec);

	// keyboard look up / down
	cl.angles[PITCH] -= cl_pitch_speed->value * cmd->msec * Cl_KeyState(&in_look_up, cmd->msec);
	cl.angles[PITCH] += cl_pitch_speed->value * cmd->msec * Cl_KeyState(&in_look_down, cmd->msec);

	Cl_ClampPitch(); // clamp, accounting for frame delta angles

	// pack the angles into the command
	PackAngles(cl.angles, cmd->angles);

	// set any button hits that occurred since last frame
	if (in_attack.state & 3)
	cmd->buttons |= BUTTON_ATTACK;

	in_attack.state &= ~2;

	if (cl_run->value) { // run by default, walk on speed toggle
		if (in_speed.state & 1)
		cmd->buttons |= BUTTON_WALK;
	} else { // walk by default, run on speed toggle
		if (!(in_speed.state & 1))
		cmd->buttons |= BUTTON_WALK;
	}
}
Пример #4
0
/*
 * @brief Sets the kick value based on recent events such as falling. Firing of
 * weapons may also set the kick value, and we factor that in here as well.
 */
static void G_ClientKickAngles(g_entity_t *ent) {
	uint16_t *kick_angles = ent->client->ps.pm_state.kick_angles;

	// spectators and dead clients receive no kick angles

	if (ent->client->ps.pm_state.type != PM_NORMAL) {
		VectorClear(kick_angles);
		return;
	}

	vec3_t kick;
	UnpackAngles(kick_angles, kick);

	// un-clamp them so that we can work with small signed values near zero

	for (int32_t i = 0; i < 3; i++) {
		if (kick[i] > 180.0)
			kick[i] -= 360.0;
	}

	// add in any event-based feedback

	switch (ent->s.event) {
		case EV_CLIENT_LAND:
			kick[PITCH] += 2.5;
			break;
		case EV_CLIENT_FALL:
			kick[PITCH] += 5.0;
			break;
		case EV_CLIENT_FALL_FAR:
			kick[PITCH] += 10.0;
			break;
		default:
			break;
	}

	// and any velocity-based feedback

	vec_t forward = DotProduct(ent->locals.velocity, ent->client->locals.forward);
	kick[PITCH] += forward / 450.0;

	vec_t right = DotProduct(ent->locals.velocity, ent->client->locals.right);
	kick[ROLL] += right / 400.0;

	// now interpolate the kick angles towards neutral over time

	vec_t delta = VectorLength(kick);

	if (!delta) // no kick, we're done
		return;

	// we recover from kick at a rate based on the kick itself

	delta = 0.5 + delta * delta * gi.frame_seconds;

	for (int32_t i = 0; i < 3; i++) {

		// clear angles smaller than our delta to avoid oscillations
		if (fabs(kick[i]) <= delta) {
			kick[i] = 0.0;
		} else if (kick[i] > 0.0) {
			kick[i] -= delta;
		} else {
			kick[i] += delta;
		}
	}

	PackAngles(kick, kick_angles);
}