mirror of
https://github.com/nzp-team/quakec.git
synced 2025-03-04 08:30:56 +00:00
CLIENT: Add Chasecam from Vril
This commit is contained in:
parent
b0f30c3824
commit
c0bd852198
5 changed files with 166 additions and 2 deletions
|
@ -31,5 +31,6 @@ chat.qc
|
||||||
user_input.qc
|
user_input.qc
|
||||||
view_model.qc
|
view_model.qc
|
||||||
particles.qc
|
particles.qc
|
||||||
|
chasecam.qc
|
||||||
main.qc
|
main.qc
|
||||||
#endlist
|
#endlist
|
159
source/client/chasecam.qc
Normal file
159
source/client/chasecam.qc
Normal file
|
@ -0,0 +1,159 @@
|
||||||
|
/*
|
||||||
|
client/chasecam.qc
|
||||||
|
|
||||||
|
A pretty direct port of Quake's chase cam to CSQC.
|
||||||
|
|
||||||
|
Copyright (C) 1996-1997 Id Software, Inc.
|
||||||
|
Copyright (C) 2021-2024 NZ:P Team
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
vector chase_pos;
|
||||||
|
vector chase_angles;
|
||||||
|
|
||||||
|
vector chase_dest;
|
||||||
|
vector chase_dest_angles;
|
||||||
|
|
||||||
|
void() Chase_Init =
|
||||||
|
{
|
||||||
|
autocvar(chase_back, 100);
|
||||||
|
autocvar(chase_up, 16);
|
||||||
|
autocvar(chase_right, 0);
|
||||||
|
autocvar(chase_active, 0);
|
||||||
|
autocvar(chase_roll, 0);
|
||||||
|
autocvar(chase_yaw, 0);
|
||||||
|
autocvar(chase_pitch, 0);
|
||||||
|
};
|
||||||
|
|
||||||
|
float chase_nodraw;
|
||||||
|
|
||||||
|
#define NUM_TESTS 64
|
||||||
|
#define CHASE_DEST_OFFSET 2.0
|
||||||
|
|
||||||
|
void() Chase_Update =
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
float dist;
|
||||||
|
vector cl_viewangles, cl_vieworigin;
|
||||||
|
vector dest, stop;
|
||||||
|
int best;
|
||||||
|
int viewcontents;
|
||||||
|
|
||||||
|
cl_viewangles = getproperty(VF_ANGLES);
|
||||||
|
cl_vieworigin = getproperty(VF_ORIGIN);
|
||||||
|
|
||||||
|
// if can't see player, reset
|
||||||
|
makevectors(cl_viewangles);
|
||||||
|
|
||||||
|
// calc exact destination
|
||||||
|
for (i = 0; i < 3; i++) {
|
||||||
|
chase_dest[i] = cl_vieworigin[i] - v_forward[i] * autocvar_chase_back - v_right[i] * autocvar_chase_right;
|
||||||
|
}
|
||||||
|
|
||||||
|
chase_dest[2] = cl_vieworigin[2] + autocvar_chase_up;
|
||||||
|
|
||||||
|
// take contents of the view leaf
|
||||||
|
viewcontents = pointcontents(cl_vieworigin);
|
||||||
|
|
||||||
|
for (best = 0; best < NUM_TESTS; best++) {
|
||||||
|
vector chase_newdest;
|
||||||
|
|
||||||
|
chase_newdest[0] = cl_vieworigin[0] + (chase_dest[0] - cl_vieworigin[0]) * best / NUM_TESTS;
|
||||||
|
chase_newdest[1] = cl_vieworigin[1] + (chase_dest[1] - cl_vieworigin[1]) * best / NUM_TESTS;
|
||||||
|
chase_newdest[2] = cl_vieworigin[2] + (chase_dest[2] - cl_vieworigin[2]) * best / NUM_TESTS;
|
||||||
|
|
||||||
|
// check for a leaf hit with different contents
|
||||||
|
if (pointcontents(chase_newdest) != viewcontents)
|
||||||
|
{
|
||||||
|
// go back to the previous best as this one is bad
|
||||||
|
// unless the first one was also bad, (viewleaf contents != viewleaf contents!!!)
|
||||||
|
if (best > 0) {
|
||||||
|
best--;
|
||||||
|
} else {
|
||||||
|
best = NUM_TESTS;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// certain surfaces can be viewed at an oblique enough angle that they are partially clipped
|
||||||
|
// by znear, so now we fix that too...
|
||||||
|
for (; best >= 0; best--) {
|
||||||
|
// number of matches
|
||||||
|
int nummatches = 0;
|
||||||
|
|
||||||
|
// adjust
|
||||||
|
chase_dest[0] = cl_vieworigin[0] + (chase_dest[0] - cl_vieworigin[0]) * best / NUM_TESTS;
|
||||||
|
chase_dest[1] = cl_vieworigin[1] + (chase_dest[1] - cl_vieworigin[1]) * best / NUM_TESTS;
|
||||||
|
chase_dest[2] = cl_vieworigin[2] + (chase_dest[2] - cl_vieworigin[2]) * best / NUM_TESTS;
|
||||||
|
|
||||||
|
// move x to neg
|
||||||
|
chase_dest[0] -= CHASE_DEST_OFFSET;
|
||||||
|
if (pointcontents(chase_dest) == viewcontents) nummatches++;
|
||||||
|
chase_dest[0] += CHASE_DEST_OFFSET;
|
||||||
|
|
||||||
|
// move x to pos
|
||||||
|
chase_dest[0] += CHASE_DEST_OFFSET;
|
||||||
|
if (pointcontents(chase_dest) == viewcontents) nummatches++;
|
||||||
|
chase_dest[0] -= CHASE_DEST_OFFSET;
|
||||||
|
|
||||||
|
// move y to neg
|
||||||
|
chase_dest[1] -= CHASE_DEST_OFFSET;
|
||||||
|
if (pointcontents(chase_dest) == viewcontents) nummatches++;
|
||||||
|
chase_dest[1] += CHASE_DEST_OFFSET;
|
||||||
|
|
||||||
|
// move y to pos
|
||||||
|
chase_dest[1] += CHASE_DEST_OFFSET;
|
||||||
|
if (pointcontents(chase_dest) == viewcontents) nummatches++;
|
||||||
|
chase_dest[1] -= CHASE_DEST_OFFSET;
|
||||||
|
|
||||||
|
// move z to neg
|
||||||
|
chase_dest[2] -= CHASE_DEST_OFFSET;
|
||||||
|
if (pointcontents(chase_dest) == viewcontents) nummatches++;
|
||||||
|
chase_dest[2] += CHASE_DEST_OFFSET;
|
||||||
|
|
||||||
|
// move z to pos
|
||||||
|
chase_dest[2] += CHASE_DEST_OFFSET;
|
||||||
|
if (pointcontents(chase_dest) == viewcontents) nummatches++;
|
||||||
|
chase_dest[2] -= CHASE_DEST_OFFSET;
|
||||||
|
|
||||||
|
// all tests passed so we're good!
|
||||||
|
if (nummatches == 6) break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// find the spot the player is looking at
|
||||||
|
dest[0] = cl_vieworigin[0] + 4096 * v_forward[0];
|
||||||
|
dest[1] = cl_vieworigin[1] + 4096 * v_forward[1];
|
||||||
|
dest[2] = cl_vieworigin[2] + 4096 * v_forward[2];
|
||||||
|
traceline(cl_vieworigin, dest, MOVE_NOMONSTERS, world);
|
||||||
|
|
||||||
|
// calculate pitch to look at the same spot from camera
|
||||||
|
stop[0] = cl_vieworigin[0] - trace_endpos[0];
|
||||||
|
stop[1] = cl_vieworigin[1] - trace_endpos[1];
|
||||||
|
stop[2] = cl_vieworigin[2] - trace_endpos[2];
|
||||||
|
dist = dotproduct(stop, v_forward);
|
||||||
|
if (dist < 1) dist = 1;
|
||||||
|
|
||||||
|
cl_viewangles[0] = -atan(stop[2] / dist) / M_PI * 180;
|
||||||
|
|
||||||
|
setviewprop(VF_ORIGIN, chase_dest);
|
||||||
|
//setviewprop(VF_ANGLES, cl_viewangles);
|
||||||
|
};
|
|
@ -788,6 +788,10 @@ noref void(float width, float height, float menushown) CSQC_UpdateView =
|
||||||
|
|
||||||
setviewprop(VF_ANGLES, camang);
|
setviewprop(VF_ANGLES, camang);
|
||||||
|
|
||||||
|
if (cvar("chase_active")) {
|
||||||
|
Chase_Update();
|
||||||
|
}
|
||||||
|
|
||||||
//does what you think it does
|
//does what you think it does
|
||||||
renderscene();
|
renderscene();
|
||||||
|
|
||||||
|
|
|
@ -38,7 +38,7 @@ vector particle_position;
|
||||||
void() Particles_MuzzleflashCallback =
|
void() Particles_MuzzleflashCallback =
|
||||||
{
|
{
|
||||||
// Do not display Muzzleflashes if we're using a Sniper Scope or not drawing the viewmodel.
|
// Do not display Muzzleflashes if we're using a Sniper Scope or not drawing the viewmodel.
|
||||||
if (getstatf(STAT_WEAPONZOOM) == 2 || !cvar("r_drawviewmodel"))
|
if (getstatf(STAT_WEAPONZOOM) == 2 || !cvar("r_drawviewmodel") || cvar("chase_active"))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Organized storage of optional_field and optional_entity.
|
// Organized storage of optional_field and optional_entity.
|
||||||
|
|
|
@ -276,7 +276,7 @@ void() ViewModel_Draw =
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we're zoomed in with a Sniper scope or r_drawviewmodel is false, early-out.
|
// If we're zoomed in with a Sniper scope or r_drawviewmodel is false, early-out.
|
||||||
if (!cvar("r_drawviewmodel") || getstatf(STAT_WEAPONZOOM) == 2)
|
if (!cvar("r_drawviewmodel") || getstatf(STAT_WEAPONZOOM) == 2 || cvar("chase_active"))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
cl_viewent.origin = cl_viewent2.origin = '0 0 0';
|
cl_viewent.origin = cl_viewent2.origin = '0 0 0';
|
||||||
|
|
Loading…
Reference in a new issue