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
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 lcd_x
= {"lcd_x","0"};
35 cvar_t lcd_yaw
= {"lcd_yaw","0"};
37 cvar_t scr_ofsx
= {"scr_ofsx","0", false};
38 cvar_t scr_ofsy
= {"scr_ofsy","0", false};
39 cvar_t scr_ofsz
= {"scr_ofsz","0", false};
41 cvar_t cl_rollspeed
= {"cl_rollspeed", "200"};
42 cvar_t cl_rollangle
= {"cl_rollangle", "3.0"};
44 cvar_t cl_bob
= {"cl_bob","0.02", true};
45 cvar_t cl_bobcycle
= {"cl_bobcycle","0.45", true};
46 cvar_t cl_bobup
= {"cl_bobup","0.5", true};
48 cvar_t cl_bobside
= {"cl_bobside","0.02", true};
49 cvar_t cl_bobsidecycle
= {"cl_bobsidecycle","0.9", true};
50 cvar_t cl_bobsideup
= {"cl_bobsideup","0.5", true};
52 cvar_t v_kicktime
= {"v_kicktime", "0.5", false};
53 cvar_t v_kickroll
= {"v_kickroll", "0.6", false};
54 cvar_t v_kickpitch
= {"v_kickpitch", "0.6", false};
56 cvar_t v_iyaw_cycle
= {"v_iyaw_cycle", "6", true};
57 cvar_t v_iroll_cycle
= {"v_iroll_cycle", "6", true};
58 cvar_t v_ipitch_cycle
= {"v_ipitch_cycle", "12", true};
59 cvar_t v_iyaw_level
= {"v_iyaw_level", "0.15", true};
60 cvar_t v_iroll_level
= {"v_iroll_level", "0.15", true};
61 cvar_t v_ipitch_level
= {"v_ipitch_level", "0.15", true};
63 cvar_t v_idlescale
= {"v_idlescale", "0.1", true};
65 cvar_t crosshair
= {"crosshair", "2", true};
66 cvar_t cl_crossx
= {"cl_crossx", "0", false};
67 cvar_t cl_crossy
= {"cl_crossy", "0", false};
69 cvar_t cl_gunpitch
= {"cl_gunpitch", "0", false};
71 cvar_t gl_cshiftpercent
= {"gl_cshiftpercent", "100", false};
73 float v_dmg_time
, v_dmg_roll
, v_dmg_pitch
;
75 extern int in_forward
, in_forward2
, in_back
;
76 extern cvar_t lookcenter
;
81 Used by view and sv_user
84 vec3_t forward
, right
, up
;
86 float V_CalcRoll (vec3_t angles
, vec3_t velocity
)
92 AngleVectors (angles
, forward
, right
, up
);
93 side
= DotProduct (velocity
, right
);
94 sign
= side
< 0 ? -1 : 1;
97 value
= cl_rollangle
.value
;
101 if (side
< cl_rollspeed
.value
)
102 side
= side
* value
/ cl_rollspeed
.value
;
117 float V_CalcBob (void)
122 cycle
= cl
.time
- (int)(cl
.time
/cl_bobcycle
.value
)*cl_bobcycle
.value
;
123 cycle
/= cl_bobcycle
.value
;
124 if (cycle
< cl_bobup
.value
)
125 cycle
= M_PI
* cycle
/ cl_bobup
.value
;
127 cycle
= M_PI
+ M_PI
*(cycle
-cl_bobup
.value
)/(1.0 - cl_bobup
.value
);
129 // bob is proportional to velocity in the xy plane
130 // (don't count Z, or jumping messes it up)
132 bob
= sqrtf(cl
.velocity
[0]*cl
.velocity
[0] + cl
.velocity
[1]*cl
.velocity
[1]) * cl_bob
.value
;
133 // Con_Printf ("speed: %5.1f\n", Length(cl.velocity));
134 bob
= bob
*0.3 + bob
*0.7*sinf(cycle
);
149 float V_CalcBobSide (void)
154 cycle
= cl
.time
- (int)(cl
.time
/cl_bobsidecycle
.value
)*cl_bobsidecycle
.value
;
155 cycle
/= cl_bobsidecycle
.value
;
156 if (cycle
< cl_bobsideup
.value
)
157 cycle
= M_PI
* cycle
/ cl_bobsideup
.value
;
159 cycle
= M_PI
+ M_PI
*(cycle
-cl_bobsideup
.value
)/(1.0 - cl_bobsideup
.value
);
161 // bob is proportional to velocity in the xy plane
162 // (don't count Z, or jumping messes it up)
164 bobside
= sqrtf(cl
.velocity
[0]*cl
.velocity
[0] + cl
.velocity
[1]*cl
.velocity
[1]) * cl_bobside
.value
;
165 //Con_Printf ("speed: %5.1f\n", Length(cl.velocity));
166 bobside
= bobside
*0.3 + bobside
*0.7*sinf(cycle
);
169 else if (bobside
< -7)
179 Kurok specific zoom code.
183 float V_ZoomIN (void)
189 //=============================================================================
192 cvar_t v_centermove
= {"v_centermove", "1", true};
193 cvar_t v_centerspeed
= {"v_centerspeed","100", true};
196 void V_StartPitchDrift (void)
199 if (cl
.laststop
== cl
.time
)
201 return; // something else is keeping it from drifting
204 if (cl
.nodrift
|| !cl
.pitchvel
)
206 cl
.pitchvel
= v_centerspeed
.value
;
212 void V_StopPitchDrift (void)
214 cl
.laststop
= cl
.time
;
223 Moves the client pitch angle towards cl.idealpitch sent by the server.
225 If the user is adjusting pitch manually, either with lookup/lookdown,
226 mlook and mouse, or klook and keyboard, pitch drifting is constantly stopped.
228 Drifting is enabled when the center view key is hit, mlook is released and
229 lookspring is non 0, or when
232 void V_DriftPitch (void)
236 if (noclip_anglehack
|| !cl
.onground
|| cls
.demoplayback
|| lookcenter
.value
)
243 // don't count small mouse motion
246 if ( fabsf(cl
.cmd
.forwardmove
) < cl_forwardspeed
.value
)
249 cl
.driftmove
+= host_frametime
;
251 if ( cl
.driftmove
> v_centermove
.value
)
253 V_StartPitchDrift ();
258 delta
= cl
.idealpitch
- cl
.viewangles
[PITCH
];
266 move
= host_frametime
* cl
.pitchvel
;
267 cl
.pitchvel
+= host_frametime
* v_centerspeed
.value
;
269 //Con_Printf ("move: %f (%f)\n", move, host_frametime);
278 cl
.viewangles
[PITCH
] += move
;
287 cl
.viewangles
[PITCH
] -= move
;
296 ==============================================================================
300 ==============================================================================
304 cshift_t cshift_empty
= { {130,80,50}, 0 };
305 cshift_t cshift_water
= { {130,80,50}, 128 };
306 cshift_t cshift_kwater
= { {64,64,128}, 128 }; // Blue water for Kurok
307 cshift_t cshift_slime
= { {0,25,5}, 150 };
308 cshift_t cshift_lava
= { {255,80,0}, 150 };
310 cvar_t v_gamma
= {"gamma", "1", true};
312 byte gammatable
[256]; // palette is sent through this
314 #if defined(GLQUAKE) || defined(PSP_HARDWARE_VIDEO)
316 float v_blend
[4]; // rgba 0.0 - 1.0
319 void BuildGammaTable (float g
)
325 for (i
=0 ; i
<256 ; i
++)
330 for (i
=0 ; i
<256 ; i
++)
332 inf
= 255 * powf ( (i
+0.5f
)/255.5f
, g
) + 0.5;
346 qboolean
V_CheckGamma (void)
348 static float oldgammavalue
;
350 if (v_gamma
.value
== oldgammavalue
)
352 oldgammavalue
= v_gamma
.value
;
354 BuildGammaTable (v_gamma
.value
);
355 vid
.recalc_refdef
= 1; // force a surface cache flush
367 void V_ParseDamage (void)
372 vec3_t forward
, right
, up
;
377 armor
= MSG_ReadByte ();
378 blood
= MSG_ReadByte ();
379 for (i
=0 ; i
<3 ; i
++)
380 from
[i
] = MSG_ReadCoord ();
382 count
= blood
*0.5 + armor
*0.5;
386 cl
.faceanimtime
= cl
.time
+ 0.2; // but sbar face into pain frame
388 cl
.cshifts
[CSHIFT_DAMAGE
].percent
+= 3*count
;
389 if (cl
.cshifts
[CSHIFT_DAMAGE
].percent
< 0)
390 cl
.cshifts
[CSHIFT_DAMAGE
].percent
= 0;
391 if (cl
.cshifts
[CSHIFT_DAMAGE
].percent
> 150)
392 cl
.cshifts
[CSHIFT_DAMAGE
].percent
= 150;
396 if (kurok
) // Flash blue for damage when wearing armor
398 cl
.cshifts
[CSHIFT_DAMAGE
].destcolor
[0] = 100; //r
399 cl
.cshifts
[CSHIFT_DAMAGE
].destcolor
[1] = 100; //g
400 cl
.cshifts
[CSHIFT_DAMAGE
].destcolor
[2] = 200; //b
404 cl
.cshifts
[CSHIFT_DAMAGE
].destcolor
[0] = 200; //r
405 cl
.cshifts
[CSHIFT_DAMAGE
].destcolor
[1] = 100; //g
406 cl
.cshifts
[CSHIFT_DAMAGE
].destcolor
[2] = 100; //b
411 if (kurok
) // Flash blue for damage when wearing armor
413 cl
.cshifts
[CSHIFT_DAMAGE
].destcolor
[0] = 0; //r
414 cl
.cshifts
[CSHIFT_DAMAGE
].destcolor
[1] = 0; //g
415 cl
.cshifts
[CSHIFT_DAMAGE
].destcolor
[2] = 255; //b
419 cl
.cshifts
[CSHIFT_DAMAGE
].destcolor
[0] = 220; //r
420 cl
.cshifts
[CSHIFT_DAMAGE
].destcolor
[1] = 50; //g
421 cl
.cshifts
[CSHIFT_DAMAGE
].destcolor
[2] = 50; //b
426 cl
.cshifts
[CSHIFT_DAMAGE
].destcolor
[0] = 255; //r
427 cl
.cshifts
[CSHIFT_DAMAGE
].destcolor
[1] = 0; //g
428 cl
.cshifts
[CSHIFT_DAMAGE
].destcolor
[2] = 0; //b
432 // calculate view angle kicks
434 ent
= &cl_entities
[cl
.viewentity
];
436 VectorSubtract (from
, ent
->origin
, from
);
437 VectorNormalize (from
);
439 AngleVectors (ent
->angles
, forward
, right
, up
);
441 side
= DotProduct (from
, right
);
442 v_dmg_roll
= count
*side
*v_kickroll
.value
;
444 side
= DotProduct (from
, forward
);
445 v_dmg_pitch
= count
*side
*v_kickpitch
.value
;
447 v_dmg_time
= v_kicktime
.value
;
456 void V_cshift_f (void)
458 cshift_empty
.destcolor
[0] = atoi(Cmd_Argv(1));
459 cshift_empty
.destcolor
[1] = atoi(Cmd_Argv(2));
460 cshift_empty
.destcolor
[2] = atoi(Cmd_Argv(3));
461 cshift_empty
.percent
= atoi(Cmd_Argv(4));
469 When you run over an item, the server sends this command
472 void V_BonusFlash_f (void)
474 cl
.cshifts
[CSHIFT_BONUS
].destcolor
[0] = 128;
475 cl
.cshifts
[CSHIFT_BONUS
].destcolor
[1] = 128;
476 cl
.cshifts
[CSHIFT_BONUS
].destcolor
[2] = 128;
477 cl
.cshifts
[CSHIFT_BONUS
].percent
= 50;
484 Underwater, lava, etc each has a color shift
487 void V_SetContentsColor (int contents
)
493 cl
.cshifts
[CSHIFT_CONTENTS
] = cshift_empty
;
496 cl
.cshifts
[CSHIFT_CONTENTS
] = cshift_lava
;
499 cl
.cshifts
[CSHIFT_CONTENTS
] = cshift_slime
;
503 cl
.cshifts
[CSHIFT_CONTENTS
] = cshift_kwater
;
505 cl
.cshifts
[CSHIFT_CONTENTS
] = cshift_water
;
514 void V_CalcPowerupCshift (void)
516 if (cl
.items
& IT_QUAD
)
518 cl
.cshifts
[CSHIFT_POWERUP
].destcolor
[0] = 0;
519 cl
.cshifts
[CSHIFT_POWERUP
].destcolor
[1] = 0;
520 cl
.cshifts
[CSHIFT_POWERUP
].destcolor
[2] = 255;
521 cl
.cshifts
[CSHIFT_POWERUP
].percent
= 30;
523 else if (cl
.items
& IT_SUIT
)
525 cl
.cshifts
[CSHIFT_POWERUP
].destcolor
[0] = 0;
526 cl
.cshifts
[CSHIFT_POWERUP
].destcolor
[1] = 255;
527 cl
.cshifts
[CSHIFT_POWERUP
].destcolor
[2] = 0;
528 cl
.cshifts
[CSHIFT_POWERUP
].percent
= 20;
530 else if (cl
.items
& IT_INVISIBILITY
)
532 cl
.cshifts
[CSHIFT_POWERUP
].destcolor
[0] = 100;
533 cl
.cshifts
[CSHIFT_POWERUP
].destcolor
[1] = 100;
534 cl
.cshifts
[CSHIFT_POWERUP
].destcolor
[2] = 100;
535 cl
.cshifts
[CSHIFT_POWERUP
].percent
= 50;
537 else if (cl
.items
& IT_INVULNERABILITY
)
539 cl
.cshifts
[CSHIFT_POWERUP
].destcolor
[0] = 255;
540 cl
.cshifts
[CSHIFT_POWERUP
].destcolor
[1] = 255;
541 cl
.cshifts
[CSHIFT_POWERUP
].destcolor
[2] = 255;
542 cl
.cshifts
[CSHIFT_POWERUP
].percent
= 30;
545 cl
.cshifts
[CSHIFT_POWERUP
].percent
= 0;
553 #if defined(GLQUAKE) || defined(PSP_HARDWARE_VIDEO)
554 void V_CalcBlend (void)
556 float r
, g
, b
, a
, a2
;
564 for (j
=0 ; j
<NUM_CSHIFTS
; j
++)
566 if (!gl_cshiftpercent
.value
)
569 a2
= ((cl
.cshifts
[j
].percent
* gl_cshiftpercent
.value
) / 100.0) / 255.0;
571 // a2 = cl.cshifts[j].percent/255.0;
575 //Con_Printf ("j:%i a:%f\n", j, a);
577 r
= r
*(1-a2
) + cl
.cshifts
[j
].destcolor
[0]*a2
;
578 g
= g
*(1-a2
) + cl
.cshifts
[j
].destcolor
[1]*a2
;
579 b
= b
*(1-a2
) + cl
.cshifts
[j
].destcolor
[2]*a2
;
582 v_blend
[0] = r
/255.0;
583 v_blend
[1] = g
/255.0;
584 v_blend
[2] = b
/255.0;
592 Draw_FadeScreenColor (v_blend
[0], v_blend
[1], v_blend
[2], v_blend
[3]);
601 #if defined(GLQUAKE) || defined(PSP_HARDWARE_VIDEO)
602 void V_UpdatePalette (void)
606 // byte *basepal, *newpal;
612 V_CalcPowerupCshift ();
616 for (i
=0 ; i
<NUM_CSHIFTS
; i
++)
618 if (cl
.cshifts
[i
].percent
!= cl
.prev_cshifts
[i
].percent
)
621 cl
.prev_cshifts
[i
].percent
= cl
.cshifts
[i
].percent
;
623 for (j
=0 ; j
<3 ; j
++)
624 if (cl
.cshifts
[i
].destcolor
[j
] != cl
.prev_cshifts
[i
].destcolor
[j
])
627 cl
.prev_cshifts
[i
].destcolor
[j
] = cl
.cshifts
[i
].destcolor
[j
];
631 // drop the damage value
632 cl
.cshifts
[CSHIFT_DAMAGE
].percent
-= host_frametime
*150;
633 if (cl
.cshifts
[CSHIFT_DAMAGE
].percent
<= 0)
634 cl
.cshifts
[CSHIFT_DAMAGE
].percent
= 0;
636 // drop the bonus value
637 cl
.cshifts
[CSHIFT_BONUS
].percent
-= host_frametime
*100;
638 if (cl
.cshifts
[CSHIFT_BONUS
].percent
<= 0)
639 cl
.cshifts
[CSHIFT_BONUS
].percent
= 0;
641 // force = V_CheckGamma ();
642 // if (!new && !force)
649 r = 255*v_blend[0]*a;
650 g = 255*v_blend[1]*a;
651 b = 255*v_blend[2]*a;
654 for (i=0 ; i<256 ; i++)
666 ramps[0][i] = gammatable[ir];
667 ramps[1][i] = gammatable[ig];
668 ramps[2][i] = gammatable[ib];
671 basepal = host_basepal;
674 for (i=0 ; i<256 ; i++)
681 newpal[0] = ramps[0][ir];
682 newpal[1] = ramps[1][ig];
683 newpal[2] = ramps[2][ib];
687 VID_ShiftPalette (pal);
691 void V_UpdatePalette (void)
695 byte
*basepal
, *newpal
;
700 V_CalcPowerupCshift ();
704 for (i
=0 ; i
<NUM_CSHIFTS
; i
++)
706 if (cl
.cshifts
[i
].percent
!= cl
.prev_cshifts
[i
].percent
)
709 cl
.prev_cshifts
[i
].percent
= cl
.cshifts
[i
].percent
;
711 for (j
=0 ; j
<3 ; j
++)
712 if (cl
.cshifts
[i
].destcolor
[j
] != cl
.prev_cshifts
[i
].destcolor
[j
])
715 cl
.prev_cshifts
[i
].destcolor
[j
] = cl
.cshifts
[i
].destcolor
[j
];
719 // drop the damage value
720 cl
.cshifts
[CSHIFT_DAMAGE
].percent
-= host_frametime
*150;
721 if (cl
.cshifts
[CSHIFT_DAMAGE
].percent
<= 0)
722 cl
.cshifts
[CSHIFT_DAMAGE
].percent
= 0;
724 // drop the bonus value
725 cl
.cshifts
[CSHIFT_BONUS
].percent
-= host_frametime
*100;
726 if (cl
.cshifts
[CSHIFT_BONUS
].percent
<= 0)
727 cl
.cshifts
[CSHIFT_BONUS
].percent
= 0;
729 force
= V_CheckGamma ();
733 basepal
= host_basepal
;
736 for (i
=0 ; i
<256 ; i
++)
743 for (j
=0 ; j
<NUM_CSHIFTS
; j
++)
745 r
+= (cl
.cshifts
[j
].percent
*(cl
.cshifts
[j
].destcolor
[0]-r
))>>8;
746 g
+= (cl
.cshifts
[j
].percent
*(cl
.cshifts
[j
].destcolor
[1]-g
))>>8;
747 b
+= (cl
.cshifts
[j
].percent
*(cl
.cshifts
[j
].destcolor
[2]-b
))>>8;
750 newpal
[0] = gammatable
[r
];
751 newpal
[1] = gammatable
[g
];
752 newpal
[2] = gammatable
[b
];
756 VID_ShiftPalette (pal
);
762 ==============================================================================
766 ==============================================================================
769 float angledelta (float a
)
782 void CalcGunAngle (void)
784 float yaw
, pitch
, move
;
785 static float oldyaw
= 0;
786 static float oldpitch
= 0;
788 extern cvar_t in_freelook_analog
;
789 extern cvar_t in_disable_analog
;
790 extern cvar_t in_analog_strafe
;
792 extern cvar_t in_x_axis_adjust
;
793 extern cvar_t in_y_axis_adjust
;
795 yaw
= r_refdef
.viewangles
[YAW
];
796 pitch
= -r_refdef
.viewangles
[PITCH
];
798 yaw
= angledelta(yaw
- r_refdef
.viewangles
[YAW
]) * 0.4;
803 pitch
= angledelta(-pitch
- r_refdef
.viewangles
[PITCH
]) * 0.4;
808 move
= host_frametime
*20;
811 if (oldyaw
+ move
< yaw
)
816 if (oldyaw
- move
> yaw
)
820 if (pitch
> oldpitch
)
822 if (oldpitch
+ move
< pitch
)
823 pitch
= oldpitch
+ move
;
827 if (oldpitch
- move
> pitch
)
828 pitch
= oldpitch
- move
;
834 cl
.viewent
.angles
[YAW
] = r_refdef
.viewangles
[YAW
] + yaw
;
835 cl
.viewent
.angles
[PITCH
] = - (r_refdef
.viewangles
[PITCH
] + pitch
);
837 // Read the pad state.
839 sceCtrlPeekBufferPositive(&pad
, 1);
841 extern cvar_t scr_fov
;
843 if (scr_fov
.value
== 90)
845 cl
.viewent
.angles
[ROLL
] -= sin(cl
.time
*3);
846 if (!in_disable_analog
.value
)
848 if (in_freelook_analog
.value
)
850 if (m_pitch
.value
< 0)
851 cl
.viewent
.angles
[PITCH
] -= sin(cl
.time
*1.8) - ((pad
.Ly
- 128) * in_y_axis_adjust
.value
* 0.015);
853 cl
.viewent
.angles
[PITCH
] -= sin(cl
.time
*1.8) + ((pad
.Ly
- 128) * in_y_axis_adjust
.value
* 0.015);
854 cl
.viewent
.angles
[YAW
] -= sin(cl
.time
*1.5) + ((pad
.Lx
- 128) * in_x_axis_adjust
.value
* 0.015);
858 if (!in_analog_strafe
.value
)
859 cl
.viewent
.angles
[YAW
] -= sin(cl
.time
*1.5) + ((pad
.Lx
- 128) * in_x_axis_adjust
.value
* 0.015);
863 if (cl_gunpitch
.value
)
864 cl
.viewent
.angles
[PITCH
] -= cl_gunpitch
.value
;
869 cl
.viewent
.angles
[ROLL
] -= v_idlescale
.value
* sin(cl
.time
*v_iroll_cycle
.value
) * v_iroll_level
.value
;
870 cl
.viewent
.angles
[PITCH
] -= v_idlescale
.value
* sin(cl
.time
*v_ipitch_cycle
.value
) * v_ipitch_level
.value
;
871 cl
.viewent
.angles
[YAW
] -= v_idlescale
.value
* sin(cl
.time
*v_iyaw_cycle
.value
) * v_iyaw_level
.value
;
881 void V_BoundOffsets (void)
885 ent
= &cl_entities
[cl
.viewentity
];
887 // absolutely bound refresh reletive to entity clipping hull
888 // so the view can never be inside a solid wall
890 if (r_refdef
.vieworg
[0] < ent
->origin
[0] - 14)
891 r_refdef
.vieworg
[0] = ent
->origin
[0] - 14;
892 else if (r_refdef
.vieworg
[0] > ent
->origin
[0] + 14)
893 r_refdef
.vieworg
[0] = ent
->origin
[0] + 14;
894 if (r_refdef
.vieworg
[1] < ent
->origin
[1] - 14)
895 r_refdef
.vieworg
[1] = ent
->origin
[1] - 14;
896 else if (r_refdef
.vieworg
[1] > ent
->origin
[1] + 14)
897 r_refdef
.vieworg
[1] = ent
->origin
[1] + 14;
898 if (r_refdef
.vieworg
[2] < ent
->origin
[2] - 22)
899 r_refdef
.vieworg
[2] = ent
->origin
[2] - 22;
900 else if (r_refdef
.vieworg
[2] > ent
->origin
[2] + 30)
901 r_refdef
.vieworg
[2] = ent
->origin
[2] + 30;
911 void V_AddIdle (void)
919 xyspeed = sqrt(cl.velocity[0]*cl.velocity[0] + cl.velocity[1]*cl.velocity[1]);
920 bspeed = xyspeed * 0.15f;
922 r_refdef.viewangles[ROLL] += v_idlescale.value * sinf(cl.time*v_iroll_cycle.value) * (v_iroll_level.value * bspeed);
923 r_refdef.viewangles[PITCH] += v_idlescale.value * sinf(cl.time*v_ipitch_cycle.value) * (v_ipitch_level.value * bspeed);
924 r_refdef.viewangles[YAW] += v_idlescale.value * sinf(cl.time*v_iyaw_cycle.value) * (v_iyaw_level.value * bspeed);
926 r_refdef.viewangles[ROLL] += (v_idlescale.value * 3 ) * sinf(cl.time*v_iroll_cycle.value * 0.25 ) * v_iroll_level.value;
927 r_refdef.viewangles[PITCH] += (v_idlescale.value * 3 ) * sinf(cl.time*v_ipitch_cycle.value * 0.25 ) * v_ipitch_level.value;
928 r_refdef.viewangles[YAW] += (v_idlescale.value * 3 ) * sinf(cl.time*v_iyaw_cycle.value * 0.25 ) * v_iyaw_level.value;
933 r_refdef
.viewangles
[ROLL
] += v_idlescale
.value
* sinf(cl
.time
*v_iroll_cycle
.value
) * v_iroll_level
.value
;
934 r_refdef
.viewangles
[PITCH
] += v_idlescale
.value
* sinf(cl
.time
*v_ipitch_cycle
.value
) * v_ipitch_level
.value
;
935 r_refdef
.viewangles
[YAW
] += v_idlescale
.value
* sinf(cl
.time
*v_iyaw_cycle
.value
) * v_iyaw_level
.value
;
944 Roll is induced by movement and damage
947 void V_CalcViewRoll (void)
951 side
= V_CalcRoll (cl_entities
[cl
.viewentity
].angles
, cl
.velocity
);
952 r_refdef
.viewangles
[ROLL
] += side
;
956 r_refdef
.viewangles
[ROLL
] += v_dmg_time
/v_kicktime
.value
*v_dmg_roll
;
957 r_refdef
.viewangles
[PITCH
] += v_dmg_time
/v_kicktime
.value
*v_dmg_pitch
;
958 v_dmg_time
-= host_frametime
;
961 if (cl
.stats
[STAT_HEALTH
] <= 0)
963 r_refdef
.viewangles
[ROLL
] = 80; // dead view angle
972 V_CalcIntermissionRefdef
976 void V_CalcIntermissionRefdef (void)
978 entity_t
*ent
, *view
;
981 // ent is the player model (visible when out of body)
982 ent
= &cl_entities
[cl
.viewentity
];
983 // view is the weapon model (only visible from inside body)
986 VectorCopy (ent
->origin
, r_refdef
.vieworg
);
987 VectorCopy (ent
->angles
, r_refdef
.viewangles
);
990 // allways idle in intermission
993 old
= v_idlescale
.value
;
994 v_idlescale
.value
= 1;
996 v_idlescale
.value
= old
;
1006 void V_CalcRefdef (void)
1008 entity_t
*ent
, *view
;
1010 vec3_t forward
, right
, up
;
1013 static float oldz
= 0;
1017 // ent is the player model (visible when out of body)
1018 ent
= &cl_entities
[cl
.viewentity
];
1019 // view is the weapon model (only visible from inside body)
1023 // transform the view offset by the model's matrix to get the offset from
1024 // model origin for the view
1025 ent
->angles
[YAW
] = cl
.viewangles
[YAW
]; // the model should face
1027 ent
->angles
[PITCH
] = -cl
.viewangles
[PITCH
]; // the model should face
1029 if (chase_active
.value
)
1037 bobside
= V_CalcBobSide ();
1041 VectorCopy (ent
->origin
, r_refdef
.vieworg
);
1042 r_refdef
.vieworg
[2] += cl
.viewheight
+ bob
;
1044 // never let it sit exactly on a node line, because a water plane can
1045 // dissapear when viewed with the eye exactly on it.
1046 // the server protocol only specifies to 1/16 pixel, so add 1/32 in each axis
1047 r_refdef
.vieworg
[0] += 1.0/32;
1048 r_refdef
.vieworg
[1] += 1.0/32;
1049 r_refdef
.vieworg
[2] += 1.0/32;
1051 VectorCopy (cl
.viewangles
, r_refdef
.viewangles
);
1053 if (!chase_active
.value
)
1060 angles
[PITCH
] = -ent
->angles
[PITCH
]; // because entity pitches are
1061 // actually backward
1062 angles
[YAW
] = ent
->angles
[YAW
];
1063 angles
[ROLL
] = ent
->angles
[ROLL
];
1065 AngleVectors (angles
, forward
, right
, up
);
1067 for (i
=0 ; i
<3 ; i
++)
1068 r_refdef
.vieworg
[i
] += scr_ofsx
.value
*forward
[i
]
1069 + scr_ofsy
.value
*right
[i
]
1070 + scr_ofsz
.value
*up
[i
];
1075 // set up gun position
1076 VectorCopy (cl
.viewangles
, view
->angles
);
1080 VectorCopy (ent
->origin
, view
->origin
);
1081 view
->origin
[2] += cl
.viewheight
;
1083 for (i
=0 ; i
<3 ; i
++)
1085 // view->origin[i] += forward[i]*bob*0.2;
1086 view
->origin
[i
] += right
[i
]*bobside
*0.2;
1087 view
->origin
[i
] += up
[i
]*bob
*0.2;
1089 view
->origin
[2] += bob
;
1094 // fudge position around to keep amount of weapon visible
1095 // roughly equal with different FOV
1098 if (cl
.model_precache
[cl
.stats
[STAT_WEAPON
]] && strcmp (cl
.model_precache
[cl
.stats
[STAT_WEAPON
]]->name
, "progs/v_shot2.mdl"))
1100 if (scr_viewsize
.value
== 130)
1101 view
->origin
[2] += 2.25;
1102 else if (scr_viewsize
.value
== 120)
1103 view
->origin
[2] += 2.25;
1104 else if (scr_viewsize
.value
== 110)
1105 view
->origin
[2] += 2.5;
1106 else if (scr_viewsize
.value
== 100)
1107 view
->origin
[2] += 3;
1108 else if (scr_viewsize
.value
== 90)
1109 view
->origin
[2] += 2.5;
1110 else if (scr_viewsize
.value
<= 80)
1111 view
->origin
[2] += 2;
1114 view
->model
= cl
.model_precache
[cl
.stats
[STAT_WEAPON
]];
1115 view
->frame
= cl
.stats
[STAT_WEAPONFRAME
];
1116 view
->colormap
= vid
.colormap
;
1118 // set up the refresh position
1119 VectorAdd (r_refdef
.viewangles
, cl
.punchangle
, r_refdef
.viewangles
);
1121 // smooth out stair step ups
1122 if (cl
.onground
&& ent
->origin
[2] - oldz
> 0)
1126 steptime
= cl
.time
- cl
.oldtime
;
1128 //FIXME I_Error ("steptime < 0");
1131 oldz
+= steptime
* 80;
1132 if (oldz
> ent
->origin
[2])
1133 oldz
= ent
->origin
[2];
1134 if (ent
->origin
[2] - oldz
> 12)
1135 oldz
= ent
->origin
[2] - 12;
1136 r_refdef
.vieworg
[2] += oldz
- ent
->origin
[2];
1137 view
->origin
[2] += oldz
- ent
->origin
[2];
1140 oldz
= ent
->origin
[2];
1142 if (chase_active
.value
)
1150 The player's clipping box goes from (-16 -16 -24) to (16 16 32) from
1151 the entity origin, so any view position inside that will be valid
1154 extern vrect_t scr_vrect
;
1156 void V_RenderView (void)
1163 // don't allow cheats in multiplayer
1164 if (cl
.maxclients
> 1)
1166 Cvar_Set ("scr_ofsx", "0");
1167 Cvar_Set ("scr_ofsy", "0");
1168 Cvar_Set ("scr_ofsz", "0");
1172 if (cl
.intermission
)
1173 { // intermission / finale rendering
1174 V_CalcIntermissionRefdef ();
1178 if (!cl
.paused
/* && (sv.maxclients > 1 || key_dest == key_game) */ )
1187 // render two interleaved views
1194 r_refdef
.viewangles
[YAW
] -= lcd_yaw
.value
;
1195 for (i
=0 ; i
<3 ; i
++)
1196 r_refdef
.vieworg
[i
] -= right
[i
]*lcd_x
.value
;
1199 vid
.buffer
+= vid
.rowbytes
>>1;
1203 r_refdef
.viewangles
[YAW
] += lcd_yaw
.value
*2;
1204 for (i
=0 ; i
<3 ; i
++)
1205 r_refdef
.vieworg
[i
] += 2*right
[i
]*lcd_x
.value
;
1208 vid
.buffer
-= vid
.rowbytes
>>1;
1210 r_refdef
.vrect
.height
<<= 1;
1220 #if !defined(GLQUAKE) && !defined(PSP_HARDWARE_VIDEO)
1221 if (crosshair
.value
)
1223 // Draw_Character (scr_vrect.x + scr_vrect.width/2 + cl_crossx.value, scr_vrect.y + scr_vrect.height/2 + cl_crossy.value, '+');
1228 //============================================================================
1237 Cmd_AddCommand ("v_cshift", V_cshift_f
);
1238 Cmd_AddCommand ("bf", V_BonusFlash_f
);
1239 Cmd_AddCommand ("centerview", V_StartPitchDrift
);
1241 Cvar_RegisterVariable (&lcd_x
);
1242 Cvar_RegisterVariable (&lcd_yaw
);
1244 Cvar_RegisterVariable (&v_centermove
);
1245 Cvar_RegisterVariable (&v_centerspeed
);
1247 Cvar_RegisterVariable (&v_iyaw_cycle
);
1248 Cvar_RegisterVariable (&v_iroll_cycle
);
1249 Cvar_RegisterVariable (&v_ipitch_cycle
);
1250 Cvar_RegisterVariable (&v_iyaw_level
);
1251 Cvar_RegisterVariable (&v_iroll_level
);
1252 Cvar_RegisterVariable (&v_ipitch_level
);
1254 Cvar_RegisterVariable (&v_idlescale
);
1255 Cvar_RegisterVariable (&crosshair
);
1256 Cvar_RegisterVariable (&cl_crossx
);
1257 Cvar_RegisterVariable (&cl_crossy
);
1258 Cvar_RegisterVariable (&gl_cshiftpercent
);
1260 Cvar_RegisterVariable (&scr_ofsx
);
1261 Cvar_RegisterVariable (&scr_ofsy
);
1262 Cvar_RegisterVariable (&scr_ofsz
);
1263 Cvar_RegisterVariable (&cl_rollspeed
);
1264 Cvar_RegisterVariable (&cl_rollangle
);
1266 Cvar_RegisterVariable (&cl_bob
);
1267 Cvar_RegisterVariable (&cl_bobcycle
);
1268 Cvar_RegisterVariable (&cl_bobup
);
1270 Cvar_RegisterVariable (&cl_bobside
);
1271 Cvar_RegisterVariable (&cl_bobsidecycle
);
1272 Cvar_RegisterVariable (&cl_bobsideup
);
1274 Cvar_RegisterVariable (&cl_gunpitch
);
1276 Cvar_RegisterVariable (&v_kicktime
);
1277 Cvar_RegisterVariable (&v_kickroll
);
1278 Cvar_RegisterVariable (&v_kickpitch
);
1280 BuildGammaTable (1.0); // no gamma yet
1281 Cvar_RegisterVariable (&v_gamma
);