2001-02-19 21:15:25 +00:00
|
|
|
/*
|
2012-05-20 10:17:41 +00:00
|
|
|
cl_chase.c
|
2001-02-19 21:15:25 +00:00
|
|
|
|
2012-05-20 10:17:41 +00:00
|
|
|
chase camera support
|
2001-02-19 21:15:25 +00:00
|
|
|
|
|
|
|
Copyright (C) 1996-1997 Id Software, Inc.
|
|
|
|
|
|
|
|
This program is free software; you can redistribute it and/or
|
|
|
|
modify it under the terms of the GNU General Public License
|
|
|
|
as published by the Free Software Foundation; either version 2
|
|
|
|
of the License, or (at your option) any later version.
|
|
|
|
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
|
|
|
|
|
|
See the GNU General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
along with this program; if not, write to:
|
|
|
|
|
|
|
|
Free Software Foundation, Inc.
|
|
|
|
59 Temple Place - Suite 330
|
|
|
|
Boston, MA 02111-1307, USA
|
|
|
|
|
|
|
|
*/
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
|
|
# include "config.h"
|
|
|
|
#endif
|
|
|
|
|
2012-05-20 10:17:41 +00:00
|
|
|
#ifdef HAVE_STRING_H
|
|
|
|
# include <string.h>
|
|
|
|
#endif
|
|
|
|
#ifdef HAVE_STRINGS_H
|
|
|
|
# include <strings.h>
|
|
|
|
#endif
|
|
|
|
|
2001-05-31 03:41:35 +00:00
|
|
|
#include "QF/cvar.h"
|
2012-02-14 08:28:09 +00:00
|
|
|
#include "QF/keys.h"
|
|
|
|
#include "QF/input.h"
|
2001-03-27 20:33:07 +00:00
|
|
|
#include "QF/mathlib.h"
|
2001-08-29 02:12:57 +00:00
|
|
|
|
2012-02-14 08:28:09 +00:00
|
|
|
#include "QF/plugin/vid_render.h"
|
2022-03-01 02:43:23 +00:00
|
|
|
#include "QF/scene/transform.h"
|
2012-02-14 08:28:09 +00:00
|
|
|
|
2001-02-19 21:15:25 +00:00
|
|
|
#include "world.h"
|
|
|
|
|
2022-02-22 06:23:09 +00:00
|
|
|
#include "client/chase.h"
|
|
|
|
#include "client/input.h"
|
|
|
|
#include "client/view.h"
|
2020-06-21 14:15:17 +00:00
|
|
|
|
2021-03-19 11:18:45 +00:00
|
|
|
|
|
|
|
vec4f_t camera_origin = {0,0,0,1};
|
|
|
|
vec4f_t player_origin = {0,0,0,1};
|
|
|
|
vec4f_t player_angles = {0,0,0,1};
|
|
|
|
|
|
|
|
vec3_t camera_angles = {0,0,0};
|
2001-09-28 07:51:15 +00:00
|
|
|
|
2002-08-20 02:22:40 +00:00
|
|
|
vec3_t chase_angles;
|
|
|
|
vec3_t chase_dest;
|
|
|
|
vec3_t chase_dest_angles;
|
|
|
|
vec3_t chase_pos;
|
2001-02-19 21:15:25 +00:00
|
|
|
|
2001-02-26 06:48:02 +00:00
|
|
|
cvar_t *chase_back;
|
|
|
|
cvar_t *chase_up;
|
|
|
|
cvar_t *chase_right;
|
|
|
|
cvar_t *chase_active;
|
2001-02-19 21:15:25 +00:00
|
|
|
|
|
|
|
|
2001-02-26 06:48:02 +00:00
|
|
|
void
|
2001-05-19 22:26:06 +00:00
|
|
|
Chase_Init_Cvars (void)
|
2001-02-19 21:15:25 +00:00
|
|
|
{
|
2001-04-10 23:39:30 +00:00
|
|
|
chase_back = Cvar_Get ("chase_back", "100", CVAR_NONE, NULL, "None");
|
|
|
|
chase_up = Cvar_Get ("chase_up", "16", CVAR_NONE, NULL, "None");
|
|
|
|
chase_right = Cvar_Get ("chase_right", "0", CVAR_NONE, NULL, "None");
|
|
|
|
chase_active = Cvar_Get ("chase_active", "0", CVAR_NONE, NULL, "None");
|
2001-02-19 21:15:25 +00:00
|
|
|
}
|
|
|
|
|
2001-02-26 06:48:02 +00:00
|
|
|
void
|
|
|
|
Chase_Reset (void)
|
2001-02-19 21:15:25 +00:00
|
|
|
{
|
|
|
|
// for respawning and teleporting
|
2001-05-14 03:08:24 +00:00
|
|
|
// start position 12 units behind head
|
2001-02-19 21:15:25 +00:00
|
|
|
}
|
|
|
|
|
2022-03-01 02:43:23 +00:00
|
|
|
static inline vec4f_t
|
|
|
|
TraceLine (chasestate_t *cs, vec4f_t start, vec4f_t end)
|
2001-02-19 21:15:25 +00:00
|
|
|
{
|
2001-02-26 06:48:02 +00:00
|
|
|
trace_t trace;
|
2001-02-19 21:15:25 +00:00
|
|
|
|
2001-02-26 06:48:02 +00:00
|
|
|
memset (&trace, 0, sizeof (trace));
|
2011-08-24 04:56:00 +00:00
|
|
|
trace.fraction = 1;
|
2022-03-01 02:43:23 +00:00
|
|
|
MOD_TraceLine (cs->worldmodel->brush.hulls, 0, &start[0], &end[0], &trace);
|
2001-02-19 21:15:25 +00:00
|
|
|
|
2022-03-01 02:43:23 +00:00
|
|
|
return (vec4f_t) {trace.endpos[0], trace.endpos[1], trace.endpos[2], 1};
|
2001-02-19 21:15:25 +00:00
|
|
|
}
|
|
|
|
|
2001-02-26 06:48:02 +00:00
|
|
|
void
|
2022-02-22 06:23:09 +00:00
|
|
|
Chase_Update (chasestate_t *cs)
|
2001-02-19 21:15:25 +00:00
|
|
|
{
|
2022-03-01 02:43:23 +00:00
|
|
|
viewstate_t *vs = cs->viewstate;
|
2021-03-19 11:18:45 +00:00
|
|
|
float pitch, yaw, fwd;
|
2022-02-22 06:23:09 +00:00
|
|
|
vec4f_t move = {};
|
2021-03-19 11:18:45 +00:00
|
|
|
vec4f_t forward = {}, up = {}, right = {}, stop = {}, dir = {};
|
2001-09-28 07:51:15 +00:00
|
|
|
|
|
|
|
// lazy camera, look toward player entity
|
|
|
|
|
2002-08-20 02:22:40 +00:00
|
|
|
if (chase_active->int_val == 2 || chase_active->int_val == 3) {
|
2001-09-28 07:51:15 +00:00
|
|
|
// control camera angles with key/mouse/joy-look
|
2021-03-19 11:18:45 +00:00
|
|
|
vec3_t d;
|
2022-03-01 02:43:23 +00:00
|
|
|
VectorSubtract (vs->player_angles, player_angles, d);
|
2021-03-19 11:18:45 +00:00
|
|
|
VectorAdd (camera_angles, d, camera_angles);
|
2002-08-20 02:22:40 +00:00
|
|
|
|
|
|
|
if (chase_active->int_val == 2) {
|
2022-03-01 02:43:23 +00:00
|
|
|
camera_angles[PITCH] = bound (-60, camera_angles[PITCH], 60);
|
2001-09-28 07:51:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// move camera, it's not enough to just change the angles because
|
|
|
|
// the angles are automatically changed to look toward the player
|
|
|
|
|
2021-03-19 11:18:45 +00:00
|
|
|
if (chase_active->int_val == 3) {
|
2022-03-01 02:43:23 +00:00
|
|
|
player_origin = vs->player_origin;
|
2021-03-19 11:18:45 +00:00
|
|
|
}
|
2001-09-28 07:51:15 +00:00
|
|
|
|
2021-03-19 11:18:45 +00:00
|
|
|
AngleVectors (camera_angles, &forward[0], &right[0], &up[0]);
|
|
|
|
camera_origin = player_origin - chase_back->value * forward;
|
2001-09-28 07:51:15 +00:00
|
|
|
|
2002-08-20 02:22:40 +00:00
|
|
|
if (chase_active->int_val == 2) {
|
2022-03-01 02:43:23 +00:00
|
|
|
player_origin = vs->player_origin;
|
2001-09-28 07:51:15 +00:00
|
|
|
|
|
|
|
// don't let camera get too low
|
2021-03-19 11:18:45 +00:00
|
|
|
if (camera_origin[2] < player_origin[2] + chase_up->value) {
|
2001-09-28 07:51:15 +00:00
|
|
|
camera_origin[2] = player_origin[2] + chase_up->value;
|
2021-03-19 11:18:45 +00:00
|
|
|
}
|
2001-09-28 07:51:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// don't let camera get too far from player
|
|
|
|
|
2021-03-19 11:18:45 +00:00
|
|
|
dir = camera_origin - player_origin;
|
|
|
|
forward = normalf (dir);
|
2001-09-28 07:51:15 +00:00
|
|
|
|
2021-03-19 11:18:45 +00:00
|
|
|
if (magnitudef (dir)[0] > chase_back->value) {
|
|
|
|
camera_origin = player_origin + forward * chase_back->value;
|
2001-09-28 07:51:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// check for walls between player and camera
|
|
|
|
|
2021-03-19 11:18:45 +00:00
|
|
|
camera_origin += 8 * forward;
|
2022-03-01 02:43:23 +00:00
|
|
|
stop = TraceLine (cs, player_origin, camera_origin);
|
2021-03-19 11:18:45 +00:00
|
|
|
if (magnitude3f (stop)[0] != 0) {
|
|
|
|
camera_origin = stop - forward;
|
|
|
|
}
|
2001-09-28 07:51:15 +00:00
|
|
|
|
2022-03-01 02:43:23 +00:00
|
|
|
dir = camera_origin - vs->player_origin;
|
2021-03-19 11:18:45 +00:00
|
|
|
forward = normalf (dir);
|
2001-09-28 07:51:15 +00:00
|
|
|
|
2002-08-20 02:22:40 +00:00
|
|
|
if (chase_active->int_val == 2) {
|
|
|
|
if (dir[1] == 0 && dir[0] == 0) {
|
2001-09-28 07:51:15 +00:00
|
|
|
// look straight up or down
|
2022-02-22 06:23:09 +00:00
|
|
|
// camera_angles[YAW] = r_data->refdef->viewstate->angles[YAW];
|
2002-08-20 02:22:40 +00:00
|
|
|
if (dir[2] > 0)
|
|
|
|
camera_angles[PITCH] = 90;
|
|
|
|
else
|
|
|
|
camera_angles[PITCH] = 270;
|
|
|
|
} else {
|
2001-09-28 07:51:15 +00:00
|
|
|
yaw = (atan2 (dir[1], dir[0]) * 180 / M_PI);
|
2002-08-20 02:22:40 +00:00
|
|
|
if (yaw < 0)
|
|
|
|
yaw += 360;
|
|
|
|
if (yaw < 180)
|
|
|
|
yaw += 180;
|
|
|
|
else
|
|
|
|
yaw -= 180;
|
2001-09-28 07:51:15 +00:00
|
|
|
camera_angles[YAW] = yaw;
|
|
|
|
|
|
|
|
fwd = sqrt (dir[0] * dir[0] + dir[1] * dir[1]);
|
|
|
|
pitch = (atan2 (dir[2], fwd) * 180 / M_PI);
|
2002-08-20 02:22:40 +00:00
|
|
|
if (pitch < 0)
|
|
|
|
pitch += 360;
|
2001-09-28 07:51:15 +00:00
|
|
|
camera_angles[PITCH] = pitch;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-03-01 02:43:23 +00:00
|
|
|
vec4f_t rotation;
|
|
|
|
AngleQuat (camera_angles, &rotation[0]);//FIXME
|
|
|
|
Transform_SetWorldRotation (vs->camera_transform, rotation);
|
|
|
|
Transform_SetWorldPosition (vs->camera_transform, camera_origin);
|
2001-09-28 07:51:15 +00:00
|
|
|
|
|
|
|
// get basic movement from keyboard
|
|
|
|
|
2022-03-01 02:43:23 +00:00
|
|
|
// VectorCopy (vs->player_angles, cmd.angles);
|
2001-09-28 07:51:15 +00:00
|
|
|
|
|
|
|
if (in_strafe.state & 1) {
|
2022-02-22 06:23:09 +00:00
|
|
|
move[SIDE] += cl_sidespeed->value * IN_ButtonState (&in_right);
|
|
|
|
move[SIDE] -= cl_sidespeed->value * IN_ButtonState (&in_left);
|
2001-09-28 07:51:15 +00:00
|
|
|
}
|
2022-02-22 06:23:09 +00:00
|
|
|
move[SIDE] += cl_sidespeed->value * IN_ButtonState (&in_moveright);
|
|
|
|
move[SIDE] -= cl_sidespeed->value * IN_ButtonState (&in_moveleft);
|
2001-09-28 07:51:15 +00:00
|
|
|
|
|
|
|
if (!(in_klook.state & 1)) {
|
2022-02-22 06:23:09 +00:00
|
|
|
move[FORWARD] += cl_forwardspeed->value
|
[input] Rework logical buttons
kbutton_t is now in_button_t and has been moved to input.h. Also, a
button registration function has been added to take care of +button and
-button command creation and, eventually, direct binding of "physical"
buttons to logical buttons. "Physical" buttons are those coming in from
the OS (keyboard, mouse, joystick...), logical buttons are what the code
looks at for button state.
Additionally, the button edge detection code has been cleaned up such
that it no longer uses magic numbers, and the conversion to a float is
cleaner. Interestingly, I found that the handling is extremely
frame-rate dependent (eg, +forward will accelerate the player to full
speed much faster at 72fps than it does at 20fps). This may be a factor
in why gamers are frame rate obsessed: other games doing the same thing
would certainly feel different under varying frame rates.
2021-10-01 00:16:31 +00:00
|
|
|
* IN_ButtonState (&in_forward);
|
2022-02-22 06:23:09 +00:00
|
|
|
move[FORWARD] -= cl_backspeed->value * IN_ButtonState (&in_back);
|
2001-09-28 07:51:15 +00:00
|
|
|
}
|
|
|
|
if (in_speed.state & 1) {
|
2022-02-22 06:23:09 +00:00
|
|
|
move *= cl_movespeedkey->value;
|
2001-09-28 07:51:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// mouse and joystick controllers add to movement
|
2022-03-01 02:43:23 +00:00
|
|
|
VectorSet (0, vs->player_angles[1] - camera_angles[1], 0, dir);
|
2021-03-19 11:18:45 +00:00
|
|
|
AngleVectors (&dir[0], &forward[0], &right[0], &up[0]); //FIXME
|
2021-11-18 06:33:49 +00:00
|
|
|
//forward *= viewdelta.position[2] * m_forward->value; FIXME
|
|
|
|
//right *= viewdelta.position[0] * m_side->value; FIXME
|
2021-03-19 11:18:45 +00:00
|
|
|
dir = forward + right;
|
2022-02-22 06:23:09 +00:00
|
|
|
move[FORWARD] += dir[0];
|
|
|
|
move[SIDE] -= dir[1];
|
2001-09-28 07:51:15 +00:00
|
|
|
|
2011-08-24 04:56:00 +00:00
|
|
|
VectorSet (0, camera_angles[1], 0, dir);
|
2021-03-19 11:18:45 +00:00
|
|
|
AngleVectors (&dir[0], &forward[0], &right[0], &up[0]); //FIXME
|
2001-09-28 07:51:15 +00:00
|
|
|
|
2022-02-22 06:23:09 +00:00
|
|
|
VectorScale (forward, move[FORWARD], forward);
|
|
|
|
VectorScale (right, move[SIDE], right);
|
2011-08-24 04:56:00 +00:00
|
|
|
VectorAdd (forward, right, dir);
|
2001-09-28 07:51:15 +00:00
|
|
|
|
2002-08-20 02:22:40 +00:00
|
|
|
if (dir[1] || dir[0]) {
|
2022-03-01 02:43:23 +00:00
|
|
|
vs->player_angles[YAW] = (atan2 (dir[1], dir[0]) * 180 / M_PI);
|
|
|
|
if (vs->player_angles[YAW] < 0) {
|
|
|
|
vs->player_angles[YAW] += 360;
|
2021-03-19 11:18:45 +00:00
|
|
|
}
|
2001-09-28 07:51:15 +00:00
|
|
|
}
|
|
|
|
|
2022-03-01 02:43:23 +00:00
|
|
|
vs->player_angles[PITCH] = 0;
|
2001-09-28 07:51:15 +00:00
|
|
|
|
|
|
|
// remember the new angle to calculate the difference next frame
|
2022-03-01 02:43:23 +00:00
|
|
|
VectorCopy (vs->player_angles, player_angles);
|
2001-09-28 07:51:15 +00:00
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// regular camera, faces same direction as player
|
2001-02-19 21:15:25 +00:00
|
|
|
|
2021-03-19 11:18:45 +00:00
|
|
|
//FIXME
|
2022-03-01 02:43:23 +00:00
|
|
|
AngleVectors (vs->player_angles, &forward[0], &right[0], &up[0]);
|
2001-02-19 21:15:25 +00:00
|
|
|
|
|
|
|
// calc exact destination
|
2022-03-01 02:43:23 +00:00
|
|
|
camera_origin = vs->player_origin
|
2021-03-19 11:18:45 +00:00
|
|
|
- forward * chase_back->value - right * chase_right->value;
|
|
|
|
// chase_up is world up
|
2001-11-30 22:30:23 +00:00
|
|
|
camera_origin[2] += chase_up->value;
|
2001-02-19 21:15:25 +00:00
|
|
|
|
2001-09-28 07:51:15 +00:00
|
|
|
// check for walls between player and camera
|
2022-03-01 02:43:23 +00:00
|
|
|
stop = TraceLine (cs, vs->player_origin, camera_origin);
|
2021-03-19 11:18:45 +00:00
|
|
|
if (magnitude3f (stop)[0] != 0) {
|
|
|
|
camera_origin = stop + forward * 8;
|
|
|
|
}
|
2001-02-19 21:15:25 +00:00
|
|
|
|
2022-03-01 02:43:23 +00:00
|
|
|
Transform_SetWorldPosition (vs->camera_transform, camera_origin);
|
2001-02-19 21:15:25 +00:00
|
|
|
}
|