2 Copyright (C) 1996-1997 Id Software, Inc.
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 See the GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 // view.c -- player eye positioning
23 #include "cl_collision.h"
27 The view is allowed to move slightly from it's true position for bobbing,
28 but if it exceeds 8 pixels linear distance (spherical, not box), the list of
29 entities sent from the server may not include everything in the pvs, especially
30 when crossing a water boudnary.
34 cvar_t cl_rollspeed = {0, "cl_rollspeed", "200", "how much strafing is necessary to tilt the view"};
35 cvar_t cl_rollangle = {0, "cl_rollangle", "2.0", "how much to tilt the view when strafing"};
37 cvar_t cl_bob = {0, "cl_bob","0.02", "view bobbing amount"};
38 cvar_t cl_bobcycle = {0, "cl_bobcycle","0.6", "view bobbing speed"};
39 cvar_t cl_bobup = {0, "cl_bobup","0.5", "view bobbing adjustment that makes the up or down swing of the bob last longer"};
41 cvar_t cl_bobmodel = {0, "cl_bobmodel", "1", "enables gun bobbing"};
42 cvar_t cl_bobmodel_side = {0, "cl_bobmodel_side", "0.05", "gun bobbing sideways sway amount"};
43 cvar_t cl_bobmodel_up = {0, "cl_bobmodel_up", "0.02", "gun bobbing upward movement amount"};
44 cvar_t cl_bobmodel_speed = {0, "cl_bobmodel_speed", "7", "gun bobbing speed"};
46 cvar_t v_kicktime = {0, "v_kicktime", "0.5", "how long a view kick from damage lasts"};
47 cvar_t v_kickroll = {0, "v_kickroll", "0.6", "how much a view kick from damage rolls your view"};
48 cvar_t v_kickpitch = {0, "v_kickpitch", "0.6", "how much a view kick from damage pitches your view"};
50 cvar_t v_iyaw_cycle = {0, "v_iyaw_cycle", "2", "v_idlescale yaw speed"};
51 cvar_t v_iroll_cycle = {0, "v_iroll_cycle", "0.5", "v_idlescale roll speed"};
52 cvar_t v_ipitch_cycle = {0, "v_ipitch_cycle", "1", "v_idlescale pitch speed"};
53 cvar_t v_iyaw_level = {0, "v_iyaw_level", "0.3", "v_idlescale yaw amount"};
54 cvar_t v_iroll_level = {0, "v_iroll_level", "0.1", "v_idlescale roll amount"};
55 cvar_t v_ipitch_level = {0, "v_ipitch_level", "0.3", "v_idlescale pitch amount"};
57 cvar_t v_idlescale = {0, "v_idlescale", "0", "how much of the quake 'drunken view' effect to use"};
59 cvar_t crosshair = {CVAR_SAVE, "crosshair", "0", "selects crosshair to use (0 is none)"};
61 cvar_t v_centermove = {0, "v_centermove", "0.15", "how long before the view begins to center itself (if freelook/+mlook/+jlook/+klook are off)"};
62 cvar_t v_centerspeed = {0, "v_centerspeed","500", "how fast the view centers itself"};
64 cvar_t cl_stairsmoothspeed = {CVAR_SAVE, "cl_stairsmoothspeed", "160", "how fast your view moves upward/downward when running up/down stairs"};
66 cvar_t chase_back = {CVAR_SAVE, "chase_back", "48", "chase cam distance from the player"};
67 cvar_t chase_up = {CVAR_SAVE, "chase_up", "24", "chase cam distance from the player"};
68 cvar_t chase_active = {CVAR_SAVE, "chase_active", "0", "enables chase cam"};
70 cvar_t chase_stevie = {0, "chase_stevie", "0", "chase cam view from above (used only by GoodVsBad2)"};
72 cvar_t v_deathtilt = {0, "v_deathtilt", "1", "whether to use sideways view when dead"};
74 float v_dmg_time, v_dmg_roll, v_dmg_pitch;
81 Used by view and sv_user
84 float V_CalcRoll (vec3_t angles, vec3_t velocity)
91 AngleVectors (angles, NULL, right, NULL);
92 side = DotProduct (velocity, right);
93 sign = side < 0 ? -1 : 1;
96 value = cl_rollangle.value;
98 if (side < cl_rollspeed.value)
99 side = side * value / cl_rollspeed.value;
107 void V_StartPitchDrift (void)
109 if (cl.laststop == cl.time)
110 return; // something else is keeping it from drifting
112 if (cl.nodrift || !cl.pitchvel)
114 cl.pitchvel = v_centerspeed.value;
120 void V_StopPitchDrift (void)
122 cl.laststop = cl.time;
131 Moves the client pitch angle towards cl.idealpitch sent by the server.
133 If the user is adjusting pitch manually, either with lookup/lookdown,
134 mlook and mouse, or klook and keyboard, pitch drifting is constantly stopped.
136 Drifting is enabled when the center view key is hit, mlook is released and
137 lookspring is non 0, or when
140 void V_DriftPitch (void)
144 if (noclip_anglehack || !cl.onground || cls.demoplayback )
151 // don't count small mouse motion
154 if ( fabs(cl.cmd.forwardmove) < cl_forwardspeed.value)
157 cl.driftmove += cl.frametime;
159 if ( cl.driftmove > v_centermove.value)
161 V_StartPitchDrift ();
166 delta = cl.idealpitch - cl.viewangles[PITCH];
174 move = cl.frametime * cl.pitchvel;
175 cl.pitchvel += cl.frametime * v_centerspeed.value;
184 cl.viewangles[PITCH] += move;
193 cl.viewangles[PITCH] -= move;
199 ==============================================================================
203 ==============================================================================
212 void V_ParseDamage (void)
216 //vec3_t forward, right;
222 armor = MSG_ReadByte ();
223 blood = MSG_ReadByte ();
224 MSG_ReadVector(from, cl.protocol);
226 count = blood*0.5 + armor*0.5;
230 cl.faceanimtime = cl.time + 0.2; // put sbar face into pain frame
232 cl.cshifts[CSHIFT_DAMAGE].percent += 3*count;
233 if (cl.cshifts[CSHIFT_DAMAGE].percent < 0)
234 cl.cshifts[CSHIFT_DAMAGE].percent = 0;
235 if (cl.cshifts[CSHIFT_DAMAGE].percent > 150)
236 cl.cshifts[CSHIFT_DAMAGE].percent = 150;
240 cl.cshifts[CSHIFT_DAMAGE].destcolor[0] = 200;
241 cl.cshifts[CSHIFT_DAMAGE].destcolor[1] = 100;
242 cl.cshifts[CSHIFT_DAMAGE].destcolor[2] = 100;
246 cl.cshifts[CSHIFT_DAMAGE].destcolor[0] = 220;
247 cl.cshifts[CSHIFT_DAMAGE].destcolor[1] = 50;
248 cl.cshifts[CSHIFT_DAMAGE].destcolor[2] = 50;
252 cl.cshifts[CSHIFT_DAMAGE].destcolor[0] = 255;
253 cl.cshifts[CSHIFT_DAMAGE].destcolor[1] = 0;
254 cl.cshifts[CSHIFT_DAMAGE].destcolor[2] = 0;
257 // calculate view angle kicks
258 if (cl_entities[cl.viewentity].state_current.active)
260 ent = &cl_entities[cl.viewentity];
261 Matrix4x4_Transform(&ent->render.inversematrix, from, localfrom);
262 VectorNormalize(localfrom);
263 v_dmg_pitch = count * localfrom[0] * v_kickpitch.value;
264 v_dmg_roll = count * localfrom[1] * v_kickroll.value;
265 v_dmg_time = v_kicktime.value;
269 static cshift_t v_cshift;
276 static void V_cshift_f (void)
278 v_cshift.destcolor[0] = atoi(Cmd_Argv(1));
279 v_cshift.destcolor[1] = atoi(Cmd_Argv(2));
280 v_cshift.destcolor[2] = atoi(Cmd_Argv(3));
281 v_cshift.percent = atoi(Cmd_Argv(4));
289 When you run over an item, the server sends this command
292 static void V_BonusFlash_f (void)
294 cl.cshifts[CSHIFT_BONUS].destcolor[0] = 215;
295 cl.cshifts[CSHIFT_BONUS].destcolor[1] = 186;
296 cl.cshifts[CSHIFT_BONUS].destcolor[2] = 69;
297 cl.cshifts[CSHIFT_BONUS].percent = 50;
301 ==============================================================================
305 ==============================================================================
308 extern matrix4x4_t viewmodelmatrix;
310 #include "cl_collision.h"
319 void V_CalcRefdef (void)
323 float vieworg[3], gunorg[3], viewangles[3];
328 Matrix4x4_CreateIdentity(&viewmodelmatrix);
329 Matrix4x4_CreateIdentity(&r_refdef.viewentitymatrix);
330 if (cls.state == ca_connected && cls.signon == SIGNONS)
332 // ent is the view entity (visible when out of body)
333 ent = &cl_entities[cl.viewentity];
336 // entity is a fixed camera, just copy the matrix
337 Matrix4x4_Copy(&r_refdef.viewentitymatrix, &ent->render.matrix);
338 Matrix4x4_Copy(&viewmodelmatrix, &ent->render.matrix);
339 r_refdef.viewentitymatrix.m[2][3] += cl.stats[STAT_VIEWHEIGHT];
340 viewmodelmatrix.m[2][3] += cl.stats[STAT_VIEWHEIGHT];
344 // player can look around, so take the origin from the entity,
345 // and the angles from the input system
346 Matrix4x4_OriginFromMatrix(&ent->render.matrix, vieworg);
347 VectorCopy(cl.viewangles, viewangles);
352 cl.hitgroundtime = cl.time;
353 cl.lastongroundtime = cl.time;
355 cl.oldonground = cl.onground;
358 //Con_Printf("cl.onground %i oldz %f newz %f\n", cl.onground, oldz, vieworg[2]);
359 if (cl.onground && oldz < vieworg[2])
361 oldz += (cl.time - cl.oldtime) * cl_stairsmoothspeed.value;
362 oldz = vieworg[2] = bound(vieworg[2] - 16, oldz, vieworg[2]);
364 else if (cl.onground && oldz > vieworg[2])
366 oldz -= (cl.time - cl.oldtime) * cl_stairsmoothspeed.value;
367 oldz = vieworg[2] = bound(vieworg[2], oldz, vieworg[2] + 16);
372 if (chase_active.value)
374 // observing entity from third person
375 vec_t camback, camup, dist, forward[3], chase_dest[3];
377 camback = bound(0, chase_back.value, 128);
378 if (chase_back.value != camback)
379 Cvar_SetValueQuick(&chase_back, camback);
380 camup = bound(-48, chase_up.value, 96);
381 if (chase_up.value != camup)
382 Cvar_SetValueQuick(&chase_up, camup);
384 // this + 22 is to match view_ofs for compatibility with older versions
387 if (gamemode == GAME_GOODVSBAD2 && chase_stevie.integer)
389 // look straight down from high above
393 AngleVectors(viewangles, forward, NULL, NULL);
395 // trace a little further so it hits a surface more consistently (to avoid 'snapping' on the edge of the range)
397 chase_dest[0] = vieworg[0] + forward[0] * dist;
398 chase_dest[1] = vieworg[1] + forward[1] * dist;
399 chase_dest[2] = vieworg[2] + forward[2] * dist + camup;
400 trace = CL_TraceBox(vieworg, vec3_origin, vec3_origin, chase_dest, true, NULL, SUPERCONTENTS_SOLID | SUPERCONTENTS_SKY, false);
401 VectorMAMAM(1, trace.endpos, 8, forward, 4, trace.plane.normal, vieworg);
405 // first person view from entity
407 if (cl.stats[STAT_HEALTH] <= 0 && v_deathtilt.integer)
408 viewangles[ROLL] = 80; // dead view angle
409 VectorAdd(viewangles, cl.punchangle, viewangles);
410 viewangles[ROLL] += V_CalcRoll(cl.viewangles, cl.movement_velocity);
413 viewangles[ROLL] += v_dmg_time/v_kicktime.value*v_dmg_roll;
414 viewangles[PITCH] += v_dmg_time/v_kicktime.value*v_dmg_pitch;
415 v_dmg_time -= cl.frametime;
418 VectorAdd(vieworg, cl.punchvector, vieworg);
419 vieworg[2] += cl.stats[STAT_VIEWHEIGHT];
420 if (cl.stats[STAT_HEALTH] > 0)
424 xyspeed = sqrt(cl.velocity[0]*cl.velocity[0] + cl.velocity[1]*cl.velocity[1]);
425 if (cl_bob.value && cl_bobcycle.value)
428 // LordHavoc: this code is *weird*, but not replacable (I think it
429 // should be done in QC on the server, but oh well, quake is quake)
430 // LordHavoc: figured out bobup: the time at which the sin is at 180
431 // degrees (which allows lengthening or squishing the peak or valley)
432 cycle = cl.time / cl_bobcycle.value;
433 cycle -= (int) cycle;
434 if (cycle < cl_bobup.value)
435 cycle = sin(M_PI * cycle / cl_bobup.value);
437 cycle = sin(M_PI + M_PI * (cycle-cl_bobup.value)/(1.0 - cl_bobup.value));
438 // bob is proportional to velocity in the xy plane
439 // (don't count Z, or jumping messes it up)
440 bob = xyspeed * cl_bob.value;
441 bob = bob*0.3 + bob*0.7*cycle;
442 vieworg[2] += bound(-7, bob, 4);
445 VectorCopy(vieworg, gunorg);
447 if (cl_bobmodel.value)
449 // calculate for swinging gun model
450 // the gun bobs when running on the ground, but doesn't bob when you're in the air.
451 // Sajt: I tried to smooth out the transitions between bob and no bob, which works
452 // for the most part, but for some reason when you go through a message trigger or
453 // pick up an item or anything like that it will momentarily jolt the gun.
454 vec3_t forward, right, up;
459 s = cl.time * cl_bobmodel_speed.value;
462 if (cl.time - cl.hitgroundtime < 0.2)
464 // just hit the ground, speed the bob back up over the next 0.2 seconds
465 t = cl.time - cl.hitgroundtime;
466 t = bound(0, t, 0.2);
474 // recently left the ground, slow the bob down over the next 0.2 seconds
475 t = cl.time - cl.lastongroundtime;
476 t = 0.2 - bound(0, t, 0.2);
480 bspeed = bound (0, xyspeed, 400) * 0.01f;
481 AngleVectors (viewangles, forward, right, up);
482 bob = bspeed * cl_bobmodel_side.value * sin (s) * t;
483 VectorMA (gunorg, bob, right, gunorg);
484 bob = bspeed * cl_bobmodel_up.value * cos (s * 2) * t;
485 VectorMA (gunorg, bob, up, gunorg);
489 // calculate a view matrix for rendering the scene
490 if (v_idlescale.value)
491 Matrix4x4_CreateFromQuakeEntity(&r_refdef.viewentitymatrix, vieworg[0], vieworg[1], vieworg[2], viewangles[0] + v_idlescale.value * sin(cl.time*v_ipitch_cycle.value) * v_ipitch_level.value, viewangles[1] + v_idlescale.value * sin(cl.time*v_iyaw_cycle.value) * v_iyaw_level.value, viewangles[2] + v_idlescale.value * sin(cl.time*v_iroll_cycle.value) * v_iroll_level.value, 1);
493 Matrix4x4_CreateFromQuakeEntity(&r_refdef.viewentitymatrix, vieworg[0], vieworg[1], vieworg[2], viewangles[0], viewangles[1], viewangles[2] + v_idlescale.value * sin(cl.time*v_iroll_cycle.value) * v_iroll_level.value, 1);
494 // calculate a viewmodel matrix for use in view-attached entities
495 Matrix4x4_CreateFromQuakeEntity(&viewmodelmatrix, gunorg[0], gunorg[1], gunorg[2], viewangles[0], viewangles[1], viewangles[2], 0.3);
496 VectorCopy(vieworg, csqc_origin);
497 VectorCopy(viewangles, csqc_angles);
502 void V_FadeViewFlashs(void)
504 // drop the damage value
505 cl.cshifts[CSHIFT_DAMAGE].percent -= (cl.time - cl.oldtime)*150;
506 if (cl.cshifts[CSHIFT_DAMAGE].percent <= 0)
507 cl.cshifts[CSHIFT_DAMAGE].percent = 0;
508 // drop the bonus value
509 cl.cshifts[CSHIFT_BONUS].percent -= (cl.time - cl.oldtime)*100;
510 if (cl.cshifts[CSHIFT_BONUS].percent <= 0)
511 cl.cshifts[CSHIFT_BONUS].percent = 0;
514 void V_CalcViewBlend(void)
518 r_refdef.viewblend[0] = 0;
519 r_refdef.viewblend[1] = 0;
520 r_refdef.viewblend[2] = 0;
521 r_refdef.viewblend[3] = 0;
522 r_refdef.frustumscale_x = 1;
523 r_refdef.frustumscale_y = 1;
524 if (cls.state == ca_connected && cls.signon == SIGNONS && gl_polyblend.value > 0)
526 // set contents color
529 Matrix4x4_OriginFromMatrix(&r_refdef.viewentitymatrix, vieworigin);
530 supercontents = CL_PointSuperContents(vieworigin);
531 if (supercontents & SUPERCONTENTS_LIQUIDSMASK)
533 r_refdef.frustumscale_x *= 1 - (((sin(cl.time * 4.7) + 1) * 0.015) * r_waterwarp.value);
534 r_refdef.frustumscale_y *= 1 - (((sin(cl.time * 3.0) + 1) * 0.015) * r_waterwarp.value);
535 if (supercontents & SUPERCONTENTS_LAVA)
537 cl.cshifts[CSHIFT_CONTENTS].destcolor[0] = 255;
538 cl.cshifts[CSHIFT_CONTENTS].destcolor[1] = 80;
539 cl.cshifts[CSHIFT_CONTENTS].destcolor[2] = 0;
541 else if (supercontents & SUPERCONTENTS_SLIME)
543 cl.cshifts[CSHIFT_CONTENTS].destcolor[0] = 0;
544 cl.cshifts[CSHIFT_CONTENTS].destcolor[1] = 25;
545 cl.cshifts[CSHIFT_CONTENTS].destcolor[2] = 5;
549 cl.cshifts[CSHIFT_CONTENTS].destcolor[0] = 130;
550 cl.cshifts[CSHIFT_CONTENTS].destcolor[1] = 80;
551 cl.cshifts[CSHIFT_CONTENTS].destcolor[2] = 50;
553 cl.cshifts[CSHIFT_CONTENTS].percent = 150 >> 1;
557 cl.cshifts[CSHIFT_CONTENTS].destcolor[0] = 0;
558 cl.cshifts[CSHIFT_CONTENTS].destcolor[1] = 0;
559 cl.cshifts[CSHIFT_CONTENTS].destcolor[2] = 0;
560 cl.cshifts[CSHIFT_CONTENTS].percent = 0;
563 if (gamemode != GAME_TRANSFUSION)
565 if (cl.stats[STAT_ITEMS] & IT_QUAD)
567 cl.cshifts[CSHIFT_POWERUP].destcolor[0] = 0;
568 cl.cshifts[CSHIFT_POWERUP].destcolor[1] = 0;
569 cl.cshifts[CSHIFT_POWERUP].destcolor[2] = 255;
570 cl.cshifts[CSHIFT_POWERUP].percent = 30;
572 else if (cl.stats[STAT_ITEMS] & IT_SUIT)
574 cl.cshifts[CSHIFT_POWERUP].destcolor[0] = 0;
575 cl.cshifts[CSHIFT_POWERUP].destcolor[1] = 255;
576 cl.cshifts[CSHIFT_POWERUP].destcolor[2] = 0;
577 cl.cshifts[CSHIFT_POWERUP].percent = 20;
579 else if (cl.stats[STAT_ITEMS] & IT_INVISIBILITY)
581 cl.cshifts[CSHIFT_POWERUP].destcolor[0] = 100;
582 cl.cshifts[CSHIFT_POWERUP].destcolor[1] = 100;
583 cl.cshifts[CSHIFT_POWERUP].destcolor[2] = 100;
584 cl.cshifts[CSHIFT_POWERUP].percent = 100;
586 else if (cl.stats[STAT_ITEMS] & IT_INVULNERABILITY)
588 cl.cshifts[CSHIFT_POWERUP].destcolor[0] = 255;
589 cl.cshifts[CSHIFT_POWERUP].destcolor[1] = 255;
590 cl.cshifts[CSHIFT_POWERUP].destcolor[2] = 0;
591 cl.cshifts[CSHIFT_POWERUP].percent = 30;
594 cl.cshifts[CSHIFT_POWERUP].percent = 0;
597 cl.cshifts[CSHIFT_VCSHIFT].destcolor[0] = v_cshift.destcolor[0];
598 cl.cshifts[CSHIFT_VCSHIFT].destcolor[1] = v_cshift.destcolor[1];
599 cl.cshifts[CSHIFT_VCSHIFT].destcolor[2] = v_cshift.destcolor[2];
600 cl.cshifts[CSHIFT_VCSHIFT].percent = v_cshift.percent;
602 // LordHavoc: fixed V_CalcBlend
603 for (j = 0;j < NUM_CSHIFTS;j++)
605 a2 = bound(0.0f, cl.cshifts[j].percent * (1.0f / 255.0f), 1.0f);
608 VectorLerp(r_refdef.viewblend, a2, cl.cshifts[j].destcolor, r_refdef.viewblend);
609 r_refdef.viewblend[3] = (1 - (1 - r_refdef.viewblend[3]) * (1 - a2)); // correct alpha multiply... took a while to find it on the web
612 // saturate color (to avoid blending in black)
613 if (r_refdef.viewblend[3])
615 a2 = 1 / r_refdef.viewblend[3];
616 VectorScale(r_refdef.viewblend, a2, r_refdef.viewblend);
619 r_refdef.viewblend[0] = bound(0.0f, r_refdef.viewblend[0] * (1.0f/255.0f), 1.0f);
620 r_refdef.viewblend[1] = bound(0.0f, r_refdef.viewblend[1] * (1.0f/255.0f), 1.0f);
621 r_refdef.viewblend[2] = bound(0.0f, r_refdef.viewblend[2] * (1.0f/255.0f), 1.0f);
622 r_refdef.viewblend[3] = bound(0.0f, r_refdef.viewblend[3] * gl_polyblend.value, 1.0f);
626 //============================================================================
635 Cmd_AddCommand ("v_cshift", V_cshift_f, "sets tint color of view");
636 Cmd_AddCommand ("bf", V_BonusFlash_f, "briefly flashes a bright color tint on view (used when items are picked up)");
637 Cmd_AddCommand ("centerview", V_StartPitchDrift, "gradually recenter view (stop looking up/down)");
639 Cvar_RegisterVariable (&v_centermove);
640 Cvar_RegisterVariable (&v_centerspeed);
642 Cvar_RegisterVariable (&v_iyaw_cycle);
643 Cvar_RegisterVariable (&v_iroll_cycle);
644 Cvar_RegisterVariable (&v_ipitch_cycle);
645 Cvar_RegisterVariable (&v_iyaw_level);
646 Cvar_RegisterVariable (&v_iroll_level);
647 Cvar_RegisterVariable (&v_ipitch_level);
649 Cvar_RegisterVariable (&v_idlescale);
650 Cvar_RegisterVariable (&crosshair);
652 Cvar_RegisterVariable (&cl_rollspeed);
653 Cvar_RegisterVariable (&cl_rollangle);
654 Cvar_RegisterVariable (&cl_bob);
655 Cvar_RegisterVariable (&cl_bobcycle);
656 Cvar_RegisterVariable (&cl_bobup);
657 Cvar_RegisterVariable (&cl_bobmodel);
658 Cvar_RegisterVariable (&cl_bobmodel_side);
659 Cvar_RegisterVariable (&cl_bobmodel_up);
660 Cvar_RegisterVariable (&cl_bobmodel_speed);
662 Cvar_RegisterVariable (&v_kicktime);
663 Cvar_RegisterVariable (&v_kickroll);
664 Cvar_RegisterVariable (&v_kickpitch);
666 Cvar_RegisterVariable (&cl_stairsmoothspeed);
668 Cvar_RegisterVariable (&chase_back);
669 Cvar_RegisterVariable (&chase_up);
670 Cvar_RegisterVariable (&chase_active);
671 if (gamemode == GAME_GOODVSBAD2)
672 Cvar_RegisterVariable (&chase_stevie);
674 Cvar_RegisterVariable (&v_deathtilt);