350 lines
9.5 KiB
Plaintext
350 lines
9.5 KiB
Plaintext
/*
|
|
* Copyright (c) 2016-2022 Vera Visions LLC.
|
|
*
|
|
* 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 bool autocvar_cg_viewmodelLag = 0;
|
|
var bool autocvar_cg_muzzleDLight = 1;
|
|
|
|
void
|
|
View_Init(void)
|
|
{
|
|
for (int s = g_seats.length; s-- > numclientseats;) {
|
|
pSeat = &g_seats[s];
|
|
if(!pSeat->m_eViewModel) {
|
|
/* right side */
|
|
pSeat->m_eViewModel = spawn();
|
|
pSeat->m_eViewModel.classname = "vm";
|
|
pSeat->m_eViewModel.renderflags = RF_DEPTHHACK | RF_FIRSTPERSON;
|
|
pSeat->m_eViewModel.effects |= EF_NOSHADOW;
|
|
pSeat->m_eViewModel.alpha = 1.0f;
|
|
setsize(pSeat->m_eViewModel, [0,0,0], [0,0,0]);
|
|
|
|
pSeat->m_eMuzzleflash = spawn();
|
|
pSeat->m_eMuzzleflash.classname = "mflash";
|
|
pSeat->m_eMuzzleflash.renderflags = RF_ADDITIVE | RF_FIRSTPERSON;
|
|
pSeat->m_eMuzzleflash.effects |= EF_NOSHADOW;
|
|
setsize(pSeat->m_eMuzzleflash, [0,0,0], [0,0,0]);
|
|
|
|
/* left side */
|
|
pSeat->m_eViewModelL = spawn();
|
|
pSeat->m_eViewModelL.classname = "vm";
|
|
pSeat->m_eViewModelL.renderflags = RF_DEPTHHACK | RF_FIRSTPERSON;
|
|
pSeat->m_eViewModelL.effects |= EF_NOSHADOW;
|
|
pSeat->m_eViewModelL.alpha = 1.0f;
|
|
setsize(pSeat->m_eViewModelL, [0,0,0], [0,0,0]);
|
|
|
|
pSeat->m_eMuzzleflashL = spawn();
|
|
pSeat->m_eMuzzleflashL.classname = "mflash";
|
|
pSeat->m_eMuzzleflashL.renderflags = RF_ADDITIVE | RF_FIRSTPERSON;
|
|
pSeat->m_eMuzzleflashL.effects |= EF_NOSHADOW;
|
|
setsize(pSeat->m_eMuzzleflashL, [0,0,0], [0,0,0]);
|
|
}
|
|
}
|
|
}
|
|
|
|
void
|
|
View_SetMuzzleflash(int index)
|
|
{
|
|
pSeat->m_eMuzzleflash.modelindex = (float)index;
|
|
}
|
|
|
|
void
|
|
View_AddEvent(void(void) pCallback, float flTime)
|
|
{
|
|
pSeat->m_pEventCall = pCallback;
|
|
pSeat->m_flEventTime = flTime;
|
|
pSeat->m_flEventFrame = pSeat->m_eViewModel.frame;
|
|
pSeat->m_flEventMdl = pSeat->m_eViewModel.modelindex;
|
|
NSClientPlayer pl = (NSClientPlayer)pSeat->m_ePlayer;
|
|
pSeat->m_iEventWeapon = pl.activeweapon;
|
|
}
|
|
|
|
void
|
|
View_ClearEvents(void)
|
|
{
|
|
pSeat->m_pEventCall = __NULL__;
|
|
pSeat->m_flEventTime = 0;
|
|
pSeat->m_flEventFrame = 0;
|
|
pSeat->m_flEventMdl = 0;
|
|
pSeat->m_iEventWeapon = 0;
|
|
|
|
pSeat->m_eViewModelL.frame1time = 0.0f;
|
|
pSeat->m_eViewModel.frame1time = 0.0f;
|
|
pSeat->m_eMuzzleflash.modelindex =
|
|
pSeat->m_eMuzzleflashL.modelindex =
|
|
pSeat->m_eMuzzleflash.alpha =
|
|
pSeat->m_eMuzzleflashL.alpha =
|
|
pSeat->m_eMuzzleflash.frame1time =
|
|
pSeat->m_eMuzzleflashL.frame1time = 0;
|
|
}
|
|
|
|
void
|
|
View_CalcViewport(int s, float fWinWidth, float fWinHeight)
|
|
{
|
|
switch (numclientseats) {
|
|
case 3:
|
|
if (!s) {
|
|
case 2:
|
|
g_viewSeats[s].SetViewSize([fWinWidth, fWinHeight * 0.5]);
|
|
g_viewSeats[s].SetViewPosition([0, (s & 1) * g_viewSeats[s].GetViewHeight()]);
|
|
break;
|
|
}
|
|
s++;
|
|
case 4:
|
|
g_viewSeats[s].SetViewSize([fWinWidth, fWinHeight] * 0.5);
|
|
g_viewSeats[s].SetViewPosition([(s&1) * g_viewSeats[s].GetViewWidth(), (s / 2i) * g_viewSeats[s].GetViewHeight()]);
|
|
break;
|
|
default:
|
|
g_viewSeats[s].SetViewSize([fWinWidth, fWinHeight]);
|
|
//g_viewSeats[s].SetViewPosition([0, 0]);
|
|
break;
|
|
}
|
|
|
|
video_res = g_viewSeats[s].m_vecSize;
|
|
video_mins = g_viewSeats[s].m_vecPosition;
|
|
g_hudmins = g_viewSeats[s].GetHUDCanvasPos();
|
|
g_hudres = g_viewSeats[s].GetHUDCanvasSize();
|
|
}
|
|
|
|
void
|
|
View_DrawViewmodel_Single(int weapon, float weapontime)
|
|
{
|
|
|
|
}
|
|
|
|
/*
|
|
====================
|
|
View_DrawViewModel
|
|
|
|
Really convoluted function that makes the gun,
|
|
muzzleflash, dynamic lights and so on appear
|
|
====================
|
|
*/
|
|
void
|
|
View_DrawViewModel(void)
|
|
{
|
|
entity m_eViewModel = pSeat->m_eViewModel;
|
|
entity m_eMuzzleflash = pSeat->m_eMuzzleflash;
|
|
entity m_eViewModelL = pSeat->m_eViewModelL;
|
|
entity m_eMuzzleflashL = pSeat->m_eMuzzleflashL;
|
|
|
|
player pl = __NULL__;
|
|
NSClient cl = (NSClient)pSeat->m_ePlayer;
|
|
|
|
/* it's either us or us spectating */
|
|
if (Client_IsSpectator(cl)) {
|
|
NSClientSpectator spec = (NSClientSpectator)pSeat->m_ePlayer;
|
|
pl = (player)findfloat(world, ::entnum, spec.spec_ent);
|
|
|
|
if (spec.spec_mode != SPECMODE_FIRSTPERSON)
|
|
return;
|
|
} else {
|
|
pl = (player)pSeat->m_ePlayer;
|
|
}
|
|
|
|
if (!pl)
|
|
return;
|
|
|
|
if (pl.health <= 0) {
|
|
return;
|
|
}
|
|
|
|
if (pl.vehicle) {
|
|
NSVehicle veh = (NSVehicle)pl.vehicle;
|
|
|
|
if (veh.HideViewWeapon() == true)
|
|
return;
|
|
}
|
|
|
|
if (cvar("r_drawviewmodel") == 0 || autocvar_pm_thirdPerson == TRUE) {
|
|
return;
|
|
}
|
|
|
|
View_UpdateWeapon(pl, m_eViewModel, m_eMuzzleflash);
|
|
float fBaseTime2 = m_eViewModel.frame1time;
|
|
float fBaseTime = m_eViewModel.frame1time;
|
|
m_eViewModelL.frame = m_eViewModel.frame = pl.weaponframe;
|
|
m_eViewModelL.frame1time =
|
|
m_eViewModelL.frame2time =
|
|
m_eViewModel.frame2time =
|
|
m_eViewModel.frame1time = pl.weapontime;
|
|
Event_Callback(m_eViewModel.frame1time, fBaseTime2);
|
|
processmodelevents(m_eViewModel.modelindex, m_eViewModel.frame, fBaseTime,
|
|
m_eViewModel.frame1time, ClientGame_ModelEvent);
|
|
|
|
makevectors(view_angles);
|
|
|
|
if (autocvar_cg_viewmodelLag == 0)
|
|
m_eViewModel.angles = view_angles;
|
|
else {
|
|
float limit;
|
|
float speed;
|
|
makevectors(pSeat->m_vecLag);
|
|
pSeat->m_vecLag = v_forward;
|
|
makevectors(view_angles);
|
|
|
|
if (autocvar_cg_viewmodelLag == 2) {
|
|
float pitchfix = fabs(view_angles[0] / 180);
|
|
limit = dotproduct(pSeat->m_vecLag, v_forward) * (1.0 - pitchfix);
|
|
speed = (1.0 - limit) * clframetime;
|
|
speed *= 90;
|
|
} else {
|
|
speed = clframetime * 20;
|
|
}
|
|
|
|
pSeat->m_vecLag[0] = Math_Lerp(pSeat->m_vecLag[0], v_forward[0], speed);
|
|
pSeat->m_vecLag[1] = Math_Lerp(pSeat->m_vecLag[1], v_forward[1], speed);
|
|
pSeat->m_vecLag[2] = Math_Lerp(pSeat->m_vecLag[2], v_forward[2], speed);
|
|
pSeat->m_vecLag = vectoangles(pSeat->m_vecLag);
|
|
m_eViewModel.angles = pSeat->m_vecLag;
|
|
}
|
|
|
|
/* apply to the left side */
|
|
m_eViewModelL.angles = m_eViewModel.angles;
|
|
m_eViewModelL.colormap = m_eViewModel.colormap = pSeat->m_ePlayer.colormap;
|
|
|
|
/* now apply the scale hack */
|
|
m_eViewModelL.scale = m_eViewModel.scale = autocvar_cg_viewmodelScale;
|
|
|
|
if (Client_IsSpectator(cl) || XR_Available(pl) == false) {
|
|
m_eViewModelL.origin = g_view.GetCameraOrigin();
|
|
m_eViewModel.origin = g_view.GetCameraOrigin();
|
|
m_eViewModel.angles = g_view.GetCameraAngle();
|
|
m_eViewModelL.angles = g_view.GetCameraAngle();
|
|
|
|
/* we only calculate bob on the right model, to avoid double speed bobbing */
|
|
Viewmodel_CalcBob();
|
|
Viewmodel_ApplyBob(m_eViewModel);
|
|
Viewmodel_ApplyBob(m_eViewModelL);
|
|
} else {
|
|
m_eViewModelL.origin = pl.m_xrInputLeft.GetOrigin();
|
|
m_eViewModel.origin = pl.m_xrInputRight.GetOrigin();
|
|
m_eViewModel.angles = pl.m_xrInputRight.GetAngles();
|
|
m_eViewModelL.angles = pl.m_xrInputLeft.GetAngles();
|
|
}
|
|
|
|
/* this is currently broken */
|
|
#if 0
|
|
// Left-handed weapons
|
|
if (autocvar_cg_viewmodelFlip) {
|
|
v_right *= -1;
|
|
m_eViewModel.renderflags |= RF_USEAXIS;
|
|
//m_eViewModel.forceshader = SHADER_CULLED;
|
|
} else {
|
|
if (m_eViewModel.forceshader) {
|
|
m_eViewModel.forceshader = 0;
|
|
m_eViewModel.renderflags &= ~RF_USEAXIS;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
/* only draw the model when it's 'enabled'... */
|
|
if (m_eViewModel.alpha != 0.0f) {
|
|
if (m_eMuzzleflash.alpha > 0.0f) {
|
|
makevectors(getproperty(VF_ANGLES));
|
|
m_eMuzzleflash.origin = gettaginfo(m_eViewModel, m_eMuzzleflash.skin);
|
|
m_eMuzzleflash.angles = m_eViewModel.angles;
|
|
m_eMuzzleflash.angles[2] += (random() * 10) - 5;
|
|
|
|
if (autocvar_cg_muzzleDLight == true)
|
|
dynamiclight_add(pSeat->m_vecPredictedOrigin + (v_forward * 32), 256, [1,0.45,0]);
|
|
|
|
setorigin(m_eMuzzleflash, m_eMuzzleflash.origin);
|
|
addentity(m_eMuzzleflash);
|
|
}
|
|
if (m_eMuzzleflashL.alpha > 0.0f) {
|
|
makevectors(getproperty(VF_ANGLES));
|
|
m_eMuzzleflashL.origin = gettaginfo(m_eViewModelL, m_eMuzzleflashL.skin);
|
|
m_eMuzzleflashL.angles = m_eViewModelL.angles;
|
|
m_eMuzzleflashL.angles[2] += (random() * 10) - 5;
|
|
|
|
if (autocvar_cg_muzzleDLight == true)
|
|
dynamiclight_add(pSeat->m_vecPredictedOrigin + (v_forward * 32), 256, [1,0.45,0]);
|
|
|
|
setorigin(m_eMuzzleflashL, m_eMuzzleflashL.origin);
|
|
addentity(m_eMuzzleflashL);
|
|
}
|
|
setorigin(m_eViewModel, m_eViewModel.origin);
|
|
setorigin(m_eViewModelL, m_eViewModel.origin);
|
|
addentity(m_eViewModel);
|
|
addentity(m_eViewModelL);
|
|
}
|
|
}
|
|
|
|
void
|
|
View_PreDraw(void)
|
|
{
|
|
ClientGame_PreDraw();
|
|
}
|
|
|
|
void
|
|
View_PostDraw(void)
|
|
{
|
|
// Take away alpha once it has drawn fully at least once
|
|
if (pSeat->m_eMuzzleflash.alpha > 0.0f) {
|
|
pSeat->m_eMuzzleflash.alpha -= (clframetime * 16);
|
|
}
|
|
if (pSeat->m_eMuzzleflashL.alpha > 0.0f) {
|
|
pSeat->m_eMuzzleflashL.alpha -= (clframetime * 16);
|
|
}
|
|
|
|
ClientGame_PostDraw();
|
|
}
|
|
|
|
/*
|
|
====================
|
|
View_PlayAnimation
|
|
|
|
Resets the timeline and plays a new sequence
|
|
onto the view model
|
|
====================
|
|
*/
|
|
void
|
|
View_PlayAnimation(int iSequence)
|
|
{
|
|
pSeat->m_eViewModel.frame =
|
|
pSeat->m_eViewModelL.frame = (float)iSequence;
|
|
}
|
|
void
|
|
View_PlayAnimationLeft(int iSequence)
|
|
{
|
|
pSeat->m_eViewModelL.frame = (float)iSequence;
|
|
}
|
|
void
|
|
View_PlayAnimationRight(int iSequence)
|
|
{
|
|
pSeat->m_eViewModel.frame = (float)iSequence;
|
|
}
|
|
|
|
int
|
|
View_GetAnimation(void)
|
|
{
|
|
return pSeat->m_eViewModel.frame;
|
|
}
|
|
|
|
void
|
|
View_EnableViewmodel(void)
|
|
{
|
|
pSeat->m_eViewModel.alpha =
|
|
pSeat->m_eViewModelL.alpha = 1.0f;
|
|
}
|
|
|
|
void
|
|
View_DisableViewmodel(void)
|
|
{
|
|
pSeat->m_eViewModel.alpha =
|
|
pSeat->m_eViewModelL.alpha = 0.0f;
|
|
}
|