From 40aee258ce8a8bfa10375b9aa7295f171dc5efbf Mon Sep 17 00:00:00 2001 From: Marco Cawthorne Date: Mon, 8 Jan 2024 14:58:45 -0800 Subject: [PATCH] NSClientSpectator: new mode: overview which is work in progress. Various misc fixes to code routines that negatively affect splitscreen. We also set frametime/clframetime to 0.0 after the first player view has been drawn as to not run predraw math more than once per frame. This should not cause any issues but if you are experiencing issues let us know. --- src/client/NSView.h | 1 + src/client/NSView.qc | 74 +++++++++++++------ src/client/cmd.qc | 4 ++ src/client/defs.h | 6 ++ src/client/efx.qc | 6 +- src/client/entities.qc | 2 +- src/client/entry.qc | 11 +-- src/client/include.src | 1 + src/client/modelevent.qc | 2 +- src/client/predict.qc | 8 ++- src/client/text.qc | 2 +- src/client/view.qc | 25 +++++-- src/gs-entbase/client/env_soundscape.qc | 2 +- src/server/NSGameRules.h | 2 +- src/server/NSGameRules.qc | 12 +++- src/server/entry.qc | 14 ++-- src/shared/NSClientPlayer.h | 4 +- src/shared/NSClientPlayer.qc | 11 +++ src/shared/NSClientSpectator.h | 17 ++++- src/shared/NSClientSpectator.qc | 37 ++++++---- src/shared/NSMonster.qc | 2 +- src/shared/NSProjectile.qc | 9 ++- src/shared/damage.h | 94 ++++++++++++------------- src/shared/decalgroups.h | 16 ++++- 24 files changed, 248 insertions(+), 114 deletions(-) diff --git a/src/client/NSView.h b/src/client/NSView.h index b24b0c10..7ea8f57a 100644 --- a/src/client/NSView.h +++ b/src/client/NSView.h @@ -132,6 +132,7 @@ private: bool m_bSetClientAngle; bool m_bDrawLocalPlayer; + bool m_bDrawEntities; }; /** one NSView for each seat */ diff --git a/src/client/NSView.qc b/src/client/NSView.qc index 00748fe4..c6e8dbf1 100644 --- a/src/client/NSView.qc +++ b/src/client/NSView.qc @@ -26,6 +26,7 @@ NSView::NSView(void) m_flFieldOfView = 90.0f; m_client = __NULL__; m_flSensitivity = 1.0f; + m_bDrawEntities = true; } void @@ -49,7 +50,7 @@ NSView::SetupView(void) if (m_bDrawLocalPlayer) setproperty(VF_VIEWENTITY, 0); else - setproperty(VF_VIEWENTITY, player_localentnum); + setproperty(VF_VIEWENTITY, m_viewTarget.entnum); /* handle camera override */ if (pSeat->m_flCameraTime > time || pSeat->m_flCameraTime == -1) { @@ -260,28 +261,30 @@ void View_DrawViewModel(); void NSView::UpdateView(void) { - player pl = (player)m_viewTarget; + NSClientPlayer pl = (NSClientPlayer)m_viewTarget; NSClient cl = (NSClient)m_viewTarget; NSClientSpectator spec = (NSClientSpectator)m_viewTarget; entity c; - if (!cl) - return; - clearscene(); - /* run preframe code on our viewtarget */ - cl.PreFrame(); + /* is a client attached to this view? */ + if (cl) { + /* run preframe code on our viewtarget */ + cl.PreFrame(); - /* update our player seat info with predicted info */ - pSeat->m_vecPredictedOrigin = cl.origin; - pSeat->m_flPredictedFlags = cl.flags; - pSeat->m_vecPredictedVelocity = cl.velocity; + /* update our player seat info with predicted info */ + pSeat->m_vecPredictedOrigin = cl.origin; + pSeat->m_flPredictedFlags = cl.flags; + pSeat->m_vecPredictedVelocity = cl.velocity; + } /* put entities into the scene (and call their predraws */ - addentities(MASK_ENGINE); + if (m_bDrawEntities) + addentities(MASK_ENGINE); /* after predraws we can act upon their new positions */ + if (cl) { switch (GetViewMode()) { case VIEWMODE_FPS: if (Client_InIntermission()) { @@ -306,6 +309,8 @@ NSView::UpdateView(void) spec = (NSClientSpectator)m_viewTarget; switch (spec.spec_mode) { + case SPECMODE_LOCKEDCHASE: + view_angles = [0, spec.v_angle[1], 0]; case SPECMODE_THIRDPERSON: makevectors(view_angles); vector vecStart = spec.GetEyePos(); @@ -322,7 +327,7 @@ NSView::UpdateView(void) c = findfloat(world, ::entnum, spec.spec_ent); if (c.classname == "player") { - player bp = (player)c; + NSClientPlayer bp = (NSClientPlayer)c; removeentity(c); SetCameraOrigin(bp.GetEyePos()); SetCameraAngle(bp.v_angle); @@ -334,7 +339,7 @@ NSView::UpdateView(void) /* we found them */ if (c && c != spec) { - player ps = (player)c; + NSClientPlayer ps = (NSClientPlayer)c; if (ps.health <= 0) pl.UpdateDeathcam(); else @@ -343,6 +348,27 @@ NSView::UpdateView(void) } } break; + case SPECMODE_CHASEOVERVIEW: + c = findfloat(world, ::entnum, spec.spec_ent); + if (c.classname == "player") { + SetCameraOrigin(c.origin); + } + + drawfill(m_vecPosition, m_vecSize, [0,0,0], 1.0f, DRAWFLAG_NORMAL); + g_overview.SetViewPosition(m_vecPosition); + g_overview.SetViewSize(m_vecSize); + g_overview.SetRadarPitch(view_angles[0]); + g_overview.UpdateView(); + return; + case SPECMODE_FREEOVERVIEW: + SetCameraOrigin(pSeat->m_vecPredictedOrigin); + drawfill(m_vecPosition, m_vecSize, [0,0,0], 1.0f, DRAWFLAG_NORMAL); + g_overview.SetViewPosition(m_vecPosition); + g_overview.SetViewSize(m_vecSize); + g_overview.SetRadarPitch(view_angles[0]); + g_overview.UpdateView(); + return; + break; default: SetCameraOrigin(cl.GetEyePos()); SetCameraAngle(view_angles); @@ -354,13 +380,19 @@ NSView::UpdateView(void) View_PreDraw(); + } + /* prepare our scene properties */ SetupView(); /* properties are locked in place, run logic that depends on final values */ - addentities(MASK_GLOWS); + if (m_bDrawEntities) + addentities(MASK_GLOWS); + SkyCamera_Setup(origin); - XR_UpdateView(m_viewTarget); + + if (cl) + XR_UpdateView(m_viewTarget); /* render our frame */ RenderView(); @@ -375,12 +407,14 @@ NSView::UpdateView(void) } /* the blinding stuff */ - Fade_Update(m_vecPosition[0], m_vecPosition[1], m_vecSize[0], m_vecSize[1]); + if (cl) { + Fade_Update(m_vecPosition[0], m_vecPosition[1], m_vecSize[0], m_vecSize[1]); - View_PostDraw(); + View_PostDraw(); - /* move this into NSClient methods */ - cl.PostFrame(); + /* move this into NSClient methods */ + cl.PostFrame(); + } if (autocvar(r_showView, 0) == false) return; diff --git a/src/client/cmd.qc b/src/client/cmd.qc index 985bf310..81d6f367 100644 --- a/src/client/cmd.qc +++ b/src/client/cmd.qc @@ -339,10 +339,14 @@ Cmd_Parse(string sCMD) pSeat->m_iInputDuck = 1 - pSeat->m_iInputDuck; else pSeat->m_iInputDuck = TRUE; + + pSeat->m_bSpecInput = true; break; case "-duck": if (autocvar_pm_crouchToggle == false) pSeat->m_iInputDuck = FALSE; + + pSeat->m_bSpecInput = false; break; case "invnext": HUD_DrawWeaponSelect_Back(); diff --git a/src/client/defs.h b/src/client/defs.h index 9c17665f..0d29fa7e 100644 --- a/src/client/defs.h +++ b/src/client/defs.h @@ -22,6 +22,7 @@ #include "cmd.h" #include "util.h" #include "NSView.h" +#include "NSRadar.h" #include "crosshair.h" var bool g_net_debug = false; @@ -372,6 +373,11 @@ struct bool m_bMoveForward; bool m_bInterfaceFocused; + bool m_bSpecInput; } g_seats[4], *pSeat; var vector g_vecMousePos; +var vector g_hudmins; +var vector g_hudres; + +var NSRadar g_overview; \ No newline at end of file diff --git a/src/client/efx.qc b/src/client/efx.qc index 7c2bf6c5..705b4a4e 100644 --- a/src/client/efx.qc +++ b/src/client/efx.qc @@ -264,7 +264,7 @@ EFX_Interpolate(int id) } void -EFX_UpdateListener(void) +EFX_UpdateListener(NSView playerView) { static int old_dsp; @@ -301,8 +301,8 @@ EFX_UpdateListener(void) EFX_SetEnvironment(scape.m_iRoomType); } - makevectors(getproperty(VF_CL_VIEWANGLES)); - SetListener(getproperty(VF_ORIGIN), v_forward, v_right, v_up, 12); + makevectors(playerView.GetCameraAngle()); + SetListener(playerView.GetCameraOrigin(), v_forward, v_right, v_up, 12); if (old_dsp == g_iEFX) { return; diff --git a/src/client/entities.qc b/src/client/entities.qc index dba3f66d..0f0ed51a 100644 --- a/src/client/entities.qc +++ b/src/client/entities.qc @@ -71,7 +71,7 @@ Entity_EntityUpdate(float type, float new) NSENTITY_READENTITY(prop_vehicle_driveable, new) break; case ENT_PLAYER: - player pl = (player)self; + NSClientPlayer pl = (NSClientPlayer)self; /* splitscreen */ CSQC_UpdateSeat(); diff --git a/src/client/entry.qc b/src/client/entry.qc index 3bdeb482..170bfe3c 100644 --- a/src/client/entry.qc +++ b/src/client/entry.qc @@ -81,6 +81,8 @@ CSQC_Init(float apilevel, string enginename, float engineversion) WorldSpawn_Init(); + g_overview = NSRadar::InitForCurrentMap(); + Sound_Precache("Player.DenyWeaponSelection"); Sound_Precache("Player.WeaponSelected"); Sound_Precache("Player.WeaponSelectionMoveSlot"); @@ -308,13 +310,14 @@ CSQC_UpdateView(float w, float h, float focus) /* 2D calls happen here, after rendering is done */ CSQC_Update2D(w, h, focus); + + EFX_UpdateListener(g_view); + DSP_UpdateSoundscape(g_view); + clframetime = 0.0f; + frametime = 0.0f; } } - /* this sucks and doesn't take seats into account */ - EFX_UpdateListener(); - DSP_UpdateSoundscape(); - /* draw AL debug info (no regard for seating */ if (autocvar_s_al_debug) EFX_DebugInfo(); diff --git a/src/client/include.src b/src/client/include.src index e02cdefa..e83aa334 100644 --- a/src/client/include.src +++ b/src/client/include.src @@ -1,6 +1,7 @@ #includelist NSInteractiveSurface.qc NSView.qc +NSRadar.qc fog.qc font.qc sky.qc diff --git a/src/client/modelevent.qc b/src/client/modelevent.qc index f6c94a7f..e82a7a54 100644 --- a/src/client/modelevent.qc +++ b/src/client/modelevent.qc @@ -39,7 +39,7 @@ Event_Callback(float mtime, __inout float btime) return; /* weapon changed */ - player pl = (player)(pSeat->m_ePlayer); + NSClientPlayer pl = (NSClientPlayer)(pSeat->m_ePlayer); if (pSeat->m_iEventWeapon != pl.activeweapon) return; diff --git a/src/client/predict.qc b/src/client/predict.qc index cef9fe31..43567eb8 100644 --- a/src/client/predict.qc +++ b/src/client/predict.qc @@ -14,6 +14,8 @@ * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +var string autocvar_g_playerClass = "player"; + /* ================= Predict_EntityUpdate @@ -24,15 +26,15 @@ Propagate our pmove state to whatever the current frame before its stomped on ================= */ void -Predict_EntityUpdate(player pl, float new) +Predict_EntityUpdate(NSClientPlayer pl, float new) { /* people expect a static camera when paused */ if (Util_IsPaused()) return; /* this is a new client entity, let's set it up right */ - if (new || self.classname != "player") { - spawnfunc_player(); + if (new || pl.classname != "player") { + Util_ChangeClass(pl, "player"); pl.classname = "player"; /* is this **us** ? */ diff --git a/src/client/text.qc b/src/client/text.qc index 65ef0cdd..655adcc4 100644 --- a/src/client/text.qc +++ b/src/client/text.qc @@ -325,4 +325,4 @@ GameMessage_Parse(void) if (strSound) sound(self, CHAN_ITEM, strSound, flVolume, iAttenuation); -} +} \ No newline at end of file diff --git a/src/client/view.qc b/src/client/view.qc index 76ea460c..367546be 100644 --- a/src/client/view.qc +++ b/src/client/view.qc @@ -111,6 +111,13 @@ View_DrawViewmodel_Single(int weapon, float weapontime) } +static void +View_HandleAnimEvent(float flTimeStamp, int iCode, string strData) +{ + NSRenderableEntity viewModel = (NSRenderableEntity)self; + viewModel.HandleAnimEvent(flTimeStamp, iCode, strData); +} + /* ==================== View_DrawViewModel @@ -125,18 +132,18 @@ View_DrawViewModel(void) NSRenderableEntity m_eViewModel = (NSRenderableEntity)pSeat->m_eViewModel; NSRenderableEntity m_eViewModelL = (NSRenderableEntity)pSeat->m_eViewModelL; - player pl = __NULL__; + NSClientPlayer 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); + pl = (NSClientPlayer)findfloat(world, ::entnum, spec.spec_ent); if (spec.spec_mode != SPECMODE_FIRSTPERSON) return; } else { - pl = (player)pSeat->m_ePlayer; + pl = (NSClientPlayer)pSeat->m_ePlayer; } if (!pl) @@ -215,7 +222,7 @@ View_DrawViewModel(void) entity oldSelf = self; self = m_eViewModel; processmodelevents(m_eViewModel.modelindex, m_eViewModel.frame, fBaseTime, - m_eViewModel.frame1time, NSRenderableEntity::HandleAnimEvent); + m_eViewModel.frame1time, View_HandleAnimEvent); self = oldSelf; makevectors(view_angles); @@ -255,11 +262,17 @@ View_DrawViewModel(void) 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(); + + if (Client_IsSpectator(cl)) { + m_eViewModel.angles = g_view.GetCameraAngle(); + m_eViewModelL.angles = g_view.GetCameraAngle(); + /* HACK: fool Viewmodel_CalcBob(); */ + pSeat->m_vecPredictedVelocity = pl.velocity; + } /* we only calculate bob on the right model, to avoid double speed bobbing */ Viewmodel_CalcBob(); + makevectors(g_view.GetCameraAngle()); Viewmodel_ApplyBob(m_eViewModel); Viewmodel_ApplyBob(m_eViewModelL); } else { diff --git a/src/gs-entbase/client/env_soundscape.qc b/src/gs-entbase/client/env_soundscape.qc index 596bb1bd..1ba88ac6 100644 --- a/src/gs-entbase/client/env_soundscape.qc +++ b/src/gs-entbase/client/env_soundscape.qc @@ -98,7 +98,7 @@ DSP_ResetSoundscape(void) } void -DSP_UpdateSoundscape(void) +DSP_UpdateSoundscape(NSView playerView) { vector vecPlayer; diff --git a/src/server/NSGameRules.h b/src/server/NSGameRules.h index 80f18034..13f7d261 100644 --- a/src/server/NSGameRules.h +++ b/src/server/NSGameRules.h @@ -91,7 +91,7 @@ public: /** Checks if an entity can be attacked from a given position. */ virtual bool DamageCheckTrace(entity,vector); /** Overridable: shim to handle application of indirect radius damage. */ - virtual void DamageRadius(vector,entity,float,float,int,int); + virtual void DamageRadius(vector,entity,float,float,bool,int); /* end of a game */ /** Called when intermission starts. */ diff --git a/src/server/NSGameRules.qc b/src/server/NSGameRules.qc index ef1217df..9f45fa16 100644 --- a/src/server/NSGameRules.qc +++ b/src/server/NSGameRules.qc @@ -221,6 +221,14 @@ NSGameRules::IntermissionCycle(void) WriteCoord(MSG_MULTICAST, cam.origin[0]); WriteCoord(MSG_MULTICAST, cam.origin[1]); WriteCoord(MSG_MULTICAST, cam.origin[2]); + } else { + WriteByte(MSG_MULTICAST, 1); + WriteFloat(MSG_MULTICAST, cam.angles[0]); + WriteFloat(MSG_MULTICAST, cam.angles[1]); + WriteFloat(MSG_MULTICAST, cam.angles[2]); + WriteCoord(MSG_MULTICAST, cam.origin[0]); + WriteCoord(MSG_MULTICAST, cam.origin[1]); + WriteCoord(MSG_MULTICAST, cam.origin[2]); } for (entity pl = world; (pl = find(pl, ::classname, "player"));) { @@ -455,7 +463,7 @@ NSGameRules::DamageCheckTrace(entity t, vector vecHitPos) } void -NSGameRules::DamageRadius(vector org, entity attacker, float dmg, float r, int check, int w) +NSGameRules::DamageRadius(vector org, entity attacker, float dmg, float r, bool checkCollision, int w) { float new_dmg; float dist; @@ -473,7 +481,7 @@ NSGameRules::DamageRadius(vector org, entity attacker, float dmg, float r, int c continue; /* can we physically hit this thing? */ - if (check == TRUE) + if (checkCollision == true) if (DamageCheckTrace(e, org) == FALSE) continue; diff --git a/src/server/entry.qc b/src/server/entry.qc index 4105c9ed..092081ce 100644 --- a/src/server/entry.qc +++ b/src/server/entry.qc @@ -269,8 +269,13 @@ SV_RunClientCommand(void) /* TODO */ } - cl.SharedInputFrame(); - cl.ServerInputFrame(); + /* FIXME: before a splitscreen player disconnects, it often sends + one last SV_RunClientCommand which causes an error if we don't + check these two methods here */ + if (cl.SharedInputFrame) + cl.SharedInputFrame(); + if (cl.ServerInputFrame) + cl.ServerInputFrame(); if (self.gotData == false) { BreakModel_SendClientData(self); @@ -313,8 +318,9 @@ SV_ParseClientCommand(string cmd) case "spectate": if (self.classname != "player") break; - ClientKill(); - spawnfunc_NSClientSpectator(); + + player pl = (player)self; + pl.MakeSpectator(); break; case "play": if (self.classname != "spectator") diff --git a/src/shared/NSClientPlayer.h b/src/shared/NSClientPlayer.h index cd439548..8c75f5b7 100644 --- a/src/shared/NSClientPlayer.h +++ b/src/shared/NSClientPlayer.h @@ -88,8 +88,10 @@ public: /** When called, will turn the client into a proper player. */ virtual void MakePlayer(void); - /** When called, will turn the client into a spectator. */ + /** When called, will turn the client into a spectator until the next round. */ virtual void MakeTempSpectator(void); + /** When called, will turn the client into a general spectator. */ + virtual void MakeSpectator(void); /** Called when we press the button bound to +use. */ virtual void InputUse_Down(void); diff --git a/src/shared/NSClientPlayer.qc b/src/shared/NSClientPlayer.qc index 2eda53ac..d353a1c2 100644 --- a/src/shared/NSClientPlayer.qc +++ b/src/shared/NSClientPlayer.qc @@ -898,6 +898,15 @@ NSClientPlayer::MakePlayer(void) forceinfokey(this, "*dead", "0"); } +void +NSClientPlayer::MakeSpectator(void) +{ + ClientKill(); + MakeTempSpectator(); + team = 0; + forceinfokey(this, "*team", ftos(team)); +} + /* ================= NSClientPlayer::EvaluateEntity @@ -910,6 +919,8 @@ at the top of player::EvaluateEntity void NSClientPlayer::EvaluateEntity(void) { + pvsflags = (flags & FL_FAKESPEC) ? 0 : PVSF_IGNOREPVS; + EVALUATE_FIELD(modelindex, PLAYER_MODELINDEX) EVALUATE_FIELD(colormap, PLAYER_MODELINDEX) diff --git a/src/shared/NSClientSpectator.h b/src/shared/NSClientSpectator.h index 178ea3a0..725c7825 100644 --- a/src/shared/NSClientSpectator.h +++ b/src/shared/NSClientSpectator.h @@ -26,12 +26,25 @@ typedef enumflags typedef enum { - SPECMODE_FREE, + SPECMODE_LOCKEDCHASE, SPECMODE_THIRDPERSON, + SPECMODE_FREE, SPECMODE_FIRSTPERSON, - SPECMODE_OVERVIEW + SPECMODE_FREEOVERVIEW, + SPECMODE_CHASEOVERVIEW } NSClientSpectatorMode_t; +#ifdef CLIENT +string g_specmodes[] = { + "Locked Chase Cam", + "Free Chase Cam", + "Free Look", + "First Person", + "Free Overview", + "Chase Overview" +}; +#endif + enumflags { SPECFLAG_BUTTON_RELEASED, diff --git a/src/shared/NSClientSpectator.qc b/src/shared/NSClientSpectator.qc index ef2d9a2f..c50e0a62 100644 --- a/src/shared/NSClientSpectator.qc +++ b/src/shared/NSClientSpectator.qc @@ -18,6 +18,7 @@ void NSClientSpectator::NSClientSpectator(void) { flags |= FL_CLIENT; + spec_mode = SPECMODE_FREE; } #ifdef SERVER @@ -90,7 +91,11 @@ NSClientSpectator::SharedInputFrame(void) { SetSize(g_vec_null, g_vec_null); - if (spec_mode == SPECMODE_FREE) { + if (spec_mode == SPECMODE_FREE || spec_mode == SPECMODE_FREEOVERVIEW) { + if (spec_mode == SPECMODE_FREEOVERVIEW) { + input_angles[0] = 0.0f; + } + SetSolid(SOLID_NOT); SetMovetype(MOVETYPE_NOCLIP); } else { @@ -134,6 +139,8 @@ NSClientSpectator::SendEntity(entity ePVSent, float flChanged) void NSClientSpectator::ServerInputFrame(void) { + movetype = MOVETYPE_NOCLIP; + if (spec_mode == SPECMODE_FREE) { runstandardplayerphysics(this); } else { @@ -163,7 +170,7 @@ NSClientSpectator::ClientInputFrame(void) void NSClientSpectator::ReceiveEntity(float new, float flChanged) { - if (spec_mode == SPECMODE_FREE) + if (spec_mode == SPECMODE_FREE || spec_mode == SPECMODE_FREEOVERVIEW) if (new == FALSE) { /* Go through all the physics code between the last received frame * and the newest frame and keep the changes this time around instead @@ -274,8 +281,8 @@ NSClientSpectator::InputNext(void) WarpToTarget(); - if (spec_mode == SPECMODE_FREE) - spec_mode = SPECMODE_THIRDPERSON; + if (spec_mode == SPECMODE_CHASEOVERVIEW) + spec_mode = SPECMODE_CHASEOVERVIEW; } void @@ -340,8 +347,8 @@ NSClientSpectator::InputPrevious(void) WarpToTarget(); - if (spec_mode == SPECMODE_FREE) - spec_mode = SPECMODE_THIRDPERSON; + if (spec_mode == SPECMODE_LOCKEDCHASE) + spec_mode = SPECMODE_CHASEOVERVIEW; } void @@ -359,13 +366,16 @@ NSClientSpectator::InputMode(void) f = (NSClient)edict_num(spec_ent); #endif - if (f == this || f.classname != "player") - spec_mode = SPECMODE_FREE; - else { + if (f == this || f.classname != "player") { + if (spec_mode != SPECMODE_FREE) + spec_mode = SPECMODE_FREE; + else + spec_mode = SPECMODE_FREEOVERVIEW; + } else { spec_mode++; - if (spec_mode > SPECMODE_FIRSTPERSON) - spec_mode = SPECMODE_FREE; + if (spec_mode > SPECMODE_CHASEOVERVIEW) + spec_mode = SPECMODE_LOCKEDCHASE; } } @@ -412,7 +422,10 @@ NSClientSpectator::PreFrame(void) void NSClientSpectator::SpectatorTrackPlayer(void) { - if (spec_mode == SPECMODE_THIRDPERSON || spec_mode == SPECMODE_FIRSTPERSON ) { + if (spec_mode == SPECMODE_THIRDPERSON + || spec_mode == SPECMODE_FIRSTPERSON + || spec_mode == SPECMODE_CHASEOVERVIEW + || spec_mode == SPECMODE_LOCKEDCHASE ) { NSClient b; #ifdef CLIENT diff --git a/src/shared/NSMonster.qc b/src/shared/NSMonster.qc index 0f592919..3d1cf7f6 100644 --- a/src/shared/NSMonster.qc +++ b/src/shared/NSMonster.qc @@ -2022,7 +2022,7 @@ NSMonster::SpawnKey(string strKey, string strValue) _m_flFrame = ReadFloat(strValue); break; default: - NSSurfacePropEntity::SpawnKey(strKey, strValue); + super::SpawnKey(strKey, strValue); break; } } diff --git a/src/shared/NSProjectile.qc b/src/shared/NSProjectile.qc index fab24730..745d3b4c 100644 --- a/src/shared/NSProjectile.qc +++ b/src/shared/NSProjectile.qc @@ -712,10 +712,13 @@ NSProjectile::_ThrustThink(void) /* homing mode */ if (m_bThrustHoming) { + vector ownerPos; + vector endPos; NSSurfacePropEntity projectileOwner = (NSSurfacePropEntity)GetOwner(); - vector ownerPos = projectileOwner.GetEyePos(); - makevectors(projectileOwner.v_angle); - traceline(ownerPos, ownerPos + v_forward * 8096, FALSE, projectileOwner); + ownerPos = projectileOwner.GetEyePos(); + makevectors(projectileOwner.GetViewAngle()); + endPos = ownerPos + (v_forward * 4096.0f); + traceline(ownerPos, endPos, MOVE_NORMAL, projectileOwner); SetAngles(vectoangles(trace_endpos - GetOrigin())); } diff --git a/src/shared/damage.h b/src/shared/damage.h index 2ba5d91b..5118fa72 100644 --- a/src/shared/damage.h +++ b/src/shared/damage.h @@ -1,48 +1,48 @@ -/* - * 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. -*/ - +/* + * 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. +*/ + /** All available damage types. */ -typedef enumflags -{ - DMG_GENERIC, /**< Non specific. */ - DMG_CRUSH, /**< Being crushed by something heavy. */ - DMG_BULLET, /**< Shot by a gun. */ - DMG_SLASH, /**< Cutting, from swords or knives. */ - DMG_FREEZE, /**< Ice/freezing temperature damage. */ - DMG_BURN, /**< Short flame, or on-fire type damage. */ - DMG_VEHICLE, /**< Vehicle ramming into you at speed. */ - DMG_FALL, /**< Fall damage */ - DMG_EXPLODE, /**< Firery explosion damage. */ - DMG_BLUNT, /**< Blunt damage, like from a pipe or a bat. */ - DMG_ELECTRO, /**< Electric shock damage. */ - DMG_SOUND, /**< Noise so irritating it creates damage. */ - DMG_ENERGYBEAM, /**< Energy beam damage. */ - DMG_GIB_NEVER, /**< This damage type doesn't cause gibbing. */ - DMG_GIB_ALWAYS, /**< This damage type will always gib. */ - DMG_DROWN, /**< Drown damage, gets restored over time. */ - DMG_PARALYZE, /**< Paralyzation damage. */ - DMG_NERVEGAS, /**< Toxins to the nerve, special effect? */ - DMG_POISON, /**< Poisonous damage. Similar to nervegas? */ - DMG_RADIATION, /**< Radiation damage. Geiger counter go brrr */ - DMG_DROWNRECOVER, /**< Health increase from drown recovery. */ - DMG_CHEMICAL, /**< Chemical damage. */ - DMG_SLOWBURN, /**< Slow burning, just like burning but different rate. */ - DMG_SLOWFREEZE, /**< Slow freeze, just freezing but different rate. */ - DMG_SKIP_ARMOR, /**< This damage will skip armor checks entirely. */ - DMG_SKIP_RAGDOLL /**< This damage will not affect ragdolls. */ -} damageType_t; - -#define DMG_ACID DMG_CHEMICAL +typedef enum +{ + DMG_GENERIC = 1, /**< Non specific. */ + DMG_CRUSH = 2, /**< Being crushed by something heavy. */ + DMG_BULLET = 4, /**< Shot by a gun. */ + DMG_SLASH = 8, /**< Cutting, from swords or knives. */ + DMG_FREEZE = 16, /**< Ice/freezing temperature damage. */ + DMG_BURN = 32, /**< Short flame, or on-fire type damage. */ + DMG_VEHICLE = 64, /**< Vehicle ramming into you at speed. */ + DMG_FALL = 128, /**< Fall damage */ + DMG_EXPLODE = 256, /**< Firery explosion damage. */ + DMG_BLUNT = 512, /**< Blunt damage, like from a pipe or a bat. */ + DMG_ELECTRO = 1024, /**< Electric shock damage. */ + DMG_SOUND = 2048, /**< Noise so irritating it creates damage. */ + DMG_ENERGYBEAM = 4096, /**< Energy beam damage. */ + DMG_GIB_NEVER = 8192, /**< This damage type doesn't cause gibbing. */ + DMG_GIB_ALWAYS = 16384, /**< This damage type will always gib. */ + DMG_DROWN = 32768, /**< Drown damage, gets restored over time. */ + DMG_PARALYZE = 65536, /**< Paralyzation damage. */ + DMG_NERVEGAS = 131072, /**< Toxins to the nerve, special effect? */ + DMG_POISON = 262144, /**< Poisonous damage. Similar to nervegas? */ + DMG_RADIATION = 524288, /**< Radiation damage. Geiger counter go brrr */ + DMG_DROWNRECOVER = 1048576, /**< Health increase from drown recovery. */ + DMG_CHEMICAL = 2097152, /**< Chemical damage. */ + DMG_SLOWBURN = 4194304, /**< Slow burning, just like burning but different rate. */ + DMG_SLOWFREEZE = 8388608, /**< Slow freeze, just freezing but different rate. */ + DMG_SKIP_ARMOR = 16777216, /**< This damage will skip armor checks entirely. */ + DMG_SKIP_RAGDOLL = 33554432 /**< This damage will not affect ragdolls. */ +} damageType_t; + +#define DMG_ACID DMG_CHEMICAL diff --git a/src/shared/decalgroups.h b/src/shared/decalgroups.h index 13bb54e3..d90bda3f 100644 --- a/src/shared/decalgroups.h +++ b/src/shared/decalgroups.h @@ -1,4 +1,18 @@ -/* Copyright (c) 2022, Vera Visions, L.L.C. All rights reserved. */ +/* + * Copyright (c) 2022-2023 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. +*/ /* Decal Property List Specs