From 843dcc8284880b1629f7da2b35bc0227780339bb Mon Sep 17 00:00:00 2001 From: Marco Cawthorne Date: Tue, 1 Nov 2022 19:12:40 -0700 Subject: [PATCH] Kill src/client/player.qc. We now have overridable methods dedicated for updating player animations, attachments and more inside NSClientPlayer. Some of these APIs are still subject to change but they're being deployed in TW 1.35 right now. --- src/client/NSView.h | 4 ++ src/client/NSView.qc | 13 +++- src/client/include.src | 1 - src/client/player.qc | 101 ------------------------------- src/client/util.h | 3 + src/client/util.qc | 7 +++ src/server/NSTraceAttack.h | 7 +++ src/server/NSTraceAttack.qc | 27 +++++++++ src/shared/NSClientPlayer.h | 12 ++++ src/shared/NSClientPlayer.qc | 111 +++++++++++++++++++++++++++++++++++ src/shared/decalgroups.h | 1 + src/shared/decalgroups.qc | 8 ++- 12 files changed, 190 insertions(+), 105 deletions(-) delete mode 100644 src/client/player.qc diff --git a/src/client/NSView.h b/src/client/NSView.h index 4f1717fc..9d3c26d3 100644 --- a/src/client/NSView.h +++ b/src/client/NSView.h @@ -57,6 +57,8 @@ private: vector m_vecClientAngle; bool m_bSetClientAngle; + bool m_bDrawLocalPlayer; + public: void NSView(void); @@ -82,6 +84,8 @@ public: virtual void SetViewSize(vector); virtual void SetViewTarget(NSEntity); virtual void SetClientOwner(NSClient); + + virtual void SetDrawLocalPlayer(bool); virtual void SetCameraOrigin(vector); virtual void SetCameraAngle(vector); diff --git a/src/client/NSView.qc b/src/client/NSView.qc index f38b3464..3cea8b69 100644 --- a/src/client/NSView.qc +++ b/src/client/NSView.qc @@ -38,8 +38,11 @@ NSView::SetupView(void) setproperty(VF_AFOV, m_flFieldOfView); setsensitivityscaler(m_flSensitivity); - /* this will hide said entity */ - setproperty(VF_VIEWENTITY, player_localentnum); + /* if yes, draw everything. */ + if (m_bDrawLocalPlayer) + setproperty(VF_VIEWENTITY, 0); + else + setproperty(VF_VIEWENTITY, player_localentnum); /* handle camera override */ if (pSeat->m_flCameraTime > time || pSeat->m_flCameraTime == -1) { @@ -69,6 +72,12 @@ NSView::RenderView(void) renderscene(); } +void +NSView::SetDrawLocalPlayer(bool choice) +{ + m_bDrawLocalPlayer = choice; +} + void NSView::StairSmooth(void) { diff --git a/src/client/include.src b/src/client/include.src index d98052a5..a88089da 100644 --- a/src/client/include.src +++ b/src/client/include.src @@ -11,7 +11,6 @@ voice.qc fade.qc titles.qc text.qc -player.qc predict.qc entities.qc modelevent.qc diff --git a/src/client/player.qc b/src/client/player.qc deleted file mode 100644 index a1ced993..00000000 --- a/src/client/player.qc +++ /dev/null @@ -1,101 +0,0 @@ -/* - * 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. -*/ - -void -player::draw(void) -{ - /* mouth flapping */ - this.bonecontrol5 = getplayerkeyfloat(this.entnum - 1, "voiploudness"); - -#if 0 - /* DEBUG! */ - if (cvar("bonetest") == 1) { - this.bonecontrol1 = cvar("bonecontrol1"); - this.bonecontrol2 = cvar("bonecontrol2"); - this.bonecontrol3 = cvar("bonecontrol3"); - this.bonecontrol4 = cvar("bonecontrol4"); - this.bonecontrol5 = cvar("bonecontrol5"); - this.subblendfrac = cvar("subblendfrac"); - this.subblend2frac = cvar("subblend2frac"); - this.basesubblendfrac = cvar("basesubblendfrac"); - this.basesubblend2frac = cvar("basesubblend2frac"); - } -#endif -} - -float -player::predraw(void) -{ - int this_us = 0; - - super::predraw(); - - /* run animations regardless of rendering the player */ - draw(); - - /* make sure we're enabling shadow rendering on us */ - effects &= ~EF_NOSHADOW; - NSClient cl = (NSClient)pSeat->m_ePlayer; - - RenderFire(); - - /* it's either us or us spectating */ - if (Client_IsSpectator(cl)) { - NSClientSpectator spec = (NSClientSpectator)pSeat->m_ePlayer; - if (entnum == spec.spec_ent && spec.spec_mode == SPECMODE_FIRSTPERSON) { - this_us = 1; - } - } else { - if (entnum == player_localentnum) { - this_us = 1; - } - } - - if (this_us && flags & FL_INVEHICLE) { - NSVehicle veh = (NSVehicle)vehicle; - if (veh) - this_us = veh.HidePlayermodel(); - } - - if (autocvar_cl_thirdperson == TRUE || !this_us) { - renderflags &= ~RF_EXTERNALMODEL; - - Voice_Draw3D(this); - Player_PreDraw(this, TRUE); - if (p_model) { - p_model.renderflags &= ~RF_EXTERNALMODEL; - addentity(p_model); - } - //addentity(this); - } else { - renderflags |= RF_EXTERNALMODEL; - - Player_PreDraw(this, FALSE); - - if (p_model) { - p_model.renderflags |= RF_EXTERNALMODEL; - addentity(p_model); - } - addentity(this); - } - - return (PREDRAW_NEXT); -} - -void -player::postdraw(void) -{ -} diff --git a/src/client/util.h b/src/client/util.h index 4809b2db..c0e25a1b 100644 --- a/src/client/util.h +++ b/src/client/util.h @@ -33,3 +33,6 @@ float Client_IsPlayer(NSClient cl); float Client_InIntermission(void); string Util_GetKeyString(string); + + +bool Client_InVehicle(void); \ No newline at end of file diff --git a/src/client/util.qc b/src/client/util.qc index aad7a818..4fddefea 100644 --- a/src/client/util.qc +++ b/src/client/util.qc @@ -47,6 +47,13 @@ Client_IsPlayer(NSClient cl) return cl.IsPlayer(); } +bool +Client_InVehicle(void) +{ + player pl = (player)pSeat->m_ePlayer; + return (pl.vehicle != world) ? true : false; +} + /* ================= Util_GetKeyString diff --git a/src/server/NSTraceAttack.h b/src/server/NSTraceAttack.h index 6084cf33..6e5c1cea 100644 --- a/src/server/NSTraceAttack.h +++ b/src/server/NSTraceAttack.h @@ -16,6 +16,8 @@ void TraceAttack_FireBullets(int iShots, vector vecPos, int iDamage, vector vecSpread, int iWeapon); +void TraceAttack_FireBulletsWithDecal(int iShots, vector vecPos, int iDamage, vector vecSpread, int iWeapon, string strDecalGroup); + #ifdef BULLETPENETRATION void TraceAttack_SetPenetrationPower(int power); #endif @@ -37,6 +39,8 @@ private: entity m_eOwner; float m_flRange; vector m_vecOrigin; + //int m_iDecalGroup; + string m_strDecalGroup; /* bullet penetration */ #ifdef BULLETPENETRATION @@ -68,6 +72,9 @@ public: virtual void SetRange(float); /** Sets the owner responsible for the trace. */ virtual void SetOwner(entity); + + /** Sets the decal group used by the trace attack */ + virtual void SetDecalGroup(string); #ifdef BULLETPENETRATION /** Sets the maximum thickness that the trace is not allowed to penetrate. diff --git a/src/server/NSTraceAttack.qc b/src/server/NSTraceAttack.qc index de24e134..24eff9c2 100644 --- a/src/server/NSTraceAttack.qc +++ b/src/server/NSTraceAttack.qc @@ -122,6 +122,8 @@ NSTraceAttack::_FireSingle(vector vecPos, vector vecAngles, float flDamage, floa /* impact per bullet */ if (trace_ent.iBleeds == 0) { + if (m_strDecalGroup) + DecalGroups_Place(m_strDecalGroup, trace_endpos); SurfData_Impact(trace_ent, trace_surfaceflagsi, trace_endpos, trace_plane_normal); } @@ -250,6 +252,12 @@ NSTraceAttack::SetOwner(entity eOwner) m_eOwner = eOwner; } +void +NSTraceAttack::SetDecalGroup(string strGroupName) +{ + //int m_iDecalGroup = DecalGroups_NumForName(strGroupName); + m_strDecalGroup = strGroupName; +} #ifdef BULLETPENETRATION void @@ -271,6 +279,8 @@ NSTraceAttack::NSTraceAttack(void) m_iMultiValue = 0; m_iMultiBody = 0; m_flRange = 8196; + //m_iDecalGroup = -1; + m_strDecalGroup = __NULL__; #ifdef BULLETPENETRATION m_flMaxThickness = 5.0f; @@ -296,6 +306,23 @@ TraceAttack_FireBullets(int iShots, vector vecPos, int iDamage, vector vecSpread g_traceAttack.Fire(); } +void +TraceAttack_FireBulletsWithDecal(int iShots, vector vecPos, int iDamage, vector vecSpread, int iWeapon, string strDecalGroup) +{ + if (!g_traceAttack) { + g_traceAttack = spawn(NSTraceAttack); + } + + g_traceAttack.SetShots(iShots); + g_traceAttack.SetOrigin(vecPos); + g_traceAttack.SetDamage(iDamage); + g_traceAttack.SetSpread(vecSpread); + g_traceAttack.SetWeapon(iWeapon); + g_traceAttack.SetOwner(self); + g_traceAttack.SetDecalGroup(strDecalGroup); + g_traceAttack.Fire(); +} + #ifdef BULLETPENETRATION void TraceAttack_SetRangeModifier(float units) diff --git a/src/shared/NSClientPlayer.h b/src/shared/NSClientPlayer.h index 17635965..d850cafe 100644 --- a/src/shared/NSClientPlayer.h +++ b/src/shared/NSClientPlayer.h @@ -90,6 +90,9 @@ NSClientPlayer:NSClientSpectator virtual bool(void) IsDead; virtual bool(void) IsPlayer; + /** Empty & shared between Client and Server. This is run on every player, every frame, to update their animation cycle. */ + virtual void UpdatePlayerAnimation(void); + #ifdef CLIENT int sequence; @@ -106,6 +109,15 @@ NSClientPlayer:NSClientSpectator virtual void(void) PredictPostFrame; virtual void(void) ClientInputFrame; virtual void(void) UpdateAliveCam; + + virtual float predraw(void); + virtual void postdraw(void); + + /** Empty. Updates the bone controller responsible for mouth movement. */ + virtual void UpdatePlayerJaw(float); + + /** Empty. This is run on every player, every frame to update attachments. */ + virtual void UpdatePlayerAttachments(bool); #else int voted; int step; diff --git a/src/shared/NSClientPlayer.qc b/src/shared/NSClientPlayer.qc index eb124c93..4af1d838 100644 --- a/src/shared/NSClientPlayer.qc +++ b/src/shared/NSClientPlayer.qc @@ -138,7 +138,118 @@ NSClientPlayer::ClientInput(void) Game_Input((player)this); } +/* this is where it gets mod specific really fast, + as some models may not even support skeletal animation */ +void +NSClientPlayer::UpdatePlayerAnimation(void) +{ + +} + #ifdef CLIENT +void +NSClientPlayer::UpdatePlayerJaw(float voip_volume) +{ +} + +void +NSClientPlayer::UpdatePlayerAttachments(bool visible) +{ + +} + +float +NSClientPlayer::predraw(void) +{ + bool localplayer = false; + + NSClient cl = (NSClient)pSeat->m_ePlayer; + + /* figure out if this is the local player. it's either us or us spectating */ + if (Client_IsSpectator(cl)) { + NSClientSpectator spec = (NSClientSpectator)pSeat->m_ePlayer; + if (entnum == spec.spec_ent && spec.spec_mode == SPECMODE_FIRSTPERSON) { + localplayer = true; + } + } else { + if (entnum == player_localentnum) { + localplayer = true; + } + } + + /* make sure we're enabling shadow rendering on us! */ + effects &= ~EF_NOSHADOW; + + /* always advance the player animation in some way */ + UpdatePlayerAnimation(); + + /* mouth flapping */ + UpdatePlayerJaw(getplayerkeyfloat(this.entnum - 1, "voiploudness")); + + /* apply any necessary filters from NSRenderableEntity */ + RenderFXPass(); + + /* apply any fire effects, if we're burning (we're of type NSSurfacePropEntity that can burn) */ + RenderFire(); + + /* if we're inside of a vehicle, it may want to hide or show us regardless */ + if (localplayer && flags & FL_INVEHICLE) { + NSVehicle veh = (NSVehicle)vehicle; + + if (veh) + localplayer = veh.HidePlayermodel(); + } + + /* if we're forcing third-person.. or this is not us - render this player */ + if (autocvar_cl_thirdperson == TRUE || !localplayer) { + /* mark as not-mirror-only */ + renderflags &= ~RF_EXTERNALMODEL; + + /* same for our attachment */ + if (p_model) + p_model.renderflags &= ~RF_EXTERNALMODEL; + + /* let mods override attachments and whatnot */ + UpdatePlayerAttachments(true); + + /* draw a 3D voice blob over its head */ + Voice_Draw3D(this); + + /* force drawing us if it's our local player and we're meant to show */ + if (entnum == player_localentnum) + g_view.SetDrawLocalPlayer(true); + + /* sucks we can't draw a shadow on this thing, maybe in the future when FTEQW allows it */ + if (p_model) + addentity(p_model); + } else { /* we're doing first person stuff */ + /* flags that the model appear in mirrors only */ + renderflags |= RF_EXTERNALMODEL; + + /* ditto */ + if (p_model) + p_model.renderflags |= RF_EXTERNALMODEL; + + /* give mods a chance to de-render attachments */ + UpdatePlayerAttachments(false); + + /* this is here just to make sure our view hides us if it's the local player */ + if (entnum == player_localentnum) + g_view.SetDrawLocalPlayer(false); + } + + /* this needs to be called absolutely last */ + /* we're calling this so that the shadow can still be drawn */ + addentity(this); + + return (PREDRAW_NEXT); +} + +void +NSClientPlayer::postdraw(void) +{ +} + void NSClientPlayer::VehicleRelink(void) { diff --git a/src/shared/decalgroups.h b/src/shared/decalgroups.h index f9145f23..3f505b66 100644 --- a/src/shared/decalgroups.h +++ b/src/shared/decalgroups.h @@ -29,6 +29,7 @@ /* public API */ void DecalGroups_Init(void); void DecalGroups_Place(string group, vector org); +int DecalGroups_NumForName(string group); #ifdef CLIENT void DecalGroups_Receive(void); diff --git a/src/shared/decalgroups.qc b/src/shared/decalgroups.qc index 512f6389..b57cc8a7 100644 --- a/src/shared/decalgroups.qc +++ b/src/shared/decalgroups.qc @@ -159,11 +159,17 @@ DecalGroups_PlaceGroupID(int index, vector org) } #endif +int +DecalGroups_NumForName(string group) +{ + return (int)hash_get(g_hashdecalgroup, group, -1); +} + void DecalGroups_Place(string group, vector org) { int index; - index = (int)hash_get(g_hashdecalgroup, group, -1); + index = (int)hash_get(g_hashdecalgroup, strtolower(group), -1); #ifdef SERVER /* on the server we only need to tell the clients in the PVS