Client: add camera.qc and viewmodel.qc, better restructure how we apply
effects to the view. Add CVARs v_cambob, v_camroll, v_bobstyle...
This commit is contained in:
parent
37c5c6efdd
commit
affa7b4a0c
5 changed files with 239 additions and 62 deletions
79
src/client/camera.qc
Normal file
79
src/client/camera.qc
Normal file
|
@ -0,0 +1,79 @@
|
|||
/*
|
||||
* Copyright (c) 2016-2021 Marco Hladik <marco@icculus.org>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
|
||||
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
struct
|
||||
{
|
||||
float m_flSpeed;
|
||||
float m_flFracSin;
|
||||
float m_flTime;
|
||||
float m_flMove;
|
||||
float m_flDelta;
|
||||
int m_iCycle;
|
||||
} g_camBobVars[4], *pCamBob;
|
||||
|
||||
/* tilts the camera for a head-bob like effect when moving */
|
||||
void
|
||||
Camera_RunBob(__inout vector camera_angle)
|
||||
{
|
||||
if (!autocvar(v_cambob, 0, "Enables bobbing effect for the first-person camera"))
|
||||
return;
|
||||
|
||||
int s = (float)getproperty(VF_ACTIVESEAT);
|
||||
pCamBob = &g_camBobVars[s];
|
||||
|
||||
/* we don't really care about the vertical velocity */
|
||||
vector speed = pSeat->m_vecPredictedVelocity;
|
||||
speed[2] = 0.0f;
|
||||
pCamBob->m_flSpeed = vlen(speed);
|
||||
|
||||
/* don't bother on low speeds */
|
||||
if ( pCamBob->m_flSpeed < 5.0f ) {
|
||||
pCamBob->m_flMove = 0.0f;
|
||||
pCamBob->m_flTime = 0.0f; /* progress has halted, start anew */
|
||||
return;
|
||||
} else if (pSeat->m_ePlayer.flags & FL_ONGROUND) {
|
||||
pCamBob->m_flMove = clframetime * (pCamBob->m_flSpeed * 0.01);
|
||||
}
|
||||
|
||||
pCamBob->m_flTime = (pCamBob->m_flTime += pCamBob->m_flMove);
|
||||
pCamBob->m_flFracSin = fabs(sin(pCamBob->m_flTime * M_PI));
|
||||
pCamBob->m_iCycle = (int)pCamBob->m_flTime;
|
||||
pCamBob->m_flDelta = (pCamBob->m_flFracSin * 0.0025f) * pCamBob->m_flSpeed;
|
||||
|
||||
camera_angle[0] += pCamBob->m_flDelta;
|
||||
|
||||
if (pCamBob->m_iCycle & 1) {
|
||||
pCamBob->m_flDelta = -pCamBob->m_flDelta;
|
||||
}
|
||||
|
||||
camera_angle[2] += pCamBob->m_flDelta;
|
||||
}
|
||||
|
||||
/* applies a tilt to the camera for when we're strafing left to right */
|
||||
float
|
||||
Camera_StrafeRoll(__inout vector camera_angle)
|
||||
{
|
||||
if (!autocvar(v_camroll, 1, "Enables strafe-roll for the first-person camera"))
|
||||
return;
|
||||
|
||||
float roll;
|
||||
makevectors(camera_angle);
|
||||
|
||||
roll = dotproduct(pSeat->m_vecPredictedVelocity, v_right);
|
||||
roll *= 0.015f;
|
||||
|
||||
camera_angle[2] += roll;
|
||||
}
|
|
@ -35,14 +35,9 @@ var float FONT_20;
|
|||
var float FONT_CON;
|
||||
|
||||
/* clientside cvars */
|
||||
var float autocvar_cl_bob = 0;
|
||||
var float autocvar_v_bob = 0.01;
|
||||
var float autocvar_v_bobcycle = 0.8;
|
||||
var float autocvar_v_bobup = 0.5;
|
||||
var float autocvar_zoom_sensitivity = 1.0f;
|
||||
var int autocvar_cl_smoothstairs = TRUE;
|
||||
var int autocvar_cl_thirdperson = FALSE;
|
||||
var int autocvar_v_bobclassic = TRUE;
|
||||
var int autocvar_v_lefthanded = FALSE;
|
||||
var string autocvar_cl_logofile = "lambda";
|
||||
var vector autocvar_cl_logocolor = [255,0,0];
|
||||
|
@ -134,8 +129,6 @@ struct
|
|||
|
||||
int m_iLastWeapon;
|
||||
int m_iOldWeapon;
|
||||
float m_flBobTime;
|
||||
float m_flBob;
|
||||
|
||||
/* damage overlay */
|
||||
float m_flDamageAlpha;
|
||||
|
|
|
@ -15,6 +15,8 @@ predict.qc
|
|||
npc.qc
|
||||
entities.qc
|
||||
modelevent.qc
|
||||
camera.qc
|
||||
viewmodel.qc
|
||||
view.qc
|
||||
damage.qc
|
||||
chat.qc
|
||||
|
|
|
@ -14,8 +14,6 @@
|
|||
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
var int autocvar_v_camroll = TRUE;
|
||||
|
||||
void
|
||||
View_Init(void)
|
||||
{
|
||||
|
@ -58,7 +56,7 @@ View_AddEvent(void(void) pCallback, float flTime)
|
|||
pSeat->m_flEventMdl = pSeat->m_eViewModel.modelindex;
|
||||
}
|
||||
|
||||
void
|
||||
void
|
||||
View_CalcViewport(int s, float fWinWidth, float fWinHeight)
|
||||
{
|
||||
//FIXME: this is awkward. renderscene internally rounds to pixels.
|
||||
|
@ -96,45 +94,6 @@ View_CalcViewport(int s, float fWinWidth, float fWinHeight)
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
View_CalcBob(void)
|
||||
{
|
||||
float cycle;
|
||||
vector vel;
|
||||
|
||||
if (self.flags & FL_ONGROUND == -1) {
|
||||
return;
|
||||
}
|
||||
|
||||
pSeat->m_flBobTime += clframetime;
|
||||
cycle = pSeat->m_flBobTime - (int)(pSeat->m_flBobTime / autocvar_v_bobcycle) * autocvar_v_bobcycle;
|
||||
cycle /= autocvar_v_bobcycle;
|
||||
|
||||
if (cycle < autocvar_v_bobup) {
|
||||
cycle = MATH_PI * cycle / autocvar_v_bobup;
|
||||
} else {
|
||||
cycle = MATH_PI + MATH_PI * (cycle - autocvar_v_bobup)/(1.0 - autocvar_v_bobup);
|
||||
}
|
||||
|
||||
vel = pSeat->m_vecPredictedVelocity;
|
||||
vel[2] = 0;
|
||||
|
||||
float flBob = sqrt(vel[0] * vel[0] + vel[1] * vel[1]) * autocvar_v_bob;
|
||||
flBob = flBob * 0.3 + flBob * 0.7 * sin(cycle);
|
||||
pSeat->m_flBob = bound(-7, flBob, 4);
|
||||
}
|
||||
|
||||
float
|
||||
View_CalcRoll(void)
|
||||
{
|
||||
float roll;
|
||||
makevectors(view_angles);
|
||||
|
||||
roll = dotproduct(pSeat->m_vecPredictedVelocity, v_right);
|
||||
roll *= 0.015f;
|
||||
return autocvar_v_camroll ? roll : 0;
|
||||
}
|
||||
|
||||
/*
|
||||
====================
|
||||
View_DrawViewModel
|
||||
|
@ -159,13 +118,12 @@ View_DrawViewModel(void)
|
|||
return;
|
||||
}
|
||||
|
||||
View_CalcBob();
|
||||
View_UpdateWeapon(m_eViewModel, m_eMuzzleflash);
|
||||
|
||||
float fBaseTime2 = m_eViewModel.frame1time;
|
||||
float fBaseTime = m_eViewModel.frame1time;
|
||||
m_eViewModel.frame2time = pl.weapontime;
|
||||
m_eViewModel.frame1time = pl.weapontime;
|
||||
m_eViewModel.frame1time = pl.weapontime;
|
||||
Event_Callback(m_eViewModel.frame1time, fBaseTime2);
|
||||
processmodelevents(m_eViewModel.modelindex, m_eViewModel.frame, fBaseTime,
|
||||
m_eViewModel.frame1time, ClientGame_ModelEvent);
|
||||
|
@ -174,20 +132,12 @@ View_DrawViewModel(void)
|
|||
m_eViewModel.angles = view_angles;
|
||||
m_eViewModel.colormap = pSeat->m_ePlayer.colormap;
|
||||
|
||||
// Give the gun a tilt effect like in old HL/CS versions
|
||||
if (autocvar_v_bobclassic == 1) {
|
||||
m_eViewModel.angles[2] = -pSeat->m_flBob;
|
||||
}
|
||||
|
||||
/* now apply the scale hack */
|
||||
m_eViewModel.scale = autocvar_r_viewmodelscale;
|
||||
pSeat->m_flBob *= autocvar_r_viewmodelscale;
|
||||
m_eViewModel.origin = pSeat->m_vecPredictedOrigin + pl.view_ofs;
|
||||
|
||||
m_eViewModel.origin += [0,0,-1] + (v_forward * (pSeat->m_flBob * 0.4))
|
||||
+ (v_forward * autocvar_v_gunofs[0])
|
||||
+ (v_right * autocvar_v_gunofs[1])
|
||||
+ (v_up * autocvar_v_gunofs[2]);
|
||||
Viewmodel_CalcBob();
|
||||
Viewmodel_ApplyBob(m_eViewModel);
|
||||
|
||||
// Left-handed weapons
|
||||
if (autocvar_v_lefthanded) {
|
||||
|
@ -220,7 +170,8 @@ View_DrawViewModel(void)
|
|||
}
|
||||
|
||||
if (pl.movetype == MOVETYPE_WALK) {
|
||||
view_angles[2] = View_CalcRoll();
|
||||
Camera_StrafeRoll(view_angles);
|
||||
Camera_RunBob(view_angles);
|
||||
setproperty(VF_ANGLES, view_angles + pl.punchangle);
|
||||
}
|
||||
}
|
||||
|
|
152
src/client/viewmodel.qc
Normal file
152
src/client/viewmodel.qc
Normal file
|
@ -0,0 +1,152 @@
|
|||
/*
|
||||
* Copyright (c) 2016-2021 Marco Hladik <marco@icculus.org>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
|
||||
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
var float autocvar_v_bob = 0.01;
|
||||
var float autocvar_v_bobcycle = 0.8;
|
||||
var float autocvar_v_bobup = 0.5;
|
||||
var int autocvar_v_bobstyle = 1;
|
||||
|
||||
enum
|
||||
{
|
||||
BOB_NONE,
|
||||
BOB_CLASSIC,
|
||||
BOB_VISIONS
|
||||
};
|
||||
|
||||
struct
|
||||
{
|
||||
float m_flBobTime;
|
||||
float m_flBob;
|
||||
float m_flBobCycle;
|
||||
float m_flSpeed;
|
||||
} g_viewBobVars[4], *pViewBob;
|
||||
|
||||
/* classic bob, similar to Q1 and HL */
|
||||
void
|
||||
Viewmodel_ClassicBobCalc(void)
|
||||
{
|
||||
vector vel;
|
||||
|
||||
pViewBob->m_flBobTime += clframetime;
|
||||
pViewBob->m_flBobCycle = pViewBob->m_flBobTime - (int)(pViewBob->m_flBobTime / autocvar_v_bobcycle) * autocvar_v_bobcycle;
|
||||
pViewBob->m_flBobCycle /= autocvar_v_bobcycle;
|
||||
|
||||
if (pViewBob->m_flBobCycle < autocvar_v_bobup) {
|
||||
pViewBob->m_flBobCycle = MATH_PI * pViewBob->m_flBobCycle / autocvar_v_bobup;
|
||||
} else {
|
||||
pViewBob->m_flBobCycle = MATH_PI + MATH_PI * (pViewBob->m_flBobCycle - autocvar_v_bobup)/(1.0 - autocvar_v_bobup);
|
||||
}
|
||||
|
||||
vel = pSeat->m_vecPredictedVelocity;
|
||||
vel[2] = 0;
|
||||
pViewBob->m_flSpeed = vlen(vel);
|
||||
|
||||
float flBob = pViewBob->m_flSpeed * autocvar_v_bob;
|
||||
flBob = flBob * 0.3 + flBob * 0.7 * sin(pViewBob->m_flBobCycle);
|
||||
pViewBob->m_flBob = bound(-7, flBob, 4);
|
||||
}
|
||||
|
||||
void
|
||||
Viewmodel_ClassicBobRun(entity gun)
|
||||
{
|
||||
// Give the gun a tilt effect like in old HL/CS versions
|
||||
if (autocvar(v_bobclassic, 1, "Viewmodel bob classic tilt switch") == 1) {
|
||||
gun.angles[2] = -pViewBob->m_flBob;
|
||||
}
|
||||
|
||||
gun.origin += [0,0,-1] + (v_forward * (pViewBob->m_flBob * 0.4))
|
||||
+ (v_forward * autocvar_v_gunofs[0])
|
||||
+ (v_right * autocvar_v_gunofs[1])
|
||||
+ (v_up * autocvar_v_gunofs[2]);
|
||||
}
|
||||
|
||||
/* Vera Visions signature bob */
|
||||
void
|
||||
Viewmodel_VisionsBobCalc(void)
|
||||
{
|
||||
/* same for now */
|
||||
Viewmodel_ClassicBobCalc();
|
||||
}
|
||||
|
||||
void
|
||||
Viewmodel_VisionsBobRun(entity gun)
|
||||
{
|
||||
float sintime;
|
||||
float strength;
|
||||
gun.angles[2] = -pViewBob->m_flBob;
|
||||
|
||||
vector angmod;
|
||||
angmod[0] += pViewBob->m_flBob * 0.5f;
|
||||
angmod[1] += pViewBob->m_flBob;
|
||||
angmod[2] += pViewBob->m_flBob * 2.0f;
|
||||
gun.angles += angmod * 2.0f;
|
||||
|
||||
/* sway with speed */
|
||||
sintime = sin( time * 1.5f);
|
||||
strength = pViewBob->m_flSpeed * 0.01f;
|
||||
gun.angles[0] += strength * sintime;
|
||||
gun.angles[1] += strength * sintime;
|
||||
gun.angles[2] += strength * sintime;
|
||||
|
||||
gun.origin += [0,0,-1] - (v_up * (-pViewBob->m_flBob * 0.2))
|
||||
+ (v_forward * autocvar_v_gunofs[0])
|
||||
+ (v_right * autocvar_v_gunofs[1])
|
||||
+ (v_up * autocvar_v_gunofs[2]);
|
||||
}
|
||||
|
||||
/* bob vars are calculated separately from application, so that if there's
|
||||
* more than one viewmodel we won't affect the speed of the bob by running
|
||||
* the math too many times */
|
||||
void
|
||||
Viewmodel_CalcBob(void)
|
||||
{
|
||||
int s = (float)getproperty(VF_ACTIVESEAT);
|
||||
pViewBob = &g_viewBobVars[s];
|
||||
|
||||
switch (autocvar_v_bobstyle)
|
||||
{
|
||||
case BOB_CLASSIC:
|
||||
Viewmodel_ClassicBobCalc();
|
||||
break;
|
||||
case BOB_VISIONS:
|
||||
Viewmodel_VisionsBobCalc();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/* make sure it's adjusted for scale */
|
||||
pViewBob->m_flBob *= autocvar_r_viewmodelscale;
|
||||
}
|
||||
|
||||
void
|
||||
Viewmodel_ApplyBob(entity gun)
|
||||
{
|
||||
int s = (float)getproperty(VF_ACTIVESEAT);
|
||||
pViewBob = &g_viewBobVars[s];
|
||||
|
||||
switch (autocvar_v_bobstyle)
|
||||
{
|
||||
case BOB_CLASSIC:
|
||||
Viewmodel_ClassicBobRun(gun);
|
||||
break;
|
||||
case BOB_VISIONS:
|
||||
Viewmodel_VisionsBobRun(gun);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue