From 93e4735c97a4bd75df455890fe0391369705b60f Mon Sep 17 00:00:00 2001 From: AdamTadeusz Date: Wed, 7 Aug 2024 16:12:56 +0100 Subject: [PATCH 01/14] First person muzzle flashes --- .../neo_predicted_viewmodel.cpp | 450 ++++++++++++++++++ mp/src/game/client/CMakeLists.txt | 2 + mp/src/game/server/CMakeLists.txt | 2 + mp/src/game/server/neo/neo_player.cpp | 7 + .../shared/neo/neo_predicted_viewmodel.cpp | 9 + .../game/shared/neo/neo_predicted_viewmodel.h | 2 + .../neo_predicted_viewmodel_muzzleflash.cpp | 49 ++ .../neo/neo_predicted_viewmodel_muzzleflash.h | 51 ++ 8 files changed, 572 insertions(+) create mode 100644 mp/src/enc_temp_folder/3c6b1714e08a6d8033a1666adb17254e/neo_predicted_viewmodel.cpp create mode 100644 mp/src/game/shared/neo/neo_predicted_viewmodel_muzzleflash.cpp create mode 100644 mp/src/game/shared/neo/neo_predicted_viewmodel_muzzleflash.h diff --git a/mp/src/enc_temp_folder/3c6b1714e08a6d8033a1666adb17254e/neo_predicted_viewmodel.cpp b/mp/src/enc_temp_folder/3c6b1714e08a6d8033a1666adb17254e/neo_predicted_viewmodel.cpp new file mode 100644 index 000000000..911fdde0f --- /dev/null +++ b/mp/src/enc_temp_folder/3c6b1714e08a6d8033a1666adb17254e/neo_predicted_viewmodel.cpp @@ -0,0 +1,450 @@ +#include "cbase.h" +#include "neo_predicted_viewmodel.h" + +#include "in_buttons.h" +#include "neo_gamerules.h" +#include "weapon_hl2mpbase.h" + +#ifdef CLIENT_DLL +#include "c_neo_player.h" + +#include "engine/ivdebugoverlay.h" +#include "iinput.h" +#include "inetchannelinfo.h" +#include "model_types.h" +#include "prediction.h" +#include "viewrender.h" +#else +#include "neo_player.h" +#endif +#include "neo_predicted_viewmodel_muzzleflash.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + + +IMPLEMENT_NETWORKCLASS_ALIASED(NEOPredictedViewModel, DT_NEOPredictedViewModel) + +BEGIN_NETWORK_TABLE(CNEOPredictedViewModel, DT_NEOPredictedViewModel) +#ifdef CLIENT_DLL +RecvPropFloat(RECVINFO(m_flYPrevious)), +#else +SendPropFloat(SENDINFO(m_flYPrevious)), +#endif +END_NETWORK_TABLE() + +#ifdef CLIENT_DLL +BEGIN_PREDICTION_DATA(CNEOPredictedViewModel) +DEFINE_PRED_FIELD(m_flYPrevious, FIELD_FLOAT, FTYPEDESC_INSENDTABLE), +END_PREDICTION_DATA() +#endif + +LINK_ENTITY_TO_CLASS(neo_predicted_viewmodel, CNEOPredictedViewModel); + +CNEOPredictedViewModel::CNEOPredictedViewModel() +#ifdef CLIENT_DLL + : m_iv_flYPrevious("CNEOPredictedViewModel::m_iv_flYPrevious") +#endif +{ +#ifdef CLIENT_DLL +#ifdef DEBUG + IMaterial *pass = materials->FindMaterial("dev/toc_cloakpass", TEXTURE_GROUP_CLIENT_EFFECTS); + Assert(pass && pass->IsPrecached()); +#endif + + AddVar(&m_flYPrevious, &m_iv_flYPrevious, LATCH_SIMULATION_VAR); +#endif + + m_flYPrevious = 0; + m_flStartAimingChange = 0; + m_bViewAim = false; +} + +CNEOPredictedViewModel::~CNEOPredictedViewModel() +{ +} + +#ifdef CLIENT_DLL +void CNEOPredictedViewModel::DrawRenderToTextureDebugInfo(IClientRenderable* pRenderable, + const Vector& mins, const Vector& maxs, const Vector &rgbColor, + const char *message, const Vector &vecOrigin) +{ + // Get the object's basis + Vector vec[3]; + AngleVectors( pRenderable->GetRenderAngles(), &vec[0], &vec[1], &vec[2] ); + vec[1] *= -1.0f; + + Vector vecSize; + VectorSubtract( maxs, mins, vecSize ); + + //Vector vecOrigin = pRenderable->GetRenderOrigin() + renderOffset; + Vector start, end, end2; + + VectorMA( vecOrigin, mins.x, vec[0], start ); + VectorMA( start, mins.y, vec[1], start ); + VectorMA( start, mins.z, vec[2], start ); + + VectorMA( start, vecSize.x, vec[0], end ); + VectorMA( end, vecSize.z, vec[2], end2 ); + + const float duration = 0.01f; + const bool noDepthTest = true; + + debugoverlay->AddLineOverlay( start, end, rgbColor[0], rgbColor[1], rgbColor[2], noDepthTest, duration); + debugoverlay->AddLineOverlay( end2, end, rgbColor[0], rgbColor[1], rgbColor[2], noDepthTest, duration); + + VectorMA( start, vecSize.y, vec[1], end ); + VectorMA( end, vecSize.z, vec[2], end2 ); + debugoverlay->AddLineOverlay( start, end, rgbColor[0], rgbColor[1], rgbColor[2], noDepthTest, duration); + debugoverlay->AddLineOverlay( end2, end, rgbColor[0], rgbColor[1], rgbColor[2], noDepthTest, duration); + + VectorMA( start, vecSize.z, vec[2], end ); + debugoverlay->AddLineOverlay( start, end, rgbColor[0], rgbColor[1], rgbColor[2], noDepthTest, duration); + + start = end; + VectorMA( start, vecSize.x, vec[0], end ); + debugoverlay->AddLineOverlay( start, end, rgbColor[0], rgbColor[1], rgbColor[2], noDepthTest, duration); + + VectorMA( start, vecSize.y, vec[1], end ); + debugoverlay->AddLineOverlay( start, end, rgbColor[0], rgbColor[1], rgbColor[2], noDepthTest, duration); + + VectorMA( end, vecSize.x, vec[0], start ); + VectorMA( start, -vecSize.x, vec[0], end ); + debugoverlay->AddLineOverlay( start, end, rgbColor[0], rgbColor[1], rgbColor[2], noDepthTest, duration); + + VectorMA( start, -vecSize.y, vec[1], end ); + debugoverlay->AddLineOverlay( start, end, rgbColor[0], rgbColor[1], rgbColor[2], noDepthTest, duration); + + VectorMA( start, -vecSize.z, vec[2], end ); + debugoverlay->AddLineOverlay( start, end, rgbColor[0], rgbColor[1], rgbColor[2], noDepthTest, duration); + + start = end; + VectorMA( start, -vecSize.x, vec[0], end ); + debugoverlay->AddLineOverlay( start, end, rgbColor[0], rgbColor[1], rgbColor[2], noDepthTest, duration); + + VectorMA( start, -vecSize.y, vec[1], end ); + debugoverlay->AddLineOverlay( start, end, rgbColor[0], rgbColor[1], rgbColor[2], noDepthTest, duration); + + C_BaseEntity *pEnt = pRenderable->GetIClientUnknown()->GetBaseEntity(); + int lineOffset = V_stristr("end", message) ? 1 : 0; + if ( pEnt ) + { + debugoverlay->AddTextOverlay( vecOrigin, lineOffset, "%s -- ent %d", message, pEnt->entindex() ); + } + else + { + debugoverlay->AddTextOverlay( vecOrigin, lineOffset, "%s -- renderable %X", message, (size_t)pRenderable ); + } +} +#endif + +ConVar neo_lean_debug_draw_hull("neo_lean_debug_draw_hull", "0", FCVAR_CHEAT | FCVAR_REPLICATED); +ConVar neo_lean_speed("neo_lean_speed", "0.333", FCVAR_REPLICATED | FCVAR_CHEAT, "Lean speed scale", true, 0.0, false, 1000.0); +// Original Neotokyo with the latest leftlean fix uses 7 for leftlean and 15 for rightlean yaw slide. +ConVar neo_lean_yaw_peek_left_amount("neo_lean_yaw_peek_left_amount", "7.0", FCVAR_REPLICATED | FCVAR_CHEAT, "How far sideways will a full left lean view reach.", true, 0.001f, false, 0); +ConVar neo_lean_yaw_peek_right_amount("neo_lean_yaw_peek_right_amount", "15.0", FCVAR_REPLICATED | FCVAR_CHEAT, "How far sideways will a full right lean view reach.", true, 0.001f, false, 0); +ConVar neo_lean_angle_percentage("neo_lean_angle_percentage", "0.75", FCVAR_REPLICATED | FCVAR_CHEAT, "for adjusting the actual angle of lean to a percentage of lean.", true, 0.0, true, 1.0); +ConVar neo_lean_tp_exaggerate_scale("neo_lean_tp_exaggerate_scale", "2", FCVAR_REPLICATED | FCVAR_CHEAT, "How much more to scale leaning motion in 3rd person animation vs 1st person viewmodel.", true, 0.0, false, 0); +ConVar neo_lean_fp_lower_eyes_scale("neo_lean_fp_lower_eyes_scale", "2.333", FCVAR_REPLICATED | FCVAR_CHEAT, "Multiplier for how low to bring eye-level (and hence bullet line level) whilst leaning.", true, 0.0, false, 0); + +#if(0) +ConVar neo_lean_thirdperson_roll_lerp_scale("neo_lean_thirdperson_roll_lerp_scale", "5", + FCVAR_REPLICATED | FCVAR_CHEAT, "Multiplier for 3rd person lean roll lerping.", true, 0.0, false, 0); +#endif + +float CNEOPredictedViewModel::freeRoomForLean(float leanAmount, CNEO_Player *player){ + const Vector playerDefaultViewPos = player->GetAbsOrigin(); + Vector deltaPlayerViewPos(0, leanAmount, 0); + VectorYawRotate(deltaPlayerViewPos, player->LocalEyeAngles().y, deltaPlayerViewPos); + const Vector leanEndPos = playerDefaultViewPos + deltaPlayerViewPos; + + // We can only lean through stuff that isn't solid for us + CTraceFilterNoNPCsOrPlayer filter(player, COLLISION_GROUP_PLAYER_MOVEMENT); + + // Player hull size, dependent on current ducking status + Vector hullMins, hullMaxs; + // Need this much z clearance to not "bump" our head whilst leaning + const Vector groundClearance(0, 0, 30); + +#if(0) // same view limits regardless of player class +#define STAND_MINS (NEORules()->GetViewVectors()->m_vHullMin + groundClearance) +#define STAND_MAXS (NEORules()->GetViewVectors()->m_vHullMax) +#define DUCK_MINS (NEORules()->GetViewVectors()->m_vDuckHullMin + groundClearance) +#define DUCK_MAXS (NEORules()->GetViewVectors()->m_vDuckHullMax) +#else // class hull specific limits +#define STAND_MINS (VEC_HULL_MIN_SCALED(player) + groundClearance) +#define STAND_MAXS (VEC_HULL_MAX_SCALED(player)) +#define DUCK_MINS (VEC_DUCK_HULL_MIN_SCALED(player) + groundClearance) +#define DUCK_MAXS (VEC_DUCK_HULL_MAX_SCALED(player)) +#endif + + if (player->GetFlags() & FL_DUCKING) + { + hullMins = DUCK_MINS; + hullMaxs = DUCK_MAXS; + } + else + { + hullMins = STAND_MINS; + hullMaxs = STAND_MAXS; + } + + Assert(hullMins.IsValid() && hullMaxs.IsValid()); + + trace_t trace; + UTIL_TraceHull(playerDefaultViewPos, leanEndPos, hullMins, hullMaxs, player->PhysicsSolidMaskForEntity(), &filter, &trace); + +#ifdef CLIENT_DLL + if (neo_lean_debug_draw_hull.GetBool()) + { + // Z offset to avoid text overlap; DrawRenderToTextureDebugInfo will also want to print text around similar area. + const Vector debugOffset = Vector(playerDefaultViewPos) + Vector(0, 0, -4); + const Vector color = Vector(20, 255, 0); + debugoverlay->AddTextOverlay(debugOffset, 0.0001, "x: %f\n y: %f\n z:%f\n", playerDefaultViewPos.x, playerDefaultViewPos.y, playerDefaultViewPos.z); + player->GetNEOViewModel()->DrawRenderToTextureDebugInfo(player, hullMins, hullMaxs, color, "freeRoomForLean", player->GetAbsOrigin()); + } +#endif + + return roundf(trace.startpos.DistTo(trace.endpos) * 100) / 100; +} + +#ifdef CLIENT_DLL +void CNEOPredictedViewModel::PostDataUpdate(DataUpdateType_t updateType) +{ + SetNextClientThink(CLIENT_THINK_ALWAYS); + BaseClass::PostDataUpdate(updateType); +} + +void CNEOPredictedViewModel::ClientThink() +{ + SetNextClientThink(CLIENT_THINK_ALWAYS); + BaseClass::ClientThink(); +} + +int CNEOPredictedViewModel::DrawModel(int flags) +{ + auto pPlayer = static_cast(GetOwner()); + + if (pPlayer) + { + if (pPlayer->IsCloaked()) + { + IMaterial *pass = materials->FindMaterial("dev/toc_vm", TEXTURE_GROUP_VIEW_MODEL); + Assert(pass && !pass->IsErrorMaterial()); + + if (pass && !pass->IsErrorMaterial()) + { + if (!pass->IsPrecached()) + { + PrecacheMaterial(pass->GetName()); + Assert(pass->IsPrecached()); + } + + //modelrender->SuppressEngineLighting(true); + modelrender->ForcedMaterialOverride(pass); + int ret = BaseClass::DrawModel(flags /*| STUDIO_RENDER | STUDIO_DRAWTRANSLUCENTSUBMODELS | STUDIO_TRANSPARENCY*/); + //modelrender->SuppressEngineLighting(false); + modelrender->ForcedMaterialOverride(NULL); + return ret; + } + + return 0; + } + } + + return BaseClass::DrawModel(flags); +} +#endif + +static inline float calculateLeanAngle(float freeRoom, CNEO_Player *player){ +#define HIP_TO_HEAD_HEIGHT 41.0f + return -RAD2DEG(atan2(freeRoom, HIP_TO_HEAD_HEIGHT)) * neo_lean_angle_percentage.GetFloat(); +} + +float GetLeanRatio(const float leanAngle) +{ + return fabs(leanAngle) / ((leanAngle < 0) ? neo_lean_yaw_peek_left_amount.GetFloat() : neo_lean_yaw_peek_right_amount.GetFloat()); +} + +float CNEOPredictedViewModel::lean(CNEO_Player *player){ + Assert(player); +#ifdef CLIENT_DLL + input->ExtraMouseSample(gpGlobals->frametime, 1); +#endif + QAngle viewAng = player->LocalEyeAngles(); + float Ycurrent = m_flYPrevious; + float Yfinal = 0; + +#ifdef GAME_DLL + if (m_pFirstPersonMuzzleFlash) + { + m_pFirstPersonMuzzleFlash->SetParentAttachment("SetParentAttachment", "Muzzle", false); + } +#endif + + if (player->IsAlive()) + { + switch (player->m_bInLean.Get()) + { + case NEO_LEAN_LEFT: + Yfinal = freeRoomForLean(neo_lean_yaw_peek_left_amount.GetFloat(), player); + break; + case NEO_LEAN_RIGHT: + Yfinal = -freeRoomForLean(-neo_lean_yaw_peek_right_amount.GetFloat(), player); + break; + default: + // not leaning, or leaning both ways; move towards zero + break; + } + } + + if (!(player->GetFlags() & FL_ONGROUND)) { + //mid-air; move towards zero + Yfinal = 0; + } + + const float dY = Yfinal - Ycurrent; + + + if (dY != 0){ + const float leanStep = 0.25f; + + // Almost done leaning; snap to zero to avoid back-and-forth "wiggle" + if (fabs(dY) - leanStep < 0) { + Ycurrent = Yfinal; + } + else { + Ycurrent = Lerp(leanStep * neo_lean_speed.GetFloat(), Ycurrent, Yfinal); + } + } + + Vector viewOffset(0, 0, 0); + viewOffset.y = m_flYPrevious = Ycurrent; + + VectorYawRotate(viewOffset, viewAng.y, viewOffset); + + float leanAngle = calculateLeanAngle(Ycurrent, player); + + const float leanRatio = GetLeanRatio(leanAngle); + + viewOffset.z = ((player->GetFlags() & FL_DUCKING) ? (VEC_DUCK_VIEW_SCALED(player).z) : VEC_VIEW_SCALED(player).z) - (neo_lean_fp_lower_eyes_scale.GetFloat() * leanRatio); + + player->m_vecLean = Vector(0, viewOffset.y, -(neo_lean_fp_lower_eyes_scale.GetFloat() * leanRatio)); + player->SetViewOffset(viewOffset); + + viewAng.z = leanAngle; +#ifdef CLIENT_DLL + engine->SetViewAngles(viewAng); +#endif + +#ifdef GAME_DLL + SetSimulationTime(gpGlobals->curtime); + SetNextThink(gpGlobals->curtime); +#endif + + if (leanAngle >= 0) + { + return leanAngle * neo_lean_tp_exaggerate_scale.GetFloat(); + } + else + { + const float leftleanOverleanRatio = (neo_lean_yaw_peek_right_amount.GetFloat() / neo_lean_yaw_peek_left_amount.GetFloat()); + return leanAngle * neo_lean_tp_exaggerate_scale.GetFloat() * leftleanOverleanRatio; + } +} + +void CNEOPredictedViewModel::CalcViewModelView(CBasePlayer *pOwner, + const Vector& eyePosition, const QAngle& eyeAngles) +{ + if (pOwner->GetObserverMode() == OBS_MODE_IN_EYE) + { + if (auto *pTargetPlayer = dynamic_cast(pOwner->GetObserverTarget()); + pTargetPlayer && !pTargetPlayer->IsObserver()) + { + // NEO NOTE (nullsystem): 1st person mode pOwner = pTargetPlayer eye position + // Take the target player's viewmodel FOV instead, otherwise it'll just look like it doesn't + // change viewmodel FOV on 1st spectate + return CalcViewModelView(pTargetPlayer, eyePosition, eyeAngles); + } + } + + // Is there a nicer way to do this? + auto weapon = static_cast(GetOwningWeapon()); + + if (!weapon) + { + return; + } + + CHL2MPSWeaponInfo data = weapon->GetHL2MPWpnData(); + + Vector vForward, vRight, vUp, newPos, vOffset; + QAngle newAng, angOffset; + + newAng = eyeAngles; + newPos = eyePosition; + + AngleVectors(newAng, &vForward, &vRight, &vUp); + + if (auto neoPlayer = static_cast(pOwner)) + { + vOffset = m_vOffset; + angOffset = m_angOffset; +#ifdef CLIENT_DLL + if (!prediction->InPrediction()) +#endif + { + const bool playerAiming = neoPlayer->IsInAim(); + const float currentTime = gpGlobals->curtime; + if (m_bViewAim && !playerAiming) + { + // From aiming to not aiming + m_flStartAimingChange = currentTime; + m_bViewAim = false; + } + else if (!m_bViewAim && playerAiming) + { + // From not aiming to aiming + m_flStartAimingChange = currentTime; + m_bViewAim = true; + } + const float endAimingChange = m_flStartAimingChange + NEO_ZOOM_SPEED; + const bool inAimingChange = (m_flStartAimingChange <= currentTime && currentTime < endAimingChange); + if (inAimingChange) + { + float percentage = clamp((currentTime - m_flStartAimingChange) / NEO_ZOOM_SPEED, 0.0f, 1.0f); + if (playerAiming) percentage = 1.0f - percentage; + vOffset = Lerp(percentage, data.m_vecVMAimPosOffset, data.m_vecVMPosOffset); + angOffset = Lerp(percentage, data.m_angVMAimAngOffset, data.m_angVMAngOffset); + } + else + { + vOffset = (playerAiming) ? data.m_vecVMAimPosOffset : data.m_vecVMPosOffset; + angOffset = (playerAiming) ? data.m_angVMAimAngOffset : data.m_angVMAngOffset; + } + m_vOffset = vOffset; + m_angOffset = angOffset; + } + } + + newPos += vForward * vOffset.x; + newPos += vRight * vOffset.y; + newPos += vUp * vOffset.z; + + newAng += angOffset; + + BaseClass::CalcViewModelView(pOwner, newPos, newAng); +} + +#ifdef CLIENT_DLL +RenderGroup_t CNEOPredictedViewModel::GetRenderGroup() +{ + auto pPlayer = static_cast(GetOwner()); + if (pPlayer) + { + return pPlayer->IsCloaked() ? RENDER_GROUP_VIEW_MODEL_TRANSLUCENT : RENDER_GROUP_VIEW_MODEL_OPAQUE; + } + + return BaseClass::GetRenderGroup(); +} +#endif diff --git a/mp/src/game/client/CMakeLists.txt b/mp/src/game/client/CMakeLists.txt index a54d53fea..c032df469 100644 --- a/mp/src/game/client/CMakeLists.txt +++ b/mp/src/game/client/CMakeLists.txt @@ -1553,6 +1553,8 @@ target_sources_grouped( ${CMAKE_SOURCE_DIR}/game/shared/neo/neo_playeranimstate.h ${CMAKE_SOURCE_DIR}/game/shared/neo/neo_predicted_viewmodel.cpp ${CMAKE_SOURCE_DIR}/game/shared/neo/neo_predicted_viewmodel.h + ${CMAKE_SOURCE_DIR}/game/shared/neo/neo_predicted_viewmodel_muzzleflash.cpp + ${CMAKE_SOURCE_DIR}/game/shared/neo/neo_predicted_viewmodel_muzzleflash.h ${CMAKE_SOURCE_DIR}/game/shared/neo/neo_shot_manipulator.cpp ${CMAKE_SOURCE_DIR}/game/shared/neo/neo_shot_manipulator.h ${CMAKE_SOURCE_DIR}/game/shared/neo/neo_version.cpp diff --git a/mp/src/game/server/CMakeLists.txt b/mp/src/game/server/CMakeLists.txt index 22f4c143c..6ecc6a149 100644 --- a/mp/src/game/server/CMakeLists.txt +++ b/mp/src/game/server/CMakeLists.txt @@ -1322,6 +1322,8 @@ target_sources_grouped( ${CMAKE_SOURCE_DIR}/game/shared/neo/neo_playeranimstate.h ${CMAKE_SOURCE_DIR}/game/shared/neo/neo_predicted_viewmodel.cpp ${CMAKE_SOURCE_DIR}/game/shared/neo/neo_predicted_viewmodel.h + ${CMAKE_SOURCE_DIR}/game/shared/neo/neo_predicted_viewmodel_muzzleflash.cpp + ${CMAKE_SOURCE_DIR}/game/shared/neo/neo_predicted_viewmodel_muzzleflash.h ${CMAKE_SOURCE_DIR}/game/shared/neo/neo_shot_manipulator.cpp ${CMAKE_SOURCE_DIR}/game/shared/neo/neo_shot_manipulator.h ${CMAKE_SOURCE_DIR}/game/shared/neo/neo_version.cpp diff --git a/mp/src/game/server/neo/neo_player.cpp b/mp/src/game/server/neo/neo_player.cpp index cff588f14..e6a17662e 100644 --- a/mp/src/game/server/neo/neo_player.cpp +++ b/mp/src/game/server/neo/neo_player.cpp @@ -1558,6 +1558,13 @@ void CNEO_Player::CreateViewModel( int index ) DispatchSpawn( vm ); vm->FollowEntity( this, false ); m_hViewModel.Set( index, vm ); + vm->m_pFirstPersonMuzzleFlash = (CNEOPredictedViewModelMuzzleFlash*)CreateEntityByName("neo_predicted_viewmodel_muzzleflash"); + if (vm->m_pFirstPersonMuzzleFlash) + { + vm->m_pFirstPersonMuzzleFlash->SetOwnerEntity(vm); + vm->m_pFirstPersonMuzzleFlash->SetParent(vm); + DispatchSpawn(vm->m_pFirstPersonMuzzleFlash); + } } else { diff --git a/mp/src/game/shared/neo/neo_predicted_viewmodel.cpp b/mp/src/game/shared/neo/neo_predicted_viewmodel.cpp index 07e3cb3c2..090358b6f 100644 --- a/mp/src/game/shared/neo/neo_predicted_viewmodel.cpp +++ b/mp/src/game/shared/neo/neo_predicted_viewmodel.cpp @@ -17,6 +17,7 @@ #else #include "neo_player.h" #endif +#include "neo_predicted_viewmodel_muzzleflash.h" // memdbgon must be the last include file in a .cpp file!!! #include "tier0/memdbgon.h" @@ -274,6 +275,14 @@ float CNEOPredictedViewModel::lean(CNEO_Player *player){ float Ycurrent = m_flYPrevious; float Yfinal = 0; + //NEOTODO (Adam) This does not belong here, work out where the viewmodel model is set when weapons are changed and update the attachment point there +#ifdef GAME_DLL + if (m_pFirstPersonMuzzleFlash) + { + m_pFirstPersonMuzzleFlash->SetParentAttachment("SetParentAttachment", "Muzzle", false); + } +#endif + if (player->IsAlive()) { switch (player->m_bInLean.Get()) diff --git a/mp/src/game/shared/neo/neo_predicted_viewmodel.h b/mp/src/game/shared/neo/neo_predicted_viewmodel.h index 8594a9c12..ccd9cb8df 100644 --- a/mp/src/game/shared/neo/neo_predicted_viewmodel.h +++ b/mp/src/game/shared/neo/neo_predicted_viewmodel.h @@ -5,6 +5,7 @@ #endif #include "predicted_viewmodel.h" +#include "neo_predicted_viewmodel_muzzleflash.h" #ifdef CLIENT_DLL //#include "clienteffectprecachesystem.h" @@ -64,6 +65,7 @@ class CNEOPredictedViewModel : public CPredictedViewModel float m_flYPrevious; CInterpolatedVar m_iv_flYPrevious; #endif + CNEOPredictedViewModelMuzzleFlash *m_pFirstPersonMuzzleFlash; private: float m_flStartAimingChange; diff --git a/mp/src/game/shared/neo/neo_predicted_viewmodel_muzzleflash.cpp b/mp/src/game/shared/neo/neo_predicted_viewmodel_muzzleflash.cpp new file mode 100644 index 000000000..47253670d --- /dev/null +++ b/mp/src/game/shared/neo/neo_predicted_viewmodel_muzzleflash.cpp @@ -0,0 +1,49 @@ +#include "cbase.h" + +#ifdef GAME_DLL +#include "baseanimating.h" +#endif + +#include "neo_predicted_viewmodel_muzzleflash.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +LINK_ENTITY_TO_CLASS(neo_predicted_viewmodel_muzzleflash, CNEOPredictedViewModelMuzzleFlash); + +// Start of our data description for the class +BEGIN_DATADESC(CNEOPredictedViewModelMuzzleFlash) + +// Save/restore our active state +DEFINE_FIELD(m_bActive, FIELD_BOOLEAN), +DEFINE_FIELD(m_flNextChangeTime, FIELD_TIME), + +END_DATADESC() + +#define MUZZLE_FLASH_ENTITY_MODEL "models/effect/fpmf/fpmf01.mdl" + +//----------------------------------------------------------------------------- +// Purpose: Precache assets used by the entity +//----------------------------------------------------------------------------- +void CNEOPredictedViewModelMuzzleFlash::Precache(void) +{ + PrecacheModel(MUZZLE_FLASH_ENTITY_MODEL); + + BaseClass::Precache(); +} + +//----------------------------------------------------------------------------- +// Purpose: Sets up the entity's initial state +//----------------------------------------------------------------------------- +void CNEOPredictedViewModelMuzzleFlash::Spawn(void) +{ + Precache(); + + SetModel(MUZZLE_FLASH_ENTITY_MODEL); + SetSolid(SOLID_NONE); + AddEffects(EF_NOSHADOW); + AddEffects(EF_NORECEIVESHADOW); +#ifdef CLIENT_DLL + clienttools->SetRenderGroup(this, RENDER_GROUP_VIEW_MODEL_OPAQUE); +#endif; +} \ No newline at end of file diff --git a/mp/src/game/shared/neo/neo_predicted_viewmodel_muzzleflash.h b/mp/src/game/shared/neo/neo_predicted_viewmodel_muzzleflash.h new file mode 100644 index 000000000..a5c72d8b5 --- /dev/null +++ b/mp/src/game/shared/neo/neo_predicted_viewmodel_muzzleflash.h @@ -0,0 +1,51 @@ +#ifndef NEO_PREDICTED_VIEWMODEL_MUZZLEFLASH_H +#define NEO_PREDICTED_VIEWMODEL_MUZZLEFLASH_H +#ifdef _WIN32 +#pragma once +#endif + +#ifdef GAME_DLL +#include "baseanimating.h" +#include "baseviewmodel_shared.h" +#else +#include "c_baseviewmodel.h" +#endif + +class CNEO_Player; +class CNEOPredictedViewModelMuzzleFlash : public CBaseAnimating +{ +public: + DECLARE_CLASS(CNEOPredictedViewModelMuzzleFlash, CBaseAnimating); + DECLARE_DATADESC(); + CNEOPredictedViewModelMuzzleFlash() + { + m_bActive = false; + m_flNextChangeTime = 0.f; +#ifdef CLIENT_DLL + m_hRender = INVALID_CLIENT_RENDER_HANDLE; + AddToLeafSystem(); +#endif + } + +#ifdef CLIENT_DLL + ShadowType_t ShadowCastType() override { return SHADOWS_NONE; }; + bool IsViewModel() const override { return true; }; + RenderGroup_t GetRenderGroup() override { return RENDER_GROUP_VIEW_MODEL_OPAQUE; }; + bool ShouldDraw() override { return true; }; +#endif + + void Spawn(void); + void Precache(void); + + void MoveThink(void); + + // Input function + void InputToggle(inputdata_t& inputData); + +private: + + bool m_bActive; + float m_flNextChangeTime; +}; + +#endif // NEO_PREDICTED_VIEWMODEL_MUZZLEFLASH_H \ No newline at end of file From a0baf1af1714db83b65caca3676904489eb99472 Mon Sep 17 00:00:00 2001 From: AdamTadeusz Date: Thu, 8 Aug 2024 13:37:49 +0100 Subject: [PATCH 02/14] terrible but works --- .../neo_predicted_viewmodel.cpp | 450 ------------------ mp/src/game/server/neo/neo_player.cpp | 7 - .../shared/neo/neo_predicted_viewmodel.cpp | 28 +- .../game/shared/neo/neo_predicted_viewmodel.h | 9 + .../neo_predicted_viewmodel_muzzleflash.cpp | 25 +- .../neo/neo_predicted_viewmodel_muzzleflash.h | 6 +- 6 files changed, 52 insertions(+), 473 deletions(-) delete mode 100644 mp/src/enc_temp_folder/3c6b1714e08a6d8033a1666adb17254e/neo_predicted_viewmodel.cpp diff --git a/mp/src/enc_temp_folder/3c6b1714e08a6d8033a1666adb17254e/neo_predicted_viewmodel.cpp b/mp/src/enc_temp_folder/3c6b1714e08a6d8033a1666adb17254e/neo_predicted_viewmodel.cpp deleted file mode 100644 index 911fdde0f..000000000 --- a/mp/src/enc_temp_folder/3c6b1714e08a6d8033a1666adb17254e/neo_predicted_viewmodel.cpp +++ /dev/null @@ -1,450 +0,0 @@ -#include "cbase.h" -#include "neo_predicted_viewmodel.h" - -#include "in_buttons.h" -#include "neo_gamerules.h" -#include "weapon_hl2mpbase.h" - -#ifdef CLIENT_DLL -#include "c_neo_player.h" - -#include "engine/ivdebugoverlay.h" -#include "iinput.h" -#include "inetchannelinfo.h" -#include "model_types.h" -#include "prediction.h" -#include "viewrender.h" -#else -#include "neo_player.h" -#endif -#include "neo_predicted_viewmodel_muzzleflash.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - - -IMPLEMENT_NETWORKCLASS_ALIASED(NEOPredictedViewModel, DT_NEOPredictedViewModel) - -BEGIN_NETWORK_TABLE(CNEOPredictedViewModel, DT_NEOPredictedViewModel) -#ifdef CLIENT_DLL -RecvPropFloat(RECVINFO(m_flYPrevious)), -#else -SendPropFloat(SENDINFO(m_flYPrevious)), -#endif -END_NETWORK_TABLE() - -#ifdef CLIENT_DLL -BEGIN_PREDICTION_DATA(CNEOPredictedViewModel) -DEFINE_PRED_FIELD(m_flYPrevious, FIELD_FLOAT, FTYPEDESC_INSENDTABLE), -END_PREDICTION_DATA() -#endif - -LINK_ENTITY_TO_CLASS(neo_predicted_viewmodel, CNEOPredictedViewModel); - -CNEOPredictedViewModel::CNEOPredictedViewModel() -#ifdef CLIENT_DLL - : m_iv_flYPrevious("CNEOPredictedViewModel::m_iv_flYPrevious") -#endif -{ -#ifdef CLIENT_DLL -#ifdef DEBUG - IMaterial *pass = materials->FindMaterial("dev/toc_cloakpass", TEXTURE_GROUP_CLIENT_EFFECTS); - Assert(pass && pass->IsPrecached()); -#endif - - AddVar(&m_flYPrevious, &m_iv_flYPrevious, LATCH_SIMULATION_VAR); -#endif - - m_flYPrevious = 0; - m_flStartAimingChange = 0; - m_bViewAim = false; -} - -CNEOPredictedViewModel::~CNEOPredictedViewModel() -{ -} - -#ifdef CLIENT_DLL -void CNEOPredictedViewModel::DrawRenderToTextureDebugInfo(IClientRenderable* pRenderable, - const Vector& mins, const Vector& maxs, const Vector &rgbColor, - const char *message, const Vector &vecOrigin) -{ - // Get the object's basis - Vector vec[3]; - AngleVectors( pRenderable->GetRenderAngles(), &vec[0], &vec[1], &vec[2] ); - vec[1] *= -1.0f; - - Vector vecSize; - VectorSubtract( maxs, mins, vecSize ); - - //Vector vecOrigin = pRenderable->GetRenderOrigin() + renderOffset; - Vector start, end, end2; - - VectorMA( vecOrigin, mins.x, vec[0], start ); - VectorMA( start, mins.y, vec[1], start ); - VectorMA( start, mins.z, vec[2], start ); - - VectorMA( start, vecSize.x, vec[0], end ); - VectorMA( end, vecSize.z, vec[2], end2 ); - - const float duration = 0.01f; - const bool noDepthTest = true; - - debugoverlay->AddLineOverlay( start, end, rgbColor[0], rgbColor[1], rgbColor[2], noDepthTest, duration); - debugoverlay->AddLineOverlay( end2, end, rgbColor[0], rgbColor[1], rgbColor[2], noDepthTest, duration); - - VectorMA( start, vecSize.y, vec[1], end ); - VectorMA( end, vecSize.z, vec[2], end2 ); - debugoverlay->AddLineOverlay( start, end, rgbColor[0], rgbColor[1], rgbColor[2], noDepthTest, duration); - debugoverlay->AddLineOverlay( end2, end, rgbColor[0], rgbColor[1], rgbColor[2], noDepthTest, duration); - - VectorMA( start, vecSize.z, vec[2], end ); - debugoverlay->AddLineOverlay( start, end, rgbColor[0], rgbColor[1], rgbColor[2], noDepthTest, duration); - - start = end; - VectorMA( start, vecSize.x, vec[0], end ); - debugoverlay->AddLineOverlay( start, end, rgbColor[0], rgbColor[1], rgbColor[2], noDepthTest, duration); - - VectorMA( start, vecSize.y, vec[1], end ); - debugoverlay->AddLineOverlay( start, end, rgbColor[0], rgbColor[1], rgbColor[2], noDepthTest, duration); - - VectorMA( end, vecSize.x, vec[0], start ); - VectorMA( start, -vecSize.x, vec[0], end ); - debugoverlay->AddLineOverlay( start, end, rgbColor[0], rgbColor[1], rgbColor[2], noDepthTest, duration); - - VectorMA( start, -vecSize.y, vec[1], end ); - debugoverlay->AddLineOverlay( start, end, rgbColor[0], rgbColor[1], rgbColor[2], noDepthTest, duration); - - VectorMA( start, -vecSize.z, vec[2], end ); - debugoverlay->AddLineOverlay( start, end, rgbColor[0], rgbColor[1], rgbColor[2], noDepthTest, duration); - - start = end; - VectorMA( start, -vecSize.x, vec[0], end ); - debugoverlay->AddLineOverlay( start, end, rgbColor[0], rgbColor[1], rgbColor[2], noDepthTest, duration); - - VectorMA( start, -vecSize.y, vec[1], end ); - debugoverlay->AddLineOverlay( start, end, rgbColor[0], rgbColor[1], rgbColor[2], noDepthTest, duration); - - C_BaseEntity *pEnt = pRenderable->GetIClientUnknown()->GetBaseEntity(); - int lineOffset = V_stristr("end", message) ? 1 : 0; - if ( pEnt ) - { - debugoverlay->AddTextOverlay( vecOrigin, lineOffset, "%s -- ent %d", message, pEnt->entindex() ); - } - else - { - debugoverlay->AddTextOverlay( vecOrigin, lineOffset, "%s -- renderable %X", message, (size_t)pRenderable ); - } -} -#endif - -ConVar neo_lean_debug_draw_hull("neo_lean_debug_draw_hull", "0", FCVAR_CHEAT | FCVAR_REPLICATED); -ConVar neo_lean_speed("neo_lean_speed", "0.333", FCVAR_REPLICATED | FCVAR_CHEAT, "Lean speed scale", true, 0.0, false, 1000.0); -// Original Neotokyo with the latest leftlean fix uses 7 for leftlean and 15 for rightlean yaw slide. -ConVar neo_lean_yaw_peek_left_amount("neo_lean_yaw_peek_left_amount", "7.0", FCVAR_REPLICATED | FCVAR_CHEAT, "How far sideways will a full left lean view reach.", true, 0.001f, false, 0); -ConVar neo_lean_yaw_peek_right_amount("neo_lean_yaw_peek_right_amount", "15.0", FCVAR_REPLICATED | FCVAR_CHEAT, "How far sideways will a full right lean view reach.", true, 0.001f, false, 0); -ConVar neo_lean_angle_percentage("neo_lean_angle_percentage", "0.75", FCVAR_REPLICATED | FCVAR_CHEAT, "for adjusting the actual angle of lean to a percentage of lean.", true, 0.0, true, 1.0); -ConVar neo_lean_tp_exaggerate_scale("neo_lean_tp_exaggerate_scale", "2", FCVAR_REPLICATED | FCVAR_CHEAT, "How much more to scale leaning motion in 3rd person animation vs 1st person viewmodel.", true, 0.0, false, 0); -ConVar neo_lean_fp_lower_eyes_scale("neo_lean_fp_lower_eyes_scale", "2.333", FCVAR_REPLICATED | FCVAR_CHEAT, "Multiplier for how low to bring eye-level (and hence bullet line level) whilst leaning.", true, 0.0, false, 0); - -#if(0) -ConVar neo_lean_thirdperson_roll_lerp_scale("neo_lean_thirdperson_roll_lerp_scale", "5", - FCVAR_REPLICATED | FCVAR_CHEAT, "Multiplier for 3rd person lean roll lerping.", true, 0.0, false, 0); -#endif - -float CNEOPredictedViewModel::freeRoomForLean(float leanAmount, CNEO_Player *player){ - const Vector playerDefaultViewPos = player->GetAbsOrigin(); - Vector deltaPlayerViewPos(0, leanAmount, 0); - VectorYawRotate(deltaPlayerViewPos, player->LocalEyeAngles().y, deltaPlayerViewPos); - const Vector leanEndPos = playerDefaultViewPos + deltaPlayerViewPos; - - // We can only lean through stuff that isn't solid for us - CTraceFilterNoNPCsOrPlayer filter(player, COLLISION_GROUP_PLAYER_MOVEMENT); - - // Player hull size, dependent on current ducking status - Vector hullMins, hullMaxs; - // Need this much z clearance to not "bump" our head whilst leaning - const Vector groundClearance(0, 0, 30); - -#if(0) // same view limits regardless of player class -#define STAND_MINS (NEORules()->GetViewVectors()->m_vHullMin + groundClearance) -#define STAND_MAXS (NEORules()->GetViewVectors()->m_vHullMax) -#define DUCK_MINS (NEORules()->GetViewVectors()->m_vDuckHullMin + groundClearance) -#define DUCK_MAXS (NEORules()->GetViewVectors()->m_vDuckHullMax) -#else // class hull specific limits -#define STAND_MINS (VEC_HULL_MIN_SCALED(player) + groundClearance) -#define STAND_MAXS (VEC_HULL_MAX_SCALED(player)) -#define DUCK_MINS (VEC_DUCK_HULL_MIN_SCALED(player) + groundClearance) -#define DUCK_MAXS (VEC_DUCK_HULL_MAX_SCALED(player)) -#endif - - if (player->GetFlags() & FL_DUCKING) - { - hullMins = DUCK_MINS; - hullMaxs = DUCK_MAXS; - } - else - { - hullMins = STAND_MINS; - hullMaxs = STAND_MAXS; - } - - Assert(hullMins.IsValid() && hullMaxs.IsValid()); - - trace_t trace; - UTIL_TraceHull(playerDefaultViewPos, leanEndPos, hullMins, hullMaxs, player->PhysicsSolidMaskForEntity(), &filter, &trace); - -#ifdef CLIENT_DLL - if (neo_lean_debug_draw_hull.GetBool()) - { - // Z offset to avoid text overlap; DrawRenderToTextureDebugInfo will also want to print text around similar area. - const Vector debugOffset = Vector(playerDefaultViewPos) + Vector(0, 0, -4); - const Vector color = Vector(20, 255, 0); - debugoverlay->AddTextOverlay(debugOffset, 0.0001, "x: %f\n y: %f\n z:%f\n", playerDefaultViewPos.x, playerDefaultViewPos.y, playerDefaultViewPos.z); - player->GetNEOViewModel()->DrawRenderToTextureDebugInfo(player, hullMins, hullMaxs, color, "freeRoomForLean", player->GetAbsOrigin()); - } -#endif - - return roundf(trace.startpos.DistTo(trace.endpos) * 100) / 100; -} - -#ifdef CLIENT_DLL -void CNEOPredictedViewModel::PostDataUpdate(DataUpdateType_t updateType) -{ - SetNextClientThink(CLIENT_THINK_ALWAYS); - BaseClass::PostDataUpdate(updateType); -} - -void CNEOPredictedViewModel::ClientThink() -{ - SetNextClientThink(CLIENT_THINK_ALWAYS); - BaseClass::ClientThink(); -} - -int CNEOPredictedViewModel::DrawModel(int flags) -{ - auto pPlayer = static_cast(GetOwner()); - - if (pPlayer) - { - if (pPlayer->IsCloaked()) - { - IMaterial *pass = materials->FindMaterial("dev/toc_vm", TEXTURE_GROUP_VIEW_MODEL); - Assert(pass && !pass->IsErrorMaterial()); - - if (pass && !pass->IsErrorMaterial()) - { - if (!pass->IsPrecached()) - { - PrecacheMaterial(pass->GetName()); - Assert(pass->IsPrecached()); - } - - //modelrender->SuppressEngineLighting(true); - modelrender->ForcedMaterialOverride(pass); - int ret = BaseClass::DrawModel(flags /*| STUDIO_RENDER | STUDIO_DRAWTRANSLUCENTSUBMODELS | STUDIO_TRANSPARENCY*/); - //modelrender->SuppressEngineLighting(false); - modelrender->ForcedMaterialOverride(NULL); - return ret; - } - - return 0; - } - } - - return BaseClass::DrawModel(flags); -} -#endif - -static inline float calculateLeanAngle(float freeRoom, CNEO_Player *player){ -#define HIP_TO_HEAD_HEIGHT 41.0f - return -RAD2DEG(atan2(freeRoom, HIP_TO_HEAD_HEIGHT)) * neo_lean_angle_percentage.GetFloat(); -} - -float GetLeanRatio(const float leanAngle) -{ - return fabs(leanAngle) / ((leanAngle < 0) ? neo_lean_yaw_peek_left_amount.GetFloat() : neo_lean_yaw_peek_right_amount.GetFloat()); -} - -float CNEOPredictedViewModel::lean(CNEO_Player *player){ - Assert(player); -#ifdef CLIENT_DLL - input->ExtraMouseSample(gpGlobals->frametime, 1); -#endif - QAngle viewAng = player->LocalEyeAngles(); - float Ycurrent = m_flYPrevious; - float Yfinal = 0; - -#ifdef GAME_DLL - if (m_pFirstPersonMuzzleFlash) - { - m_pFirstPersonMuzzleFlash->SetParentAttachment("SetParentAttachment", "Muzzle", false); - } -#endif - - if (player->IsAlive()) - { - switch (player->m_bInLean.Get()) - { - case NEO_LEAN_LEFT: - Yfinal = freeRoomForLean(neo_lean_yaw_peek_left_amount.GetFloat(), player); - break; - case NEO_LEAN_RIGHT: - Yfinal = -freeRoomForLean(-neo_lean_yaw_peek_right_amount.GetFloat(), player); - break; - default: - // not leaning, or leaning both ways; move towards zero - break; - } - } - - if (!(player->GetFlags() & FL_ONGROUND)) { - //mid-air; move towards zero - Yfinal = 0; - } - - const float dY = Yfinal - Ycurrent; - - - if (dY != 0){ - const float leanStep = 0.25f; - - // Almost done leaning; snap to zero to avoid back-and-forth "wiggle" - if (fabs(dY) - leanStep < 0) { - Ycurrent = Yfinal; - } - else { - Ycurrent = Lerp(leanStep * neo_lean_speed.GetFloat(), Ycurrent, Yfinal); - } - } - - Vector viewOffset(0, 0, 0); - viewOffset.y = m_flYPrevious = Ycurrent; - - VectorYawRotate(viewOffset, viewAng.y, viewOffset); - - float leanAngle = calculateLeanAngle(Ycurrent, player); - - const float leanRatio = GetLeanRatio(leanAngle); - - viewOffset.z = ((player->GetFlags() & FL_DUCKING) ? (VEC_DUCK_VIEW_SCALED(player).z) : VEC_VIEW_SCALED(player).z) - (neo_lean_fp_lower_eyes_scale.GetFloat() * leanRatio); - - player->m_vecLean = Vector(0, viewOffset.y, -(neo_lean_fp_lower_eyes_scale.GetFloat() * leanRatio)); - player->SetViewOffset(viewOffset); - - viewAng.z = leanAngle; -#ifdef CLIENT_DLL - engine->SetViewAngles(viewAng); -#endif - -#ifdef GAME_DLL - SetSimulationTime(gpGlobals->curtime); - SetNextThink(gpGlobals->curtime); -#endif - - if (leanAngle >= 0) - { - return leanAngle * neo_lean_tp_exaggerate_scale.GetFloat(); - } - else - { - const float leftleanOverleanRatio = (neo_lean_yaw_peek_right_amount.GetFloat() / neo_lean_yaw_peek_left_amount.GetFloat()); - return leanAngle * neo_lean_tp_exaggerate_scale.GetFloat() * leftleanOverleanRatio; - } -} - -void CNEOPredictedViewModel::CalcViewModelView(CBasePlayer *pOwner, - const Vector& eyePosition, const QAngle& eyeAngles) -{ - if (pOwner->GetObserverMode() == OBS_MODE_IN_EYE) - { - if (auto *pTargetPlayer = dynamic_cast(pOwner->GetObserverTarget()); - pTargetPlayer && !pTargetPlayer->IsObserver()) - { - // NEO NOTE (nullsystem): 1st person mode pOwner = pTargetPlayer eye position - // Take the target player's viewmodel FOV instead, otherwise it'll just look like it doesn't - // change viewmodel FOV on 1st spectate - return CalcViewModelView(pTargetPlayer, eyePosition, eyeAngles); - } - } - - // Is there a nicer way to do this? - auto weapon = static_cast(GetOwningWeapon()); - - if (!weapon) - { - return; - } - - CHL2MPSWeaponInfo data = weapon->GetHL2MPWpnData(); - - Vector vForward, vRight, vUp, newPos, vOffset; - QAngle newAng, angOffset; - - newAng = eyeAngles; - newPos = eyePosition; - - AngleVectors(newAng, &vForward, &vRight, &vUp); - - if (auto neoPlayer = static_cast(pOwner)) - { - vOffset = m_vOffset; - angOffset = m_angOffset; -#ifdef CLIENT_DLL - if (!prediction->InPrediction()) -#endif - { - const bool playerAiming = neoPlayer->IsInAim(); - const float currentTime = gpGlobals->curtime; - if (m_bViewAim && !playerAiming) - { - // From aiming to not aiming - m_flStartAimingChange = currentTime; - m_bViewAim = false; - } - else if (!m_bViewAim && playerAiming) - { - // From not aiming to aiming - m_flStartAimingChange = currentTime; - m_bViewAim = true; - } - const float endAimingChange = m_flStartAimingChange + NEO_ZOOM_SPEED; - const bool inAimingChange = (m_flStartAimingChange <= currentTime && currentTime < endAimingChange); - if (inAimingChange) - { - float percentage = clamp((currentTime - m_flStartAimingChange) / NEO_ZOOM_SPEED, 0.0f, 1.0f); - if (playerAiming) percentage = 1.0f - percentage; - vOffset = Lerp(percentage, data.m_vecVMAimPosOffset, data.m_vecVMPosOffset); - angOffset = Lerp(percentage, data.m_angVMAimAngOffset, data.m_angVMAngOffset); - } - else - { - vOffset = (playerAiming) ? data.m_vecVMAimPosOffset : data.m_vecVMPosOffset; - angOffset = (playerAiming) ? data.m_angVMAimAngOffset : data.m_angVMAngOffset; - } - m_vOffset = vOffset; - m_angOffset = angOffset; - } - } - - newPos += vForward * vOffset.x; - newPos += vRight * vOffset.y; - newPos += vUp * vOffset.z; - - newAng += angOffset; - - BaseClass::CalcViewModelView(pOwner, newPos, newAng); -} - -#ifdef CLIENT_DLL -RenderGroup_t CNEOPredictedViewModel::GetRenderGroup() -{ - auto pPlayer = static_cast(GetOwner()); - if (pPlayer) - { - return pPlayer->IsCloaked() ? RENDER_GROUP_VIEW_MODEL_TRANSLUCENT : RENDER_GROUP_VIEW_MODEL_OPAQUE; - } - - return BaseClass::GetRenderGroup(); -} -#endif diff --git a/mp/src/game/server/neo/neo_player.cpp b/mp/src/game/server/neo/neo_player.cpp index e6a17662e..cff588f14 100644 --- a/mp/src/game/server/neo/neo_player.cpp +++ b/mp/src/game/server/neo/neo_player.cpp @@ -1558,13 +1558,6 @@ void CNEO_Player::CreateViewModel( int index ) DispatchSpawn( vm ); vm->FollowEntity( this, false ); m_hViewModel.Set( index, vm ); - vm->m_pFirstPersonMuzzleFlash = (CNEOPredictedViewModelMuzzleFlash*)CreateEntityByName("neo_predicted_viewmodel_muzzleflash"); - if (vm->m_pFirstPersonMuzzleFlash) - { - vm->m_pFirstPersonMuzzleFlash->SetOwnerEntity(vm); - vm->m_pFirstPersonMuzzleFlash->SetParent(vm); - DispatchSpawn(vm->m_pFirstPersonMuzzleFlash); - } } else { diff --git a/mp/src/game/shared/neo/neo_predicted_viewmodel.cpp b/mp/src/game/shared/neo/neo_predicted_viewmodel.cpp index 090358b6f..5f60a9284 100644 --- a/mp/src/game/shared/neo/neo_predicted_viewmodel.cpp +++ b/mp/src/game/shared/neo/neo_predicted_viewmodel.cpp @@ -58,6 +58,18 @@ CNEOPredictedViewModel::CNEOPredictedViewModel() m_flYPrevious = 0; m_flStartAimingChange = 0; m_bViewAim = false; + m_pFirstPersonMuzzleFlash = (CNEOPredictedViewModelMuzzleFlash*)CreateEntityByName("neo_predicted_viewmodel_muzzleflash"); + if (m_pFirstPersonMuzzleFlash) + { + m_pFirstPersonMuzzleFlash->SetOwnerEntity(this); + m_pFirstPersonMuzzleFlash->SetParent(this); + m_pFirstPersonMuzzleFlash->SetModelScale(1); +#ifdef GAME_DLL + m_pFirstPersonMuzzleFlash->Spawn(); +#else + clienttools->SetRenderGroup(m_pFirstPersonMuzzleFlash, RENDER_GROUP_VIEW_MODEL_OPAQUE); +#endif + } } CNEOPredictedViewModel::~CNEOPredictedViewModel() @@ -275,14 +287,6 @@ float CNEOPredictedViewModel::lean(CNEO_Player *player){ float Ycurrent = m_flYPrevious; float Yfinal = 0; - //NEOTODO (Adam) This does not belong here, work out where the viewmodel model is set when weapons are changed and update the attachment point there -#ifdef GAME_DLL - if (m_pFirstPersonMuzzleFlash) - { - m_pFirstPersonMuzzleFlash->SetParentAttachment("SetParentAttachment", "Muzzle", false); - } -#endif - if (player->IsAlive()) { switch (player->m_bInLean.Get()) @@ -377,6 +381,14 @@ void CNEOPredictedViewModel::CalcViewModelView(CBasePlayer *pOwner, return; } +#ifdef GAME_DLL + if (LookupAttachment("Muzzle") > 0) + { + m_pFirstPersonMuzzleFlash->SetParent(this); + m_pFirstPersonMuzzleFlash->SetParentAttachment("SetParentAttachment", "Muzzle", false); + } +#endif + CHL2MPSWeaponInfo data = weapon->GetHL2MPWpnData(); Vector vForward, vRight, vUp, newPos, vOffset; diff --git a/mp/src/game/shared/neo/neo_predicted_viewmodel.h b/mp/src/game/shared/neo/neo_predicted_viewmodel.h index ccd9cb8df..4826fbb2c 100644 --- a/mp/src/game/shared/neo/neo_predicted_viewmodel.h +++ b/mp/src/game/shared/neo/neo_predicted_viewmodel.h @@ -44,7 +44,16 @@ class CNEOPredictedViewModel : public CPredictedViewModel virtual int DrawModel(int flags); virtual RenderGroup_t GetRenderGroup(); + #endif + virtual void DoMuzzleFlash() + { + if (m_pFirstPersonMuzzleFlash) + { + m_pFirstPersonMuzzleFlash->DoMuzzleFlash(); + } + BaseClass::DoMuzzleFlash(); + } #ifdef CLIENT_DLL float GetLeanInterp() diff --git a/mp/src/game/shared/neo/neo_predicted_viewmodel_muzzleflash.cpp b/mp/src/game/shared/neo/neo_predicted_viewmodel_muzzleflash.cpp index 47253670d..93647a165 100644 --- a/mp/src/game/shared/neo/neo_predicted_viewmodel_muzzleflash.cpp +++ b/mp/src/game/shared/neo/neo_predicted_viewmodel_muzzleflash.cpp @@ -1,4 +1,5 @@ #include "cbase.h" +#include "model_types.h" #ifdef GAME_DLL #include "baseanimating.h" @@ -41,9 +42,27 @@ void CNEOPredictedViewModelMuzzleFlash::Spawn(void) SetModel(MUZZLE_FLASH_ENTITY_MODEL); SetSolid(SOLID_NONE); + SetMoveType(MOVETYPE_NONE); AddEffects(EF_NOSHADOW); AddEffects(EF_NORECEIVESHADOW); +} + #ifdef CLIENT_DLL - clienttools->SetRenderGroup(this, RENDER_GROUP_VIEW_MODEL_OPAQUE); -#endif; -} \ No newline at end of file +int CNEOPredictedViewModelMuzzleFlash::DrawModel(int flags) +{ + IMaterial* pass = materials->FindMaterial("effects/fpmf/fpmf01.vmt", TEXTURE_GROUP_VIEW_MODEL); + if (!ShouldMuzzleFlash()) + { + pass->SetMaterialVarFlag(MATERIAL_VAR_NO_DRAW, true); + } + else + { + SetLocalAnglesDim( 1, AngleNormalize(random->RandomInt(-1200, 1200))); + pass->SetMaterialVarFlag(MATERIAL_VAR_NO_DRAW, false); + } + DisableMuzzleFlash(); + pass->SetMaterialVarFlag(MATERIAL_VAR_IGNOREZ, true); + int ret = BaseClass::DrawModel(flags); + return ret; +} +#endif \ No newline at end of file diff --git a/mp/src/game/shared/neo/neo_predicted_viewmodel_muzzleflash.h b/mp/src/game/shared/neo/neo_predicted_viewmodel_muzzleflash.h index a5c72d8b5..2e55b3e50 100644 --- a/mp/src/game/shared/neo/neo_predicted_viewmodel_muzzleflash.h +++ b/mp/src/game/shared/neo/neo_predicted_viewmodel_muzzleflash.h @@ -32,16 +32,12 @@ class CNEOPredictedViewModelMuzzleFlash : public CBaseAnimating bool IsViewModel() const override { return true; }; RenderGroup_t GetRenderGroup() override { return RENDER_GROUP_VIEW_MODEL_OPAQUE; }; bool ShouldDraw() override { return true; }; + int DrawModel(int flags) override; #endif void Spawn(void); void Precache(void); - void MoveThink(void); - - // Input function - void InputToggle(inputdata_t& inputData); - private: bool m_bActive; From 61390eb57554c25bb50c34d1dc61e71ebd5f3da8 Mon Sep 17 00:00:00 2001 From: AdamTadeusz Date: Fri, 9 Aug 2024 14:56:54 +0100 Subject: [PATCH 03/14] groundwork for the different muzzle flash types --- mp/game/neo/materials/effects/fpmf/fpmf01.vmt | 8 ++++++ mp/game/neo/materials/effects/fpmf/fpmf02.vmt | 8 ++++++ .../neo_predicted_viewmodel_muzzleflash.cpp | 25 +++++++++++++------ .../neo/neo_predicted_viewmodel_muzzleflash.h | 5 +++- 4 files changed, 37 insertions(+), 9 deletions(-) create mode 100644 mp/game/neo/materials/effects/fpmf/fpmf01.vmt create mode 100644 mp/game/neo/materials/effects/fpmf/fpmf02.vmt diff --git a/mp/game/neo/materials/effects/fpmf/fpmf01.vmt b/mp/game/neo/materials/effects/fpmf/fpmf01.vmt new file mode 100644 index 000000000..4bd04ed73 --- /dev/null +++ b/mp/game/neo/materials/effects/fpmf/fpmf01.vmt @@ -0,0 +1,8 @@ +"UnlitGeneric" +{ + "$basetexture" "effects\fpmf\fpmf01" + "$nocull" 1 + "$additive" 1 + "$model" 1 + "$translucent" 1 +} diff --git a/mp/game/neo/materials/effects/fpmf/fpmf02.vmt b/mp/game/neo/materials/effects/fpmf/fpmf02.vmt new file mode 100644 index 000000000..f097b4916 --- /dev/null +++ b/mp/game/neo/materials/effects/fpmf/fpmf02.vmt @@ -0,0 +1,8 @@ +"UnlitGeneric" +{ + "$basetexture" "effects\fpmf\fpmf02" + "$nocull" 1 + "$additive" 1 + "$model" 1 + "$translucent" 1 +} diff --git a/mp/src/game/shared/neo/neo_predicted_viewmodel_muzzleflash.cpp b/mp/src/game/shared/neo/neo_predicted_viewmodel_muzzleflash.cpp index 93647a165..63c14f4b9 100644 --- a/mp/src/game/shared/neo/neo_predicted_viewmodel_muzzleflash.cpp +++ b/mp/src/game/shared/neo/neo_predicted_viewmodel_muzzleflash.cpp @@ -40,6 +40,11 @@ void CNEOPredictedViewModelMuzzleFlash::Spawn(void) { Precache(); +#ifdef CLIENT_DLL + starFlash = materials->FindMaterial("effects/fpmf/fpmf01.vmt", TEXTURE_GROUP_VIEW_MODEL); + circleFlash = materials->FindMaterial("effects/fpmf/fpmf02.vmt", TEXTURE_GROUP_VIEW_MODEL); +#endif + SetModel(MUZZLE_FLASH_ENTITY_MODEL); SetSolid(SOLID_NONE); SetMoveType(MOVETYPE_NONE); @@ -50,18 +55,22 @@ void CNEOPredictedViewModelMuzzleFlash::Spawn(void) #ifdef CLIENT_DLL int CNEOPredictedViewModelMuzzleFlash::DrawModel(int flags) { - IMaterial* pass = materials->FindMaterial("effects/fpmf/fpmf01.vmt", TEXTURE_GROUP_VIEW_MODEL); if (!ShouldMuzzleFlash()) { - pass->SetMaterialVarFlag(MATERIAL_VAR_NO_DRAW, true); - } - else - { - SetLocalAnglesDim( 1, AngleNormalize(random->RandomInt(-1200, 1200))); - pass->SetMaterialVarFlag(MATERIAL_VAR_NO_DRAW, false); + starFlash = materials->FindMaterial("effects/fpmf/fpmf01.vmt", TEXTURE_GROUP_VIEW_MODEL); + circleFlash = materials->FindMaterial("effects/fpmf/fpmf02.vmt", TEXTURE_GROUP_VIEW_MODEL); + starFlash->SetMaterialVarFlag(MATERIAL_VAR_NO_DRAW, true); + circleFlash->SetMaterialVarFlag(MATERIAL_VAR_NO_DRAW, true); + return 0; } + starFlash = materials->FindMaterial("effects/fpmf/fpmf01.vmt", TEXTURE_GROUP_VIEW_MODEL); + circleFlash = materials->FindMaterial("effects/fpmf/fpmf02.vmt", TEXTURE_GROUP_VIEW_MODEL); DisableMuzzleFlash(); - pass->SetMaterialVarFlag(MATERIAL_VAR_IGNOREZ, true); + starFlash->SetMaterialVarFlag(MATERIAL_VAR_NO_DRAW, false); + starFlash->SetMaterialVarFlag(MATERIAL_VAR_IGNOREZ, true); + circleFlash->SetMaterialVarFlag(MATERIAL_VAR_NO_DRAW, false); + circleFlash->SetMaterialVarFlag(MATERIAL_VAR_IGNOREZ, true); + int ret = BaseClass::DrawModel(flags); return ret; } diff --git a/mp/src/game/shared/neo/neo_predicted_viewmodel_muzzleflash.h b/mp/src/game/shared/neo/neo_predicted_viewmodel_muzzleflash.h index 2e55b3e50..b4398a360 100644 --- a/mp/src/game/shared/neo/neo_predicted_viewmodel_muzzleflash.h +++ b/mp/src/game/shared/neo/neo_predicted_viewmodel_muzzleflash.h @@ -38,8 +38,11 @@ class CNEOPredictedViewModelMuzzleFlash : public CBaseAnimating void Spawn(void); void Precache(void); -private: + IMaterial* selectedFlash; + IMaterial* starFlash; + IMaterial* circleFlash; +private: bool m_bActive; float m_flNextChangeTime; }; From d9c0ef6b1c85e798bd637135fb790bfb26683531 Mon Sep 17 00:00:00 2001 From: AdamTadeusz Date: Fri, 23 Aug 2024 14:22:47 +0100 Subject: [PATCH 04/14] change muzzleflash model depending on gun used --- .../neo_predicted_viewmodel.cpp | 470 ++++++++++++++++++ mp/src/game/shared/baseplayer_shared.cpp | 35 ++ .../shared/neo/neo_predicted_viewmodel.cpp | 15 +- .../neo_predicted_viewmodel_muzzleflash.cpp | 21 +- .../neo/neo_predicted_viewmodel_muzzleflash.h | 7 +- 5 files changed, 522 insertions(+), 26 deletions(-) create mode 100644 mp/src/enc_temp_folder/26d7ac2f0544c4cc6c39cf177d4f3a1/neo_predicted_viewmodel.cpp diff --git a/mp/src/enc_temp_folder/26d7ac2f0544c4cc6c39cf177d4f3a1/neo_predicted_viewmodel.cpp b/mp/src/enc_temp_folder/26d7ac2f0544c4cc6c39cf177d4f3a1/neo_predicted_viewmodel.cpp new file mode 100644 index 000000000..737b9544d --- /dev/null +++ b/mp/src/enc_temp_folder/26d7ac2f0544c4cc6c39cf177d4f3a1/neo_predicted_viewmodel.cpp @@ -0,0 +1,470 @@ +#include "cbase.h" +#include "neo_predicted_viewmodel.h" + +#include "in_buttons.h" +#include "neo_gamerules.h" +#include "weapon_hl2mpbase.h" + +#ifdef CLIENT_DLL +#include "c_neo_player.h" + +#include "engine/ivdebugoverlay.h" +#include "iinput.h" +#include "inetchannelinfo.h" +#include "model_types.h" +#include "prediction.h" +#include "viewrender.h" +#else +#include "neo_player.h" +#endif +#include "neo_predicted_viewmodel_muzzleflash.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + + +IMPLEMENT_NETWORKCLASS_ALIASED(NEOPredictedViewModel, DT_NEOPredictedViewModel) + +BEGIN_NETWORK_TABLE(CNEOPredictedViewModel, DT_NEOPredictedViewModel) +#ifdef CLIENT_DLL +RecvPropFloat(RECVINFO(m_flYPrevious)), +#else +SendPropFloat(SENDINFO(m_flYPrevious)), +#endif +END_NETWORK_TABLE() + +#ifdef CLIENT_DLL +BEGIN_PREDICTION_DATA(CNEOPredictedViewModel) +DEFINE_PRED_FIELD(m_flYPrevious, FIELD_FLOAT, FTYPEDESC_INSENDTABLE), +END_PREDICTION_DATA() +#endif + +LINK_ENTITY_TO_CLASS(neo_predicted_viewmodel, CNEOPredictedViewModel); + +CNEOPredictedViewModel::CNEOPredictedViewModel() +#ifdef CLIENT_DLL + : m_iv_flYPrevious("CNEOPredictedViewModel::m_iv_flYPrevious") +#endif +{ +#ifdef CLIENT_DLL +#ifdef DEBUG + IMaterial *pass = materials->FindMaterial("dev/toc_cloakpass", TEXTURE_GROUP_CLIENT_EFFECTS); + Assert(pass && pass->IsPrecached()); +#endif + + AddVar(&m_flYPrevious, &m_iv_flYPrevious, LATCH_SIMULATION_VAR); +#endif + + m_flYPrevious = 0; + m_flStartAimingChange = 0; + m_bViewAim = false; + m_pFirstPersonMuzzleFlash = (CNEOPredictedViewModelMuzzleFlash*)CreateEntityByName("neo_predicted_viewmodel_muzzleflash"); + if (m_pFirstPersonMuzzleFlash) + { + m_pFirstPersonMuzzleFlash->SetOwnerEntity(this); + m_pFirstPersonMuzzleFlash->SetParent(this); + m_pFirstPersonMuzzleFlash->m_bActive = true; +#ifdef GAME_DLL +#else + m_pFirstPersonMuzzleFlash->SpawnClientEntity(); + m_pFirstPersonMuzzleFlash->SetModelScale(1); + m_pFirstPersonMuzzleFlash->flash[0] = materials->FindMaterial("effects/fpmf/fpmf01.vmt", TEXTURE_GROUP_VIEW_MODEL); + m_pFirstPersonMuzzleFlash->flash[1] = materials->FindMaterial("effects/fpmf/fpmf02.vmt", TEXTURE_GROUP_VIEW_MODEL); + m_pFirstPersonMuzzleFlash->flash[0]->SetMaterialVarFlag(MATERIAL_VAR_IGNOREZ, true); + m_pFirstPersonMuzzleFlash->flash[1]->SetMaterialVarFlag(MATERIAL_VAR_IGNOREZ, true); + clienttools->SetRenderGroup(m_pFirstPersonMuzzleFlash, RENDER_GROUP_VIEW_MODEL_OPAQUE); +#endif + } +} + +CNEOPredictedViewModel::~CNEOPredictedViewModel() +{ +} + +#ifdef CLIENT_DLL +void CNEOPredictedViewModel::DrawRenderToTextureDebugInfo(IClientRenderable* pRenderable, + const Vector& mins, const Vector& maxs, const Vector &rgbColor, + const char *message, const Vector &vecOrigin) +{ + // Get the object's basis + Vector vec[3]; + AngleVectors( pRenderable->GetRenderAngles(), &vec[0], &vec[1], &vec[2] ); + vec[1] *= -1.0f; + + Vector vecSize; + VectorSubtract( maxs, mins, vecSize ); + + //Vector vecOrigin = pRenderable->GetRenderOrigin() + renderOffset; + Vector start, end, end2; + + VectorMA( vecOrigin, mins.x, vec[0], start ); + VectorMA( start, mins.y, vec[1], start ); + VectorMA( start, mins.z, vec[2], start ); + + VectorMA( start, vecSize.x, vec[0], end ); + VectorMA( end, vecSize.z, vec[2], end2 ); + + const float duration = 0.01f; + const bool noDepthTest = true; + + debugoverlay->AddLineOverlay( start, end, rgbColor[0], rgbColor[1], rgbColor[2], noDepthTest, duration); + debugoverlay->AddLineOverlay( end2, end, rgbColor[0], rgbColor[1], rgbColor[2], noDepthTest, duration); + + VectorMA( start, vecSize.y, vec[1], end ); + VectorMA( end, vecSize.z, vec[2], end2 ); + debugoverlay->AddLineOverlay( start, end, rgbColor[0], rgbColor[1], rgbColor[2], noDepthTest, duration); + debugoverlay->AddLineOverlay( end2, end, rgbColor[0], rgbColor[1], rgbColor[2], noDepthTest, duration); + + VectorMA( start, vecSize.z, vec[2], end ); + debugoverlay->AddLineOverlay( start, end, rgbColor[0], rgbColor[1], rgbColor[2], noDepthTest, duration); + + start = end; + VectorMA( start, vecSize.x, vec[0], end ); + debugoverlay->AddLineOverlay( start, end, rgbColor[0], rgbColor[1], rgbColor[2], noDepthTest, duration); + + VectorMA( start, vecSize.y, vec[1], end ); + debugoverlay->AddLineOverlay( start, end, rgbColor[0], rgbColor[1], rgbColor[2], noDepthTest, duration); + + VectorMA( end, vecSize.x, vec[0], start ); + VectorMA( start, -vecSize.x, vec[0], end ); + debugoverlay->AddLineOverlay( start, end, rgbColor[0], rgbColor[1], rgbColor[2], noDepthTest, duration); + + VectorMA( start, -vecSize.y, vec[1], end ); + debugoverlay->AddLineOverlay( start, end, rgbColor[0], rgbColor[1], rgbColor[2], noDepthTest, duration); + + VectorMA( start, -vecSize.z, vec[2], end ); + debugoverlay->AddLineOverlay( start, end, rgbColor[0], rgbColor[1], rgbColor[2], noDepthTest, duration); + + start = end; + VectorMA( start, -vecSize.x, vec[0], end ); + debugoverlay->AddLineOverlay( start, end, rgbColor[0], rgbColor[1], rgbColor[2], noDepthTest, duration); + + VectorMA( start, -vecSize.y, vec[1], end ); + debugoverlay->AddLineOverlay( start, end, rgbColor[0], rgbColor[1], rgbColor[2], noDepthTest, duration); + + C_BaseEntity *pEnt = pRenderable->GetIClientUnknown()->GetBaseEntity(); + int lineOffset = V_stristr("end", message) ? 1 : 0; + if ( pEnt ) + { + debugoverlay->AddTextOverlay( vecOrigin, lineOffset, "%s -- ent %d", message, pEnt->entindex() ); + } + else + { + debugoverlay->AddTextOverlay( vecOrigin, lineOffset, "%s -- renderable %X", message, (size_t)pRenderable ); + } +} +#endif + +ConVar neo_lean_debug_draw_hull("neo_lean_debug_draw_hull", "0", FCVAR_CHEAT | FCVAR_REPLICATED); +ConVar neo_lean_speed("neo_lean_speed", "0.333", FCVAR_REPLICATED | FCVAR_CHEAT, "Lean speed scale", true, 0.0, false, 1000.0); +// Original Neotokyo with the latest leftlean fix uses 7 for leftlean and 15 for rightlean yaw slide. +ConVar neo_lean_yaw_peek_left_amount("neo_lean_yaw_peek_left_amount", "7.0", FCVAR_REPLICATED | FCVAR_CHEAT, "How far sideways will a full left lean view reach.", true, 0.001f, false, 0); +ConVar neo_lean_yaw_peek_right_amount("neo_lean_yaw_peek_right_amount", "15.0", FCVAR_REPLICATED | FCVAR_CHEAT, "How far sideways will a full right lean view reach.", true, 0.001f, false, 0); +ConVar neo_lean_angle_percentage("neo_lean_angle_percentage", "0.75", FCVAR_REPLICATED | FCVAR_CHEAT, "for adjusting the actual angle of lean to a percentage of lean.", true, 0.0, true, 1.0); +ConVar neo_lean_tp_exaggerate_scale("neo_lean_tp_exaggerate_scale", "2", FCVAR_REPLICATED | FCVAR_CHEAT, "How much more to scale leaning motion in 3rd person animation vs 1st person viewmodel.", true, 0.0, false, 0); +ConVar neo_lean_fp_lower_eyes_scale("neo_lean_fp_lower_eyes_scale", "2.333", FCVAR_REPLICATED | FCVAR_CHEAT, "Multiplier for how low to bring eye-level (and hence bullet line level) whilst leaning.", true, 0.0, false, 0); + +#if(0) +ConVar neo_lean_thirdperson_roll_lerp_scale("neo_lean_thirdperson_roll_lerp_scale", "5", + FCVAR_REPLICATED | FCVAR_CHEAT, "Multiplier for 3rd person lean roll lerping.", true, 0.0, false, 0); +#endif + +float CNEOPredictedViewModel::freeRoomForLean(float leanAmount, CNEO_Player *player){ + const Vector playerDefaultViewPos = player->GetAbsOrigin(); + Vector deltaPlayerViewPos(0, leanAmount, 0); + VectorYawRotate(deltaPlayerViewPos, player->LocalEyeAngles().y, deltaPlayerViewPos); + const Vector leanEndPos = playerDefaultViewPos + deltaPlayerViewPos; + + // We can only lean through stuff that isn't solid for us + CTraceFilterNoNPCsOrPlayer filter(player, COLLISION_GROUP_PLAYER_MOVEMENT); + + // Player hull size, dependent on current ducking status + Vector hullMins, hullMaxs; + // Need this much z clearance to not "bump" our head whilst leaning + const Vector groundClearance(0, 0, 30); + +#if(0) // same view limits regardless of player class +#define STAND_MINS (NEORules()->GetViewVectors()->m_vHullMin + groundClearance) +#define STAND_MAXS (NEORules()->GetViewVectors()->m_vHullMax) +#define DUCK_MINS (NEORules()->GetViewVectors()->m_vDuckHullMin + groundClearance) +#define DUCK_MAXS (NEORules()->GetViewVectors()->m_vDuckHullMax) +#else // class hull specific limits +#define STAND_MINS (VEC_HULL_MIN_SCALED(player) + groundClearance) +#define STAND_MAXS (VEC_HULL_MAX_SCALED(player)) +#define DUCK_MINS (VEC_DUCK_HULL_MIN_SCALED(player) + groundClearance) +#define DUCK_MAXS (VEC_DUCK_HULL_MAX_SCALED(player)) +#endif + + if (player->GetFlags() & FL_DUCKING) + { + hullMins = DUCK_MINS; + hullMaxs = DUCK_MAXS; + } + else + { + hullMins = STAND_MINS; + hullMaxs = STAND_MAXS; + } + + Assert(hullMins.IsValid() && hullMaxs.IsValid()); + + trace_t trace; + UTIL_TraceHull(playerDefaultViewPos, leanEndPos, hullMins, hullMaxs, player->PhysicsSolidMaskForEntity(), &filter, &trace); + +#ifdef CLIENT_DLL + if (neo_lean_debug_draw_hull.GetBool()) + { + // Z offset to avoid text overlap; DrawRenderToTextureDebugInfo will also want to print text around similar area. + const Vector debugOffset = Vector(playerDefaultViewPos) + Vector(0, 0, -4); + const Vector color = Vector(20, 255, 0); + debugoverlay->AddTextOverlay(debugOffset, 0.0001, "x: %f\n y: %f\n z:%f\n", playerDefaultViewPos.x, playerDefaultViewPos.y, playerDefaultViewPos.z); + player->GetNEOViewModel()->DrawRenderToTextureDebugInfo(player, hullMins, hullMaxs, color, "freeRoomForLean", player->GetAbsOrigin()); + } +#endif + + return roundf(trace.startpos.DistTo(trace.endpos) * 100) / 100; +} + +#ifdef CLIENT_DLL +void CNEOPredictedViewModel::PostDataUpdate(DataUpdateType_t updateType) +{ + SetNextClientThink(CLIENT_THINK_ALWAYS); + BaseClass::PostDataUpdate(updateType); +} + +void CNEOPredictedViewModel::ClientThink() +{ + SetNextClientThink(CLIENT_THINK_ALWAYS); + BaseClass::ClientThink(); +} + +int CNEOPredictedViewModel::DrawModel(int flags) +{ + auto pPlayer = static_cast(GetOwner()); + + if (pPlayer) + { + if (pPlayer->IsCloaked()) + { + IMaterial *pass = materials->FindMaterial("dev/toc_vm", TEXTURE_GROUP_VIEW_MODEL); + Assert(pass && !pass->IsErrorMaterial()); + + if (pass && !pass->IsErrorMaterial()) + { + if (!pass->IsPrecached()) + { + PrecacheMaterial(pass->GetName()); + Assert(pass->IsPrecached()); + } + + //modelrender->SuppressEngineLighting(true); + modelrender->ForcedMaterialOverride(pass); + int ret = BaseClass::DrawModel(flags /*| STUDIO_RENDER | STUDIO_DRAWTRANSLUCENTSUBMODELS | STUDIO_TRANSPARENCY*/); + //modelrender->SuppressEngineLighting(false); + modelrender->ForcedMaterialOverride(NULL); + return ret; + } + + return 0; + } + } + + return BaseClass::DrawModel(flags); +} +#endif + +static inline float calculateLeanAngle(float freeRoom, CNEO_Player *player){ +#define HIP_TO_HEAD_HEIGHT 41.0f + return -RAD2DEG(atan2(freeRoom, HIP_TO_HEAD_HEIGHT)) * neo_lean_angle_percentage.GetFloat(); +} + +float GetLeanRatio(const float leanAngle) +{ + return fabs(leanAngle) / ((leanAngle < 0) ? neo_lean_yaw_peek_left_amount.GetFloat() : neo_lean_yaw_peek_right_amount.GetFloat()); +} + +float CNEOPredictedViewModel::lean(CNEO_Player *player){ + Assert(player); +#ifdef CLIENT_DLL + input->ExtraMouseSample(gpGlobals->frametime, 1); +#endif + QAngle viewAng = player->LocalEyeAngles(); + float Ycurrent = m_flYPrevious; + float Yfinal = 0; + + if (player->IsAlive()) + { + switch (player->m_bInLean.Get()) + { + case NEO_LEAN_LEFT: + Yfinal = freeRoomForLean(neo_lean_yaw_peek_left_amount.GetFloat(), player); + break; + case NEO_LEAN_RIGHT: + Yfinal = -freeRoomForLean(-neo_lean_yaw_peek_right_amount.GetFloat(), player); + break; + default: + // not leaning, or leaning both ways; move towards zero + break; + } + } + + if (!(player->GetFlags() & FL_ONGROUND)) { + //mid-air; move towards zero + Yfinal = 0; + } + + const float dY = Yfinal - Ycurrent; + + + if (dY != 0){ + const float leanStep = 0.25f; + + // Almost done leaning; snap to zero to avoid back-and-forth "wiggle" + if (fabs(dY) - leanStep < 0) { + Ycurrent = Yfinal; + } + else { + Ycurrent = Lerp(leanStep * neo_lean_speed.GetFloat(), Ycurrent, Yfinal); + } + } + + Vector viewOffset(0, 0, 0); + viewOffset.y = m_flYPrevious = Ycurrent; + + VectorYawRotate(viewOffset, viewAng.y, viewOffset); + + float leanAngle = calculateLeanAngle(Ycurrent, player); + + const float leanRatio = GetLeanRatio(leanAngle); + + viewOffset.z = ((player->GetFlags() & FL_DUCKING) ? (VEC_DUCK_VIEW_SCALED(player).z) : VEC_VIEW_SCALED(player).z) - (neo_lean_fp_lower_eyes_scale.GetFloat() * leanRatio); + + player->m_vecLean = Vector(0, viewOffset.y, -(neo_lean_fp_lower_eyes_scale.GetFloat() * leanRatio)); + player->SetViewOffset(viewOffset); + + viewAng.z = leanAngle; +#ifdef CLIENT_DLL + engine->SetViewAngles(viewAng); +#endif + +#ifdef GAME_DLL + SetSimulationTime(gpGlobals->curtime); + SetNextThink(gpGlobals->curtime); +#endif + + if (leanAngle >= 0) + { + return leanAngle * neo_lean_tp_exaggerate_scale.GetFloat(); + } + else + { + const float leftleanOverleanRatio = (neo_lean_yaw_peek_right_amount.GetFloat() / neo_lean_yaw_peek_left_amount.GetFloat()); + return leanAngle * neo_lean_tp_exaggerate_scale.GetFloat() * leftleanOverleanRatio; + } +} + +void CNEOPredictedViewModel::CalcViewModelView(CBasePlayer *pOwner, + const Vector& eyePosition, const QAngle& eyeAngles) +{ + if (pOwner->GetObserverMode() == OBS_MODE_IN_EYE) + { + if (auto *pTargetPlayer = dynamic_cast(pOwner->GetObserverTarget()); + pTargetPlayer && !pTargetPlayer->IsObserver()) + { + // NEO NOTE (nullsystem): 1st person mode pOwner = pTargetPlayer eye position + // Take the target player's viewmodel FOV instead, otherwise it'll just look like it doesn't + // change viewmodel FOV on 1st spectate + return CalcViewModelView(pTargetPlayer, eyePosition, eyeAngles); + } + } + + // Is there a nicer way to do this? + auto weapon = static_cast(GetOwningWeapon()); + + if (!weapon) + { + return; + } + +#ifdef GAME_DLL + if (LookupAttachment("Muzzle") > 0) + { + if (m_pFirstPersonMuzzleFlash) { + m_pFirstPersonMuzzleFlash->SetParent(this); + m_pFirstPersonMuzzleFlash->SetParentAttachment("SetParentAttachment", "Muzzle", false); + } + } +#endif + + CHL2MPSWeaponInfo data = weapon->GetHL2MPWpnData(); + + Vector vForward, vRight, vUp, newPos, vOffset; + QAngle newAng, angOffset; + + newAng = eyeAngles; + newPos = eyePosition; + + AngleVectors(newAng, &vForward, &vRight, &vUp); + + if (auto neoPlayer = static_cast(pOwner)) + { + vOffset = m_vOffset; + angOffset = m_angOffset; +#ifdef CLIENT_DLL + if (!prediction->InPrediction()) +#endif + { + const bool playerAiming = neoPlayer->IsInAim(); + const float currentTime = gpGlobals->curtime; + if (m_bViewAim && !playerAiming) + { + // From aiming to not aiming + m_flStartAimingChange = currentTime; + m_bViewAim = false; + } + else if (!m_bViewAim && playerAiming) + { + // From not aiming to aiming + m_flStartAimingChange = currentTime; + m_bViewAim = true; + } + const float endAimingChange = m_flStartAimingChange + NEO_ZOOM_SPEED; + const bool inAimingChange = (m_flStartAimingChange <= currentTime && currentTime < endAimingChange); + if (inAimingChange) + { + float percentage = clamp((currentTime - m_flStartAimingChange) / NEO_ZOOM_SPEED, 0.0f, 1.0f); + if (playerAiming) percentage = 1.0f - percentage; + vOffset = Lerp(percentage, data.m_vecVMAimPosOffset, data.m_vecVMPosOffset); + angOffset = Lerp(percentage, data.m_angVMAimAngOffset, data.m_angVMAngOffset); + } + else + { + vOffset = (playerAiming) ? data.m_vecVMAimPosOffset : data.m_vecVMPosOffset; + angOffset = (playerAiming) ? data.m_angVMAimAngOffset : data.m_angVMAngOffset; + } + m_vOffset = vOffset; + m_angOffset = angOffset; + } + } + + newPos += vForward * vOffset.x; + newPos += vRight * vOffset.y; + newPos += vUp * vOffset.z; + + newAng += angOffset; + + BaseClass::CalcViewModelView(pOwner, newPos, newAng); +} + +#ifdef CLIENT_DLL +RenderGroup_t CNEOPredictedViewModel::GetRenderGroup() +{ + auto pPlayer = static_cast(GetOwner()); + if (pPlayer) + { + return pPlayer->IsCloaked() ? RENDER_GROUP_VIEW_MODEL_TRANSLUCENT : RENDER_GROUP_VIEW_MODEL_OPAQUE; + } + + return BaseClass::GetRenderGroup(); +} +#endif diff --git a/mp/src/game/shared/baseplayer_shared.cpp b/mp/src/game/shared/baseplayer_shared.cpp index 62a30b9e8..bbeefb36f 100644 --- a/mp/src/game/shared/baseplayer_shared.cpp +++ b/mp/src/game/shared/baseplayer_shared.cpp @@ -53,6 +53,7 @@ #ifdef NEO #include "neo_gamerules.h" +#include "weapon_neobasecombatweapon.h" #ifdef GAME_DLL #include "neo_player.h" #else @@ -890,6 +891,40 @@ bool CBasePlayer::Weapon_Switch( CBaseCombatWeapon *pWeapon, int viewmodelindex if ( pViewModel ) pViewModel->RemoveEffects( EF_NODRAW ); ResetAutoaim( ); + +#ifdef NEO + auto neoWep = static_cast(pWeapon); + CNEOPredictedViewModel* neoViewModel = static_cast(m_hViewModel[0].Get()); + if (neoViewModel->m_pFirstPersonMuzzleFlash) + { + if (neoWep->GetNeoWepBits() & NEO_WEP_SUPPRESSED) + { + neoViewModel->m_pFirstPersonMuzzleFlash->m_bActive = false; + } + else if (neoWep->GetNeoWepBits() & (NEO_WEP_PZ | NEO_WEP_TACHI)) + { + neoViewModel->m_pFirstPersonMuzzleFlash->m_bActive = true; + neoViewModel->m_pFirstPersonMuzzleFlash->selectedFlash = 1; + neoViewModel->m_pFirstPersonMuzzleFlash->m_nSkin = 1; + //neoViewModel->m_pFirstPersonMuzzleFlash->SetModelScale(1); + } + else if (neoWep->GetNeoWepBits() & NEO_WEP_SUPA7) + { + neoViewModel->m_pFirstPersonMuzzleFlash->m_bActive = true; + neoViewModel->m_pFirstPersonMuzzleFlash->selectedFlash = 0; + neoViewModel->m_pFirstPersonMuzzleFlash->m_nSkin = 0; + //neoViewModel->m_pFirstPersonMuzzleFlash->SetModelScale(1.5); + } + else + { + neoViewModel->m_pFirstPersonMuzzleFlash->m_bActive = true; + neoViewModel->m_pFirstPersonMuzzleFlash->selectedFlash = 0; + neoViewModel->m_pFirstPersonMuzzleFlash->m_nSkin = 0; + //neoViewModel->m_pFirstPersonMuzzleFlash->SetModelScale(1); + } + } +#endif // NEO + return true; } return false; diff --git a/mp/src/game/shared/neo/neo_predicted_viewmodel.cpp b/mp/src/game/shared/neo/neo_predicted_viewmodel.cpp index 5f60a9284..1c99a2e3a 100644 --- a/mp/src/game/shared/neo/neo_predicted_viewmodel.cpp +++ b/mp/src/game/shared/neo/neo_predicted_viewmodel.cpp @@ -63,10 +63,15 @@ CNEOPredictedViewModel::CNEOPredictedViewModel() { m_pFirstPersonMuzzleFlash->SetOwnerEntity(this); m_pFirstPersonMuzzleFlash->SetParent(this); - m_pFirstPersonMuzzleFlash->SetModelScale(1); + m_pFirstPersonMuzzleFlash->m_bActive = true; #ifdef GAME_DLL - m_pFirstPersonMuzzleFlash->Spawn(); + DispatchSpawn(m_pFirstPersonMuzzleFlash); #else + m_pFirstPersonMuzzleFlash->SetModelScale(1); + m_pFirstPersonMuzzleFlash->flash[0] = materials->FindMaterial("effects/fpmf/fpmf01.vmt", TEXTURE_GROUP_VIEW_MODEL); + m_pFirstPersonMuzzleFlash->flash[1] = materials->FindMaterial("effects/fpmf/fpmf02.vmt", TEXTURE_GROUP_VIEW_MODEL); + m_pFirstPersonMuzzleFlash->flash[0]->SetMaterialVarFlag(MATERIAL_VAR_IGNOREZ, true); + m_pFirstPersonMuzzleFlash->flash[1]->SetMaterialVarFlag(MATERIAL_VAR_IGNOREZ, true); clienttools->SetRenderGroup(m_pFirstPersonMuzzleFlash, RENDER_GROUP_VIEW_MODEL_OPAQUE); #endif } @@ -384,8 +389,10 @@ void CNEOPredictedViewModel::CalcViewModelView(CBasePlayer *pOwner, #ifdef GAME_DLL if (LookupAttachment("Muzzle") > 0) { - m_pFirstPersonMuzzleFlash->SetParent(this); - m_pFirstPersonMuzzleFlash->SetParentAttachment("SetParentAttachment", "Muzzle", false); + if (m_pFirstPersonMuzzleFlash) { + m_pFirstPersonMuzzleFlash->SetParent(this); + m_pFirstPersonMuzzleFlash->SetParentAttachment("SetParentAttachment", "Muzzle", false); + } } #endif diff --git a/mp/src/game/shared/neo/neo_predicted_viewmodel_muzzleflash.cpp b/mp/src/game/shared/neo/neo_predicted_viewmodel_muzzleflash.cpp index 63c14f4b9..2482ce609 100644 --- a/mp/src/game/shared/neo/neo_predicted_viewmodel_muzzleflash.cpp +++ b/mp/src/game/shared/neo/neo_predicted_viewmodel_muzzleflash.cpp @@ -39,12 +39,6 @@ void CNEOPredictedViewModelMuzzleFlash::Precache(void) void CNEOPredictedViewModelMuzzleFlash::Spawn(void) { Precache(); - -#ifdef CLIENT_DLL - starFlash = materials->FindMaterial("effects/fpmf/fpmf01.vmt", TEXTURE_GROUP_VIEW_MODEL); - circleFlash = materials->FindMaterial("effects/fpmf/fpmf02.vmt", TEXTURE_GROUP_VIEW_MODEL); -#endif - SetModel(MUZZLE_FLASH_ENTITY_MODEL); SetSolid(SOLID_NONE); SetMoveType(MOVETYPE_NONE); @@ -55,22 +49,13 @@ void CNEOPredictedViewModelMuzzleFlash::Spawn(void) #ifdef CLIENT_DLL int CNEOPredictedViewModelMuzzleFlash::DrawModel(int flags) { - if (!ShouldMuzzleFlash()) + if (!ShouldMuzzleFlash() || !m_bActive) { - starFlash = materials->FindMaterial("effects/fpmf/fpmf01.vmt", TEXTURE_GROUP_VIEW_MODEL); - circleFlash = materials->FindMaterial("effects/fpmf/fpmf02.vmt", TEXTURE_GROUP_VIEW_MODEL); - starFlash->SetMaterialVarFlag(MATERIAL_VAR_NO_DRAW, true); - circleFlash->SetMaterialVarFlag(MATERIAL_VAR_NO_DRAW, true); + flash[selectedFlash]->SetMaterialVarFlag(MATERIAL_VAR_NO_DRAW, true); return 0; } - starFlash = materials->FindMaterial("effects/fpmf/fpmf01.vmt", TEXTURE_GROUP_VIEW_MODEL); - circleFlash = materials->FindMaterial("effects/fpmf/fpmf02.vmt", TEXTURE_GROUP_VIEW_MODEL); DisableMuzzleFlash(); - starFlash->SetMaterialVarFlag(MATERIAL_VAR_NO_DRAW, false); - starFlash->SetMaterialVarFlag(MATERIAL_VAR_IGNOREZ, true); - circleFlash->SetMaterialVarFlag(MATERIAL_VAR_NO_DRAW, false); - circleFlash->SetMaterialVarFlag(MATERIAL_VAR_IGNOREZ, true); - + flash[selectedFlash]->SetMaterialVarFlag(MATERIAL_VAR_NO_DRAW, false); int ret = BaseClass::DrawModel(flags); return ret; } diff --git a/mp/src/game/shared/neo/neo_predicted_viewmodel_muzzleflash.h b/mp/src/game/shared/neo/neo_predicted_viewmodel_muzzleflash.h index b4398a360..a823402cb 100644 --- a/mp/src/game/shared/neo/neo_predicted_viewmodel_muzzleflash.h +++ b/mp/src/game/shared/neo/neo_predicted_viewmodel_muzzleflash.h @@ -38,12 +38,11 @@ class CNEOPredictedViewModelMuzzleFlash : public CBaseAnimating void Spawn(void); void Precache(void); - IMaterial* selectedFlash; - IMaterial* starFlash; - IMaterial* circleFlash; + int selectedFlash; + IMaterial* flash[2]; -private: bool m_bActive; +private: float m_flNextChangeTime; }; From 622c94ff0eddce0090bb429d6f484f77367faabc Mon Sep 17 00:00:00 2001 From: AdamTadeusz Date: Sun, 25 Aug 2024 15:10:55 +0100 Subject: [PATCH 05/14] using a viewmodel instead of a baseanimatingentity --- .../neo_predicted_viewmodel.cpp | 470 ------------------ mp/src/game/server/neo/neo_player.cpp | 21 + mp/src/game/shared/baseplayer_shared.cpp | 27 +- .../shared/neo/neo_predicted_viewmodel.cpp | 27 - .../game/shared/neo/neo_predicted_viewmodel.h | 9 - .../neo_predicted_viewmodel_muzzleflash.cpp | 49 +- .../neo/neo_predicted_viewmodel_muzzleflash.h | 34 +- 7 files changed, 79 insertions(+), 558 deletions(-) delete mode 100644 mp/src/enc_temp_folder/26d7ac2f0544c4cc6c39cf177d4f3a1/neo_predicted_viewmodel.cpp diff --git a/mp/src/enc_temp_folder/26d7ac2f0544c4cc6c39cf177d4f3a1/neo_predicted_viewmodel.cpp b/mp/src/enc_temp_folder/26d7ac2f0544c4cc6c39cf177d4f3a1/neo_predicted_viewmodel.cpp deleted file mode 100644 index 737b9544d..000000000 --- a/mp/src/enc_temp_folder/26d7ac2f0544c4cc6c39cf177d4f3a1/neo_predicted_viewmodel.cpp +++ /dev/null @@ -1,470 +0,0 @@ -#include "cbase.h" -#include "neo_predicted_viewmodel.h" - -#include "in_buttons.h" -#include "neo_gamerules.h" -#include "weapon_hl2mpbase.h" - -#ifdef CLIENT_DLL -#include "c_neo_player.h" - -#include "engine/ivdebugoverlay.h" -#include "iinput.h" -#include "inetchannelinfo.h" -#include "model_types.h" -#include "prediction.h" -#include "viewrender.h" -#else -#include "neo_player.h" -#endif -#include "neo_predicted_viewmodel_muzzleflash.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - - -IMPLEMENT_NETWORKCLASS_ALIASED(NEOPredictedViewModel, DT_NEOPredictedViewModel) - -BEGIN_NETWORK_TABLE(CNEOPredictedViewModel, DT_NEOPredictedViewModel) -#ifdef CLIENT_DLL -RecvPropFloat(RECVINFO(m_flYPrevious)), -#else -SendPropFloat(SENDINFO(m_flYPrevious)), -#endif -END_NETWORK_TABLE() - -#ifdef CLIENT_DLL -BEGIN_PREDICTION_DATA(CNEOPredictedViewModel) -DEFINE_PRED_FIELD(m_flYPrevious, FIELD_FLOAT, FTYPEDESC_INSENDTABLE), -END_PREDICTION_DATA() -#endif - -LINK_ENTITY_TO_CLASS(neo_predicted_viewmodel, CNEOPredictedViewModel); - -CNEOPredictedViewModel::CNEOPredictedViewModel() -#ifdef CLIENT_DLL - : m_iv_flYPrevious("CNEOPredictedViewModel::m_iv_flYPrevious") -#endif -{ -#ifdef CLIENT_DLL -#ifdef DEBUG - IMaterial *pass = materials->FindMaterial("dev/toc_cloakpass", TEXTURE_GROUP_CLIENT_EFFECTS); - Assert(pass && pass->IsPrecached()); -#endif - - AddVar(&m_flYPrevious, &m_iv_flYPrevious, LATCH_SIMULATION_VAR); -#endif - - m_flYPrevious = 0; - m_flStartAimingChange = 0; - m_bViewAim = false; - m_pFirstPersonMuzzleFlash = (CNEOPredictedViewModelMuzzleFlash*)CreateEntityByName("neo_predicted_viewmodel_muzzleflash"); - if (m_pFirstPersonMuzzleFlash) - { - m_pFirstPersonMuzzleFlash->SetOwnerEntity(this); - m_pFirstPersonMuzzleFlash->SetParent(this); - m_pFirstPersonMuzzleFlash->m_bActive = true; -#ifdef GAME_DLL -#else - m_pFirstPersonMuzzleFlash->SpawnClientEntity(); - m_pFirstPersonMuzzleFlash->SetModelScale(1); - m_pFirstPersonMuzzleFlash->flash[0] = materials->FindMaterial("effects/fpmf/fpmf01.vmt", TEXTURE_GROUP_VIEW_MODEL); - m_pFirstPersonMuzzleFlash->flash[1] = materials->FindMaterial("effects/fpmf/fpmf02.vmt", TEXTURE_GROUP_VIEW_MODEL); - m_pFirstPersonMuzzleFlash->flash[0]->SetMaterialVarFlag(MATERIAL_VAR_IGNOREZ, true); - m_pFirstPersonMuzzleFlash->flash[1]->SetMaterialVarFlag(MATERIAL_VAR_IGNOREZ, true); - clienttools->SetRenderGroup(m_pFirstPersonMuzzleFlash, RENDER_GROUP_VIEW_MODEL_OPAQUE); -#endif - } -} - -CNEOPredictedViewModel::~CNEOPredictedViewModel() -{ -} - -#ifdef CLIENT_DLL -void CNEOPredictedViewModel::DrawRenderToTextureDebugInfo(IClientRenderable* pRenderable, - const Vector& mins, const Vector& maxs, const Vector &rgbColor, - const char *message, const Vector &vecOrigin) -{ - // Get the object's basis - Vector vec[3]; - AngleVectors( pRenderable->GetRenderAngles(), &vec[0], &vec[1], &vec[2] ); - vec[1] *= -1.0f; - - Vector vecSize; - VectorSubtract( maxs, mins, vecSize ); - - //Vector vecOrigin = pRenderable->GetRenderOrigin() + renderOffset; - Vector start, end, end2; - - VectorMA( vecOrigin, mins.x, vec[0], start ); - VectorMA( start, mins.y, vec[1], start ); - VectorMA( start, mins.z, vec[2], start ); - - VectorMA( start, vecSize.x, vec[0], end ); - VectorMA( end, vecSize.z, vec[2], end2 ); - - const float duration = 0.01f; - const bool noDepthTest = true; - - debugoverlay->AddLineOverlay( start, end, rgbColor[0], rgbColor[1], rgbColor[2], noDepthTest, duration); - debugoverlay->AddLineOverlay( end2, end, rgbColor[0], rgbColor[1], rgbColor[2], noDepthTest, duration); - - VectorMA( start, vecSize.y, vec[1], end ); - VectorMA( end, vecSize.z, vec[2], end2 ); - debugoverlay->AddLineOverlay( start, end, rgbColor[0], rgbColor[1], rgbColor[2], noDepthTest, duration); - debugoverlay->AddLineOverlay( end2, end, rgbColor[0], rgbColor[1], rgbColor[2], noDepthTest, duration); - - VectorMA( start, vecSize.z, vec[2], end ); - debugoverlay->AddLineOverlay( start, end, rgbColor[0], rgbColor[1], rgbColor[2], noDepthTest, duration); - - start = end; - VectorMA( start, vecSize.x, vec[0], end ); - debugoverlay->AddLineOverlay( start, end, rgbColor[0], rgbColor[1], rgbColor[2], noDepthTest, duration); - - VectorMA( start, vecSize.y, vec[1], end ); - debugoverlay->AddLineOverlay( start, end, rgbColor[0], rgbColor[1], rgbColor[2], noDepthTest, duration); - - VectorMA( end, vecSize.x, vec[0], start ); - VectorMA( start, -vecSize.x, vec[0], end ); - debugoverlay->AddLineOverlay( start, end, rgbColor[0], rgbColor[1], rgbColor[2], noDepthTest, duration); - - VectorMA( start, -vecSize.y, vec[1], end ); - debugoverlay->AddLineOverlay( start, end, rgbColor[0], rgbColor[1], rgbColor[2], noDepthTest, duration); - - VectorMA( start, -vecSize.z, vec[2], end ); - debugoverlay->AddLineOverlay( start, end, rgbColor[0], rgbColor[1], rgbColor[2], noDepthTest, duration); - - start = end; - VectorMA( start, -vecSize.x, vec[0], end ); - debugoverlay->AddLineOverlay( start, end, rgbColor[0], rgbColor[1], rgbColor[2], noDepthTest, duration); - - VectorMA( start, -vecSize.y, vec[1], end ); - debugoverlay->AddLineOverlay( start, end, rgbColor[0], rgbColor[1], rgbColor[2], noDepthTest, duration); - - C_BaseEntity *pEnt = pRenderable->GetIClientUnknown()->GetBaseEntity(); - int lineOffset = V_stristr("end", message) ? 1 : 0; - if ( pEnt ) - { - debugoverlay->AddTextOverlay( vecOrigin, lineOffset, "%s -- ent %d", message, pEnt->entindex() ); - } - else - { - debugoverlay->AddTextOverlay( vecOrigin, lineOffset, "%s -- renderable %X", message, (size_t)pRenderable ); - } -} -#endif - -ConVar neo_lean_debug_draw_hull("neo_lean_debug_draw_hull", "0", FCVAR_CHEAT | FCVAR_REPLICATED); -ConVar neo_lean_speed("neo_lean_speed", "0.333", FCVAR_REPLICATED | FCVAR_CHEAT, "Lean speed scale", true, 0.0, false, 1000.0); -// Original Neotokyo with the latest leftlean fix uses 7 for leftlean and 15 for rightlean yaw slide. -ConVar neo_lean_yaw_peek_left_amount("neo_lean_yaw_peek_left_amount", "7.0", FCVAR_REPLICATED | FCVAR_CHEAT, "How far sideways will a full left lean view reach.", true, 0.001f, false, 0); -ConVar neo_lean_yaw_peek_right_amount("neo_lean_yaw_peek_right_amount", "15.0", FCVAR_REPLICATED | FCVAR_CHEAT, "How far sideways will a full right lean view reach.", true, 0.001f, false, 0); -ConVar neo_lean_angle_percentage("neo_lean_angle_percentage", "0.75", FCVAR_REPLICATED | FCVAR_CHEAT, "for adjusting the actual angle of lean to a percentage of lean.", true, 0.0, true, 1.0); -ConVar neo_lean_tp_exaggerate_scale("neo_lean_tp_exaggerate_scale", "2", FCVAR_REPLICATED | FCVAR_CHEAT, "How much more to scale leaning motion in 3rd person animation vs 1st person viewmodel.", true, 0.0, false, 0); -ConVar neo_lean_fp_lower_eyes_scale("neo_lean_fp_lower_eyes_scale", "2.333", FCVAR_REPLICATED | FCVAR_CHEAT, "Multiplier for how low to bring eye-level (and hence bullet line level) whilst leaning.", true, 0.0, false, 0); - -#if(0) -ConVar neo_lean_thirdperson_roll_lerp_scale("neo_lean_thirdperson_roll_lerp_scale", "5", - FCVAR_REPLICATED | FCVAR_CHEAT, "Multiplier for 3rd person lean roll lerping.", true, 0.0, false, 0); -#endif - -float CNEOPredictedViewModel::freeRoomForLean(float leanAmount, CNEO_Player *player){ - const Vector playerDefaultViewPos = player->GetAbsOrigin(); - Vector deltaPlayerViewPos(0, leanAmount, 0); - VectorYawRotate(deltaPlayerViewPos, player->LocalEyeAngles().y, deltaPlayerViewPos); - const Vector leanEndPos = playerDefaultViewPos + deltaPlayerViewPos; - - // We can only lean through stuff that isn't solid for us - CTraceFilterNoNPCsOrPlayer filter(player, COLLISION_GROUP_PLAYER_MOVEMENT); - - // Player hull size, dependent on current ducking status - Vector hullMins, hullMaxs; - // Need this much z clearance to not "bump" our head whilst leaning - const Vector groundClearance(0, 0, 30); - -#if(0) // same view limits regardless of player class -#define STAND_MINS (NEORules()->GetViewVectors()->m_vHullMin + groundClearance) -#define STAND_MAXS (NEORules()->GetViewVectors()->m_vHullMax) -#define DUCK_MINS (NEORules()->GetViewVectors()->m_vDuckHullMin + groundClearance) -#define DUCK_MAXS (NEORules()->GetViewVectors()->m_vDuckHullMax) -#else // class hull specific limits -#define STAND_MINS (VEC_HULL_MIN_SCALED(player) + groundClearance) -#define STAND_MAXS (VEC_HULL_MAX_SCALED(player)) -#define DUCK_MINS (VEC_DUCK_HULL_MIN_SCALED(player) + groundClearance) -#define DUCK_MAXS (VEC_DUCK_HULL_MAX_SCALED(player)) -#endif - - if (player->GetFlags() & FL_DUCKING) - { - hullMins = DUCK_MINS; - hullMaxs = DUCK_MAXS; - } - else - { - hullMins = STAND_MINS; - hullMaxs = STAND_MAXS; - } - - Assert(hullMins.IsValid() && hullMaxs.IsValid()); - - trace_t trace; - UTIL_TraceHull(playerDefaultViewPos, leanEndPos, hullMins, hullMaxs, player->PhysicsSolidMaskForEntity(), &filter, &trace); - -#ifdef CLIENT_DLL - if (neo_lean_debug_draw_hull.GetBool()) - { - // Z offset to avoid text overlap; DrawRenderToTextureDebugInfo will also want to print text around similar area. - const Vector debugOffset = Vector(playerDefaultViewPos) + Vector(0, 0, -4); - const Vector color = Vector(20, 255, 0); - debugoverlay->AddTextOverlay(debugOffset, 0.0001, "x: %f\n y: %f\n z:%f\n", playerDefaultViewPos.x, playerDefaultViewPos.y, playerDefaultViewPos.z); - player->GetNEOViewModel()->DrawRenderToTextureDebugInfo(player, hullMins, hullMaxs, color, "freeRoomForLean", player->GetAbsOrigin()); - } -#endif - - return roundf(trace.startpos.DistTo(trace.endpos) * 100) / 100; -} - -#ifdef CLIENT_DLL -void CNEOPredictedViewModel::PostDataUpdate(DataUpdateType_t updateType) -{ - SetNextClientThink(CLIENT_THINK_ALWAYS); - BaseClass::PostDataUpdate(updateType); -} - -void CNEOPredictedViewModel::ClientThink() -{ - SetNextClientThink(CLIENT_THINK_ALWAYS); - BaseClass::ClientThink(); -} - -int CNEOPredictedViewModel::DrawModel(int flags) -{ - auto pPlayer = static_cast(GetOwner()); - - if (pPlayer) - { - if (pPlayer->IsCloaked()) - { - IMaterial *pass = materials->FindMaterial("dev/toc_vm", TEXTURE_GROUP_VIEW_MODEL); - Assert(pass && !pass->IsErrorMaterial()); - - if (pass && !pass->IsErrorMaterial()) - { - if (!pass->IsPrecached()) - { - PrecacheMaterial(pass->GetName()); - Assert(pass->IsPrecached()); - } - - //modelrender->SuppressEngineLighting(true); - modelrender->ForcedMaterialOverride(pass); - int ret = BaseClass::DrawModel(flags /*| STUDIO_RENDER | STUDIO_DRAWTRANSLUCENTSUBMODELS | STUDIO_TRANSPARENCY*/); - //modelrender->SuppressEngineLighting(false); - modelrender->ForcedMaterialOverride(NULL); - return ret; - } - - return 0; - } - } - - return BaseClass::DrawModel(flags); -} -#endif - -static inline float calculateLeanAngle(float freeRoom, CNEO_Player *player){ -#define HIP_TO_HEAD_HEIGHT 41.0f - return -RAD2DEG(atan2(freeRoom, HIP_TO_HEAD_HEIGHT)) * neo_lean_angle_percentage.GetFloat(); -} - -float GetLeanRatio(const float leanAngle) -{ - return fabs(leanAngle) / ((leanAngle < 0) ? neo_lean_yaw_peek_left_amount.GetFloat() : neo_lean_yaw_peek_right_amount.GetFloat()); -} - -float CNEOPredictedViewModel::lean(CNEO_Player *player){ - Assert(player); -#ifdef CLIENT_DLL - input->ExtraMouseSample(gpGlobals->frametime, 1); -#endif - QAngle viewAng = player->LocalEyeAngles(); - float Ycurrent = m_flYPrevious; - float Yfinal = 0; - - if (player->IsAlive()) - { - switch (player->m_bInLean.Get()) - { - case NEO_LEAN_LEFT: - Yfinal = freeRoomForLean(neo_lean_yaw_peek_left_amount.GetFloat(), player); - break; - case NEO_LEAN_RIGHT: - Yfinal = -freeRoomForLean(-neo_lean_yaw_peek_right_amount.GetFloat(), player); - break; - default: - // not leaning, or leaning both ways; move towards zero - break; - } - } - - if (!(player->GetFlags() & FL_ONGROUND)) { - //mid-air; move towards zero - Yfinal = 0; - } - - const float dY = Yfinal - Ycurrent; - - - if (dY != 0){ - const float leanStep = 0.25f; - - // Almost done leaning; snap to zero to avoid back-and-forth "wiggle" - if (fabs(dY) - leanStep < 0) { - Ycurrent = Yfinal; - } - else { - Ycurrent = Lerp(leanStep * neo_lean_speed.GetFloat(), Ycurrent, Yfinal); - } - } - - Vector viewOffset(0, 0, 0); - viewOffset.y = m_flYPrevious = Ycurrent; - - VectorYawRotate(viewOffset, viewAng.y, viewOffset); - - float leanAngle = calculateLeanAngle(Ycurrent, player); - - const float leanRatio = GetLeanRatio(leanAngle); - - viewOffset.z = ((player->GetFlags() & FL_DUCKING) ? (VEC_DUCK_VIEW_SCALED(player).z) : VEC_VIEW_SCALED(player).z) - (neo_lean_fp_lower_eyes_scale.GetFloat() * leanRatio); - - player->m_vecLean = Vector(0, viewOffset.y, -(neo_lean_fp_lower_eyes_scale.GetFloat() * leanRatio)); - player->SetViewOffset(viewOffset); - - viewAng.z = leanAngle; -#ifdef CLIENT_DLL - engine->SetViewAngles(viewAng); -#endif - -#ifdef GAME_DLL - SetSimulationTime(gpGlobals->curtime); - SetNextThink(gpGlobals->curtime); -#endif - - if (leanAngle >= 0) - { - return leanAngle * neo_lean_tp_exaggerate_scale.GetFloat(); - } - else - { - const float leftleanOverleanRatio = (neo_lean_yaw_peek_right_amount.GetFloat() / neo_lean_yaw_peek_left_amount.GetFloat()); - return leanAngle * neo_lean_tp_exaggerate_scale.GetFloat() * leftleanOverleanRatio; - } -} - -void CNEOPredictedViewModel::CalcViewModelView(CBasePlayer *pOwner, - const Vector& eyePosition, const QAngle& eyeAngles) -{ - if (pOwner->GetObserverMode() == OBS_MODE_IN_EYE) - { - if (auto *pTargetPlayer = dynamic_cast(pOwner->GetObserverTarget()); - pTargetPlayer && !pTargetPlayer->IsObserver()) - { - // NEO NOTE (nullsystem): 1st person mode pOwner = pTargetPlayer eye position - // Take the target player's viewmodel FOV instead, otherwise it'll just look like it doesn't - // change viewmodel FOV on 1st spectate - return CalcViewModelView(pTargetPlayer, eyePosition, eyeAngles); - } - } - - // Is there a nicer way to do this? - auto weapon = static_cast(GetOwningWeapon()); - - if (!weapon) - { - return; - } - -#ifdef GAME_DLL - if (LookupAttachment("Muzzle") > 0) - { - if (m_pFirstPersonMuzzleFlash) { - m_pFirstPersonMuzzleFlash->SetParent(this); - m_pFirstPersonMuzzleFlash->SetParentAttachment("SetParentAttachment", "Muzzle", false); - } - } -#endif - - CHL2MPSWeaponInfo data = weapon->GetHL2MPWpnData(); - - Vector vForward, vRight, vUp, newPos, vOffset; - QAngle newAng, angOffset; - - newAng = eyeAngles; - newPos = eyePosition; - - AngleVectors(newAng, &vForward, &vRight, &vUp); - - if (auto neoPlayer = static_cast(pOwner)) - { - vOffset = m_vOffset; - angOffset = m_angOffset; -#ifdef CLIENT_DLL - if (!prediction->InPrediction()) -#endif - { - const bool playerAiming = neoPlayer->IsInAim(); - const float currentTime = gpGlobals->curtime; - if (m_bViewAim && !playerAiming) - { - // From aiming to not aiming - m_flStartAimingChange = currentTime; - m_bViewAim = false; - } - else if (!m_bViewAim && playerAiming) - { - // From not aiming to aiming - m_flStartAimingChange = currentTime; - m_bViewAim = true; - } - const float endAimingChange = m_flStartAimingChange + NEO_ZOOM_SPEED; - const bool inAimingChange = (m_flStartAimingChange <= currentTime && currentTime < endAimingChange); - if (inAimingChange) - { - float percentage = clamp((currentTime - m_flStartAimingChange) / NEO_ZOOM_SPEED, 0.0f, 1.0f); - if (playerAiming) percentage = 1.0f - percentage; - vOffset = Lerp(percentage, data.m_vecVMAimPosOffset, data.m_vecVMPosOffset); - angOffset = Lerp(percentage, data.m_angVMAimAngOffset, data.m_angVMAngOffset); - } - else - { - vOffset = (playerAiming) ? data.m_vecVMAimPosOffset : data.m_vecVMPosOffset; - angOffset = (playerAiming) ? data.m_angVMAimAngOffset : data.m_angVMAngOffset; - } - m_vOffset = vOffset; - m_angOffset = angOffset; - } - } - - newPos += vForward * vOffset.x; - newPos += vRight * vOffset.y; - newPos += vUp * vOffset.z; - - newAng += angOffset; - - BaseClass::CalcViewModelView(pOwner, newPos, newAng); -} - -#ifdef CLIENT_DLL -RenderGroup_t CNEOPredictedViewModel::GetRenderGroup() -{ - auto pPlayer = static_cast(GetOwner()); - if (pPlayer) - { - return pPlayer->IsCloaked() ? RENDER_GROUP_VIEW_MODEL_TRANSLUCENT : RENDER_GROUP_VIEW_MODEL_OPAQUE; - } - - return BaseClass::GetRenderGroup(); -} -#endif diff --git a/mp/src/game/server/neo/neo_player.cpp b/mp/src/game/server/neo/neo_player.cpp index cff588f14..ac46bc855 100644 --- a/mp/src/game/server/neo/neo_player.cpp +++ b/mp/src/game/server/neo/neo_player.cpp @@ -1543,12 +1543,19 @@ bool CNEO_Player::ClientCommand( const CCommand &args ) void CNEO_Player::CreateViewModel( int index ) { Assert( index >= 0 && index < MAX_VIEWMODELS ); + static int constexpr VIEWMODELMUZZLEFLASH_INDEX = 1; + Assert(VIEWMODELMUZZLEFLASH_INDEX != index && VIEWMODELMUZZLEFLASH_INDEX < MAX_VIEWMODELS); if ( GetViewModel( index ) ) { return; } + if (GetViewModel(VIEWMODELMUZZLEFLASH_INDEX)) + { + return; + } + CNEOPredictedViewModel *vm = ( CNEOPredictedViewModel * )CreateEntityByName( "neo_predicted_viewmodel" ); if ( vm ) { @@ -1564,6 +1571,20 @@ void CNEO_Player::CreateViewModel( int index ) Warning("CNEO_Player::CreateViewModel: Failed to create neo_predicted_viewmodel\n"); return; } + + CNEOPredictedViewModelMuzzleFlash* vmm = (CNEOPredictedViewModelMuzzleFlash*)CreateEntityByName( "neo_predicted_viewmodel_muzzleflash" ); + if (vmm) + { + vmm->SetAbsOrigin(vm->GetAbsOrigin()); + vmm->SetOwner(this); + vmm->SetParent(vm); + DispatchSpawn(vmm); + m_hViewModel.Set(VIEWMODELMUZZLEFLASH_INDEX, vmm); + } + else + { + Warning("CNEO_Player::CreateViewModel: Failed to create neo_predicted_viewmodel_muzzleflash\n"); + } } bool CNEO_Player::BecomeRagdollOnClient( const Vector &force ) diff --git a/mp/src/game/shared/baseplayer_shared.cpp b/mp/src/game/shared/baseplayer_shared.cpp index bbeefb36f..3ceb056a0 100644 --- a/mp/src/game/shared/baseplayer_shared.cpp +++ b/mp/src/game/shared/baseplayer_shared.cpp @@ -894,33 +894,30 @@ bool CBasePlayer::Weapon_Switch( CBaseCombatWeapon *pWeapon, int viewmodelindex #ifdef NEO auto neoWep = static_cast(pWeapon); - CNEOPredictedViewModel* neoViewModel = static_cast(m_hViewModel[0].Get()); - if (neoViewModel->m_pFirstPersonMuzzleFlash) + CNEOPredictedViewModelMuzzleFlash* neoViewModelMuzzleflash = static_cast(m_hViewModel[1].Get()); + if (neoViewModelMuzzleflash) { if (neoWep->GetNeoWepBits() & NEO_WEP_SUPPRESSED) { - neoViewModel->m_pFirstPersonMuzzleFlash->m_bActive = false; + neoViewModelMuzzleflash->m_bActive = false; } else if (neoWep->GetNeoWepBits() & (NEO_WEP_PZ | NEO_WEP_TACHI)) { - neoViewModel->m_pFirstPersonMuzzleFlash->m_bActive = true; - neoViewModel->m_pFirstPersonMuzzleFlash->selectedFlash = 1; - neoViewModel->m_pFirstPersonMuzzleFlash->m_nSkin = 1; - //neoViewModel->m_pFirstPersonMuzzleFlash->SetModelScale(1); + neoViewModelMuzzleflash->m_bActive = true; + neoViewModelMuzzleflash->m_nSkin = 1; + neoViewModelMuzzleflash->SetModelScale(1); } else if (neoWep->GetNeoWepBits() & NEO_WEP_SUPA7) { - neoViewModel->m_pFirstPersonMuzzleFlash->m_bActive = true; - neoViewModel->m_pFirstPersonMuzzleFlash->selectedFlash = 0; - neoViewModel->m_pFirstPersonMuzzleFlash->m_nSkin = 0; - //neoViewModel->m_pFirstPersonMuzzleFlash->SetModelScale(1.5); + neoViewModelMuzzleflash->m_bActive = true; + neoViewModelMuzzleflash->m_nSkin = 0; + neoViewModelMuzzleflash->SetModelScale(1.5); } else { - neoViewModel->m_pFirstPersonMuzzleFlash->m_bActive = true; - neoViewModel->m_pFirstPersonMuzzleFlash->selectedFlash = 0; - neoViewModel->m_pFirstPersonMuzzleFlash->m_nSkin = 0; - //neoViewModel->m_pFirstPersonMuzzleFlash->SetModelScale(1); + neoViewModelMuzzleflash->m_bActive = true; + neoViewModelMuzzleflash->m_nSkin = 0; + neoViewModelMuzzleflash->SetModelScale(1); } } #endif // NEO diff --git a/mp/src/game/shared/neo/neo_predicted_viewmodel.cpp b/mp/src/game/shared/neo/neo_predicted_viewmodel.cpp index 1c99a2e3a..c870e7113 100644 --- a/mp/src/game/shared/neo/neo_predicted_viewmodel.cpp +++ b/mp/src/game/shared/neo/neo_predicted_viewmodel.cpp @@ -58,23 +58,6 @@ CNEOPredictedViewModel::CNEOPredictedViewModel() m_flYPrevious = 0; m_flStartAimingChange = 0; m_bViewAim = false; - m_pFirstPersonMuzzleFlash = (CNEOPredictedViewModelMuzzleFlash*)CreateEntityByName("neo_predicted_viewmodel_muzzleflash"); - if (m_pFirstPersonMuzzleFlash) - { - m_pFirstPersonMuzzleFlash->SetOwnerEntity(this); - m_pFirstPersonMuzzleFlash->SetParent(this); - m_pFirstPersonMuzzleFlash->m_bActive = true; -#ifdef GAME_DLL - DispatchSpawn(m_pFirstPersonMuzzleFlash); -#else - m_pFirstPersonMuzzleFlash->SetModelScale(1); - m_pFirstPersonMuzzleFlash->flash[0] = materials->FindMaterial("effects/fpmf/fpmf01.vmt", TEXTURE_GROUP_VIEW_MODEL); - m_pFirstPersonMuzzleFlash->flash[1] = materials->FindMaterial("effects/fpmf/fpmf02.vmt", TEXTURE_GROUP_VIEW_MODEL); - m_pFirstPersonMuzzleFlash->flash[0]->SetMaterialVarFlag(MATERIAL_VAR_IGNOREZ, true); - m_pFirstPersonMuzzleFlash->flash[1]->SetMaterialVarFlag(MATERIAL_VAR_IGNOREZ, true); - clienttools->SetRenderGroup(m_pFirstPersonMuzzleFlash, RENDER_GROUP_VIEW_MODEL_OPAQUE); -#endif - } } CNEOPredictedViewModel::~CNEOPredictedViewModel() @@ -386,16 +369,6 @@ void CNEOPredictedViewModel::CalcViewModelView(CBasePlayer *pOwner, return; } -#ifdef GAME_DLL - if (LookupAttachment("Muzzle") > 0) - { - if (m_pFirstPersonMuzzleFlash) { - m_pFirstPersonMuzzleFlash->SetParent(this); - m_pFirstPersonMuzzleFlash->SetParentAttachment("SetParentAttachment", "Muzzle", false); - } - } -#endif - CHL2MPSWeaponInfo data = weapon->GetHL2MPWpnData(); Vector vForward, vRight, vUp, newPos, vOffset; diff --git a/mp/src/game/shared/neo/neo_predicted_viewmodel.h b/mp/src/game/shared/neo/neo_predicted_viewmodel.h index 4826fbb2c..49ee62866 100644 --- a/mp/src/game/shared/neo/neo_predicted_viewmodel.h +++ b/mp/src/game/shared/neo/neo_predicted_viewmodel.h @@ -46,14 +46,6 @@ class CNEOPredictedViewModel : public CPredictedViewModel virtual RenderGroup_t GetRenderGroup(); #endif - virtual void DoMuzzleFlash() - { - if (m_pFirstPersonMuzzleFlash) - { - m_pFirstPersonMuzzleFlash->DoMuzzleFlash(); - } - BaseClass::DoMuzzleFlash(); - } #ifdef CLIENT_DLL float GetLeanInterp() @@ -74,7 +66,6 @@ class CNEOPredictedViewModel : public CPredictedViewModel float m_flYPrevious; CInterpolatedVar m_iv_flYPrevious; #endif - CNEOPredictedViewModelMuzzleFlash *m_pFirstPersonMuzzleFlash; private: float m_flStartAimingChange; diff --git a/mp/src/game/shared/neo/neo_predicted_viewmodel_muzzleflash.cpp b/mp/src/game/shared/neo/neo_predicted_viewmodel_muzzleflash.cpp index 2482ce609..02915224d 100644 --- a/mp/src/game/shared/neo/neo_predicted_viewmodel_muzzleflash.cpp +++ b/mp/src/game/shared/neo/neo_predicted_viewmodel_muzzleflash.cpp @@ -10,16 +10,22 @@ // memdbgon must be the last include file in a .cpp file!!! #include "tier0/memdbgon.h" -LINK_ENTITY_TO_CLASS(neo_predicted_viewmodel_muzzleflash, CNEOPredictedViewModelMuzzleFlash); +IMPLEMENT_NETWORKCLASS_ALIASED(NEOPredictedViewModelMuzzleFlash, DT_NEOPredictedViewModelMuzzleFlash) -// Start of our data description for the class -BEGIN_DATADESC(CNEOPredictedViewModelMuzzleFlash) +BEGIN_NETWORK_TABLE(CNEOPredictedViewModelMuzzleFlash, DT_NEOPredictedViewModelMuzzleFlash) +#ifndef CLIENT_DLL +SendPropEHandle(SENDINFO_NAME(m_hMoveParent, moveparent)), +#else +RecvPropInt(RECVINFO_NAME(m_hNetworkMoveParent, moveparent), 0, RecvProxy_IntToMoveParent), +#endif +END_NETWORK_TABLE() -// Save/restore our active state -DEFINE_FIELD(m_bActive, FIELD_BOOLEAN), -DEFINE_FIELD(m_flNextChangeTime, FIELD_TIME), +#ifdef CLIENT_DLL +BEGIN_PREDICTION_DATA(CNEOPredictedViewModelMuzzleFlash) +END_PREDICTION_DATA() +#endif -END_DATADESC() +LINK_ENTITY_TO_CLASS(neo_predicted_viewmodel_muzzleflash, CNEOPredictedViewModelMuzzleFlash); #define MUZZLE_FLASH_ENTITY_MODEL "models/effect/fpmf/fpmf01.mdl" @@ -41,22 +47,35 @@ void CNEOPredictedViewModelMuzzleFlash::Spawn(void) Precache(); SetModel(MUZZLE_FLASH_ENTITY_MODEL); SetSolid(SOLID_NONE); - SetMoveType(MOVETYPE_NONE); AddEffects(EF_NOSHADOW); AddEffects(EF_NORECEIVESHADOW); + RemoveEffects(EF_NODRAW); + RemoveEffects(EF_BONEMERGE); } #ifdef CLIENT_DLL int CNEOPredictedViewModelMuzzleFlash::DrawModel(int flags) { - if (!ShouldMuzzleFlash() || !m_bActive) + if (!IsEffectActive(EF_NODRAW) && m_bActive) { - flash[selectedFlash]->SetMaterialVarFlag(MATERIAL_VAR_NO_DRAW, true); - return 0; + CBasePlayer* pOwner = ToBasePlayer(GetOwner()); + if (pOwner == NULL) + return -1; + CBaseViewModel* vm = pOwner->GetViewModel(0, false); + if (vm == NULL) + return -1; + int iAttachment = vm->LookupAttachment("muzzle"); + Vector localOrigin; + QAngle localAngle; + vm->GetAttachment(iAttachment, localOrigin, localAngle); + UncorrectViewModelAttachment(localOrigin); + localAngle.z += RandomFloat(-5.f, 5.f); + SetAbsOrigin(localOrigin); + SetAbsAngles(localAngle); + int ret = BaseClass::DrawModel(flags); + AddEffects(EF_NODRAW); + return ret; } - DisableMuzzleFlash(); - flash[selectedFlash]->SetMaterialVarFlag(MATERIAL_VAR_NO_DRAW, false); - int ret = BaseClass::DrawModel(flags); - return ret; + return -1; } #endif \ No newline at end of file diff --git a/mp/src/game/shared/neo/neo_predicted_viewmodel_muzzleflash.h b/mp/src/game/shared/neo/neo_predicted_viewmodel_muzzleflash.h index a823402cb..29d334b84 100644 --- a/mp/src/game/shared/neo/neo_predicted_viewmodel_muzzleflash.h +++ b/mp/src/game/shared/neo/neo_predicted_viewmodel_muzzleflash.h @@ -4,46 +4,36 @@ #pragma once #endif -#ifdef GAME_DLL -#include "baseanimating.h" -#include "baseviewmodel_shared.h" -#else -#include "c_baseviewmodel.h" +#include "predicted_viewmodel.h" + +#ifdef CLIENT_DLL +#define CNEOPredictedViewModelMuzzleFlash C_NEOPredictedViewModelMuzzleFlash +#define CNEO_Player C_NEO_Player #endif class CNEO_Player; -class CNEOPredictedViewModelMuzzleFlash : public CBaseAnimating +class CNEOPredictedViewModelMuzzleFlash : public CPredictedViewModel { + DECLARE_CLASS(CNEOPredictedViewModelMuzzleFlash, CPredictedViewModel); public: - DECLARE_CLASS(CNEOPredictedViewModelMuzzleFlash, CBaseAnimating); - DECLARE_DATADESC(); + DECLARE_NETWORKCLASS(); + DECLARE_PREDICTABLE(); CNEOPredictedViewModelMuzzleFlash() { - m_bActive = false; - m_flNextChangeTime = 0.f; -#ifdef CLIENT_DLL - m_hRender = INVALID_CLIENT_RENDER_HANDLE; - AddToLeafSystem(); -#endif + m_bActive = true; } #ifdef CLIENT_DLL ShadowType_t ShadowCastType() override { return SHADOWS_NONE; }; - bool IsViewModel() const override { return true; }; - RenderGroup_t GetRenderGroup() override { return RENDER_GROUP_VIEW_MODEL_OPAQUE; }; - bool ShouldDraw() override { return true; }; + RenderGroup_t GetRenderGroup() override { return RENDER_GROUP_VIEW_MODEL_TRANSLUCENT; }; int DrawModel(int flags) override; + void ProcessMuzzleFlashEvent() override { RemoveEffects(EF_NODRAW); } #endif void Spawn(void); void Precache(void); - int selectedFlash; - IMaterial* flash[2]; - bool m_bActive; -private: - float m_flNextChangeTime; }; #endif // NEO_PREDICTED_VIEWMODEL_MUZZLEFLASH_H \ No newline at end of file From a4bf9c0cc999af5fc62efe0a59ae62c365cd948e Mon Sep 17 00:00:00 2001 From: AdamTadeusz Date: Sun, 25 Aug 2024 16:05:08 +0100 Subject: [PATCH 06/14] Always remake the muzzle flash viewmodel if need be, tie muzzle flash time seen to global time --- mp/src/game/server/neo/neo_player.cpp | 47 ++++++++----------- .../neo_predicted_viewmodel_muzzleflash.cpp | 3 +- .../neo/neo_predicted_viewmodel_muzzleflash.h | 3 +- 3 files changed, 22 insertions(+), 31 deletions(-) diff --git a/mp/src/game/server/neo/neo_player.cpp b/mp/src/game/server/neo/neo_player.cpp index ac46bc855..0c8f13f09 100644 --- a/mp/src/game/server/neo/neo_player.cpp +++ b/mp/src/game/server/neo/neo_player.cpp @@ -1546,45 +1546,36 @@ void CNEO_Player::CreateViewModel( int index ) static int constexpr VIEWMODELMUZZLEFLASH_INDEX = 1; Assert(VIEWMODELMUZZLEFLASH_INDEX != index && VIEWMODELMUZZLEFLASH_INDEX < MAX_VIEWMODELS); - if ( GetViewModel( index ) ) + if ( !GetViewModel( index ) ) { - return; - } - - if (GetViewModel(VIEWMODELMUZZLEFLASH_INDEX)) - { - return; + CNEOPredictedViewModel* vm = (CNEOPredictedViewModel*)CreateEntityByName("neo_predicted_viewmodel"); + if (vm) + { + vm->SetAbsOrigin(GetAbsOrigin()); + vm->SetOwner(this); + vm->SetIndex(index); + DispatchSpawn(vm); + vm->FollowEntity(this, false); + m_hViewModel.Set(index, vm); + } } - CNEOPredictedViewModel *vm = ( CNEOPredictedViewModel * )CreateEntityByName( "neo_predicted_viewmodel" ); - if ( vm ) - { - vm->SetAbsOrigin( GetAbsOrigin() ); - vm->SetOwner( this ); - vm->SetIndex( index ); - DispatchSpawn( vm ); - vm->FollowEntity( this, false ); - m_hViewModel.Set( index, vm ); - } - else + if ( !GetViewModel(VIEWMODELMUZZLEFLASH_INDEX)) { - Warning("CNEO_Player::CreateViewModel: Failed to create neo_predicted_viewmodel\n"); - return; - } + CNEOPredictedViewModelMuzzleFlash* vmm = (CNEOPredictedViewModelMuzzleFlash*)CreateEntityByName("neo_predicted_viewmodel_muzzleflash"); + if (!vmm) + return; + + CBaseViewModel* vm = GetViewModel(); + if (!vm) + return; - CNEOPredictedViewModelMuzzleFlash* vmm = (CNEOPredictedViewModelMuzzleFlash*)CreateEntityByName( "neo_predicted_viewmodel_muzzleflash" ); - if (vmm) - { vmm->SetAbsOrigin(vm->GetAbsOrigin()); vmm->SetOwner(this); vmm->SetParent(vm); DispatchSpawn(vmm); m_hViewModel.Set(VIEWMODELMUZZLEFLASH_INDEX, vmm); } - else - { - Warning("CNEO_Player::CreateViewModel: Failed to create neo_predicted_viewmodel_muzzleflash\n"); - } } bool CNEO_Player::BecomeRagdollOnClient( const Vector &force ) diff --git a/mp/src/game/shared/neo/neo_predicted_viewmodel_muzzleflash.cpp b/mp/src/game/shared/neo/neo_predicted_viewmodel_muzzleflash.cpp index 02915224d..9c69606fa 100644 --- a/mp/src/game/shared/neo/neo_predicted_viewmodel_muzzleflash.cpp +++ b/mp/src/game/shared/neo/neo_predicted_viewmodel_muzzleflash.cpp @@ -56,7 +56,7 @@ void CNEOPredictedViewModelMuzzleFlash::Spawn(void) #ifdef CLIENT_DLL int CNEOPredictedViewModelMuzzleFlash::DrawModel(int flags) { - if (!IsEffectActive(EF_NODRAW) && m_bActive) + if (m_flTimeSwitchOffMuzzleFlash > gpGlobals->curtime && m_bActive) { CBasePlayer* pOwner = ToBasePlayer(GetOwner()); if (pOwner == NULL) @@ -73,7 +73,6 @@ int CNEOPredictedViewModelMuzzleFlash::DrawModel(int flags) SetAbsOrigin(localOrigin); SetAbsAngles(localAngle); int ret = BaseClass::DrawModel(flags); - AddEffects(EF_NODRAW); return ret; } return -1; diff --git a/mp/src/game/shared/neo/neo_predicted_viewmodel_muzzleflash.h b/mp/src/game/shared/neo/neo_predicted_viewmodel_muzzleflash.h index 29d334b84..7e6273c83 100644 --- a/mp/src/game/shared/neo/neo_predicted_viewmodel_muzzleflash.h +++ b/mp/src/game/shared/neo/neo_predicted_viewmodel_muzzleflash.h @@ -27,13 +27,14 @@ class CNEOPredictedViewModelMuzzleFlash : public CPredictedViewModel ShadowType_t ShadowCastType() override { return SHADOWS_NONE; }; RenderGroup_t GetRenderGroup() override { return RENDER_GROUP_VIEW_MODEL_TRANSLUCENT; }; int DrawModel(int flags) override; - void ProcessMuzzleFlashEvent() override { RemoveEffects(EF_NODRAW); } + void ProcessMuzzleFlashEvent() override { m_flTimeSwitchOffMuzzleFlash = gpGlobals->curtime + 0.02f; } #endif void Spawn(void); void Precache(void); bool m_bActive; + float m_flTimeSwitchOffMuzzleFlash; }; #endif // NEO_PREDICTED_VIEWMODEL_MUZZLEFLASH_H \ No newline at end of file From db8ff92a2ef06373319dbc9f3445c465a988e794 Mon Sep 17 00:00:00 2001 From: AdamTadeusz Date: Mon, 26 Aug 2024 11:51:58 +0100 Subject: [PATCH 07/14] added environment light for fp muzzle flash, synchronise muzzle flash scale between server and client --- mp/src/game/client/c_baseanimating.cpp | 17 +++- mp/src/game/client/c_baseplayer.h | 3 + mp/src/game/server/player.h | 3 + mp/src/game/shared/baseplayer_shared.cpp | 94 +++++++++++++------ .../neo_predicted_viewmodel_muzzleflash.cpp | 21 ++++- .../neo/neo_predicted_viewmodel_muzzleflash.h | 24 ++++- .../weapons/weapon_neobasecombatweapon.cpp | 5 +- 7 files changed, 133 insertions(+), 34 deletions(-) diff --git a/mp/src/game/client/c_baseanimating.cpp b/mp/src/game/client/c_baseanimating.cpp index 428c87dd9..174fafe7a 100644 --- a/mp/src/game/client/c_baseanimating.cpp +++ b/mp/src/game/client/c_baseanimating.cpp @@ -3391,12 +3391,27 @@ void C_BaseAnimating::ProcessMuzzleFlashEvent() { Vector vAttachment; QAngle dummyAngles; + +#ifdef NEO + GetAttachment( 2, vAttachment, dummyAngles ); + + // Make a dlight + dlight_t* dl = effects->CL_AllocDlight(LIGHT_INDEX_MUZZLEFLASH + index); + dl->origin = vAttachment; + dl->radius = random->RandomInt(64, 96); + dl->decay = dl->radius / 0.1f; + dl->die = gpGlobals->curtime + 0.1f; + dl->color.r = 255; + dl->color.g = 192; + dl->color.b = 64; + dl->color.exponent = 5; +#endif GetAttachment( 1, vAttachment, dummyAngles ); // Make an elight dlight_t *el = effects->CL_AllocElight( LIGHT_INDEX_MUZZLEFLASH + index ); el->origin = vAttachment; - el->radius = random->RandomInt( 32, 64 ); + el->radius = random->RandomInt( 32, 64 ); el->decay = el->radius / 0.05f; el->die = gpGlobals->curtime + 0.05f; el->color.r = 255; diff --git a/mp/src/game/client/c_baseplayer.h b/mp/src/game/client/c_baseplayer.h index dc3286c61..6b7c4b92f 100644 --- a/mp/src/game/client/c_baseplayer.h +++ b/mp/src/game/client/c_baseplayer.h @@ -263,6 +263,9 @@ class C_BasePlayer : public C_BaseCombatCharacter, public CGameEventListener virtual void Weapon_SetLast( C_BaseCombatWeapon *pWeapon ); virtual bool Weapon_ShouldSetLast( C_BaseCombatWeapon *pOldWeapon, C_BaseCombatWeapon *pNewWeapon ) { return true; } virtual bool Weapon_ShouldSelectItem( C_BaseCombatWeapon *pWeapon ); +#ifdef NEO + void UpdateMuzzleFlashProperties( C_BaseCombatWeapon* pWeapon ); +#endif virtual bool Weapon_Switch( C_BaseCombatWeapon *pWeapon, int viewmodelindex = 0 ); // Switch to given weapon if has ammo (false if failed) virtual C_BaseCombatWeapon *GetLastWeapon( void ) { return m_hLastWeapon.Get(); } void ResetAutoaim( void ); diff --git a/mp/src/game/server/player.h b/mp/src/game/server/player.h index 828b418a7..aaa37f063 100644 --- a/mp/src/game/server/player.h +++ b/mp/src/game/server/player.h @@ -410,6 +410,9 @@ class CBasePlayer : public CBaseCombatCharacter virtual bool Weapon_CanUse( CBaseCombatWeapon *pWeapon ); virtual void Weapon_Equip( CBaseCombatWeapon *pWeapon ); virtual void Weapon_Drop( CBaseCombatWeapon *pWeapon, const Vector *pvecTarget /* = NULL */, const Vector *pVelocity /* = NULL */ ); +#ifdef NEO + void UpdateMuzzleFlashProperties( CBaseCombatWeapon* pWeapon ); +#endif virtual bool Weapon_Switch( CBaseCombatWeapon *pWeapon, int viewmodelindex = 0 ); // Switch to given weapon if has ammo (false if failed) virtual void Weapon_SetLast( CBaseCombatWeapon *pWeapon ); virtual bool Weapon_ShouldSetLast( CBaseCombatWeapon *pOldWeapon, CBaseCombatWeapon *pNewWeapon ) { return true; } diff --git a/mp/src/game/shared/baseplayer_shared.cpp b/mp/src/game/shared/baseplayer_shared.cpp index 3ceb056a0..6cd97bf3d 100644 --- a/mp/src/game/shared/baseplayer_shared.cpp +++ b/mp/src/game/shared/baseplayer_shared.cpp @@ -870,6 +870,64 @@ void CBasePlayer::Weapon_SetLast( CBaseCombatWeapon *pWeapon ) m_hLastWeapon = pWeapon; } +#ifdef NEO +void CBasePlayer::UpdateMuzzleFlashProperties(CBaseCombatWeapon* pWeapon) +{ + auto neoWep = static_cast(pWeapon); + if (!neoWep) + return; + + CNEOPredictedViewModelMuzzleFlash* neoViewModelMuzzleflash = static_cast(m_hViewModel[1].Get()); + if (neoViewModelMuzzleflash) + { + if (neoWep->GetNeoWepBits() & (NEO_WEP_DETPACK | NEO_WEP_GHOST | NEO_WEP_FRAG_GRENADE | NEO_WEP_KNIFE | NEO_WEP_SMOKE_GRENADE | NEO_WEP_SUPPRESSED | NEO_WEP_EXPLOSIVE)) + { + neoViewModelMuzzleflash->m_bActive = false; + } + else if (neoWep->GetNeoWepBits() & (NEO_WEP_PZ | NEO_WEP_TACHI | NEO_WEP_KYLA)) + { + neoViewModelMuzzleflash->m_bActive = true; + neoViewModelMuzzleflash->m_nSkin = 1; + neoViewModelMuzzleflash->m_iAngleZ = 0; + neoViewModelMuzzleflash->m_iAngleZIncrement = -90; + neoViewModelMuzzleflash->m_iModelScale = 0.75; + } + else if (neoWep->GetNeoWepBits() & NEO_WEP_SUPA7) + { + neoViewModelMuzzleflash->m_bActive = true; + neoViewModelMuzzleflash->m_nSkin = 1; + neoViewModelMuzzleflash->m_iAngleZ = 0; + neoViewModelMuzzleflash->m_iAngleZIncrement = -90; + neoViewModelMuzzleflash->m_iModelScale = 1; + } + else if (neoWep->GetNeoWepBits() & (NEO_WEP_SRM | NEO_WEP_JITTE)) + { + neoViewModelMuzzleflash->m_bActive = true; + neoViewModelMuzzleflash->m_nSkin = 0; + neoViewModelMuzzleflash->m_iAngleZ = 0; + neoViewModelMuzzleflash->m_iAngleZIncrement = -90; + neoViewModelMuzzleflash->m_iModelScale = 0.75; + } + else if (neoWep->GetNeoWepBits() & (NEO_WEP_MX)) + { + neoViewModelMuzzleflash->m_bActive = true; + neoViewModelMuzzleflash->m_nSkin = 0; + neoViewModelMuzzleflash->m_iAngleZ = 0; + neoViewModelMuzzleflash->m_iAngleZIncrement = -95; + neoViewModelMuzzleflash->m_iModelScale = 0.6; + } + else + { + neoViewModelMuzzleflash->m_bActive = true; + neoViewModelMuzzleflash->m_nSkin = 0; + neoViewModelMuzzleflash->m_iAngleZ = 0; + neoViewModelMuzzleflash->m_iAngleZIncrement = -90; + neoViewModelMuzzleflash->m_iModelScale = 0.75; + } + } +} +#endif // NEO + //----------------------------------------------------------------------------- // Purpose: Override base class so player can reset autoaim // Input : @@ -893,37 +951,19 @@ bool CBasePlayer::Weapon_Switch( CBaseCombatWeapon *pWeapon, int viewmodelindex ResetAutoaim( ); #ifdef NEO - auto neoWep = static_cast(pWeapon); - CNEOPredictedViewModelMuzzleFlash* neoViewModelMuzzleflash = static_cast(m_hViewModel[1].Get()); - if (neoViewModelMuzzleflash) - { - if (neoWep->GetNeoWepBits() & NEO_WEP_SUPPRESSED) - { - neoViewModelMuzzleflash->m_bActive = false; - } - else if (neoWep->GetNeoWepBits() & (NEO_WEP_PZ | NEO_WEP_TACHI)) - { - neoViewModelMuzzleflash->m_bActive = true; - neoViewModelMuzzleflash->m_nSkin = 1; - neoViewModelMuzzleflash->SetModelScale(1); - } - else if (neoWep->GetNeoWepBits() & NEO_WEP_SUPA7) - { - neoViewModelMuzzleflash->m_bActive = true; - neoViewModelMuzzleflash->m_nSkin = 0; - neoViewModelMuzzleflash->SetModelScale(1.5); - } - else - { - neoViewModelMuzzleflash->m_bActive = true; - neoViewModelMuzzleflash->m_nSkin = 0; - neoViewModelMuzzleflash->SetModelScale(1); - } - } + UpdateMuzzleFlashProperties(pWeapon); #endif // NEO return true; } + +#ifdef NEO + if (IsAlive() == false) + { + // Active weapon was probably updated, update muzzle flash properties regardless + UpdateMuzzleFlashProperties(pWeapon); + } +#endif // NEO return false; } diff --git a/mp/src/game/shared/neo/neo_predicted_viewmodel_muzzleflash.cpp b/mp/src/game/shared/neo/neo_predicted_viewmodel_muzzleflash.cpp index 9c69606fa..f2e6acf6d 100644 --- a/mp/src/game/shared/neo/neo_predicted_viewmodel_muzzleflash.cpp +++ b/mp/src/game/shared/neo/neo_predicted_viewmodel_muzzleflash.cpp @@ -15,8 +15,16 @@ IMPLEMENT_NETWORKCLASS_ALIASED(NEOPredictedViewModelMuzzleFlash, DT_NEOPredicted BEGIN_NETWORK_TABLE(CNEOPredictedViewModelMuzzleFlash, DT_NEOPredictedViewModelMuzzleFlash) #ifndef CLIENT_DLL SendPropEHandle(SENDINFO_NAME(m_hMoveParent, moveparent)), +SendPropBool(SENDINFO(m_bActive)), +SendPropInt(SENDINFO(m_iAngleZ)), +SendPropInt(SENDINFO(m_iAngleZIncrement)), +SendPropFloat(SENDINFO(m_iModelScale)), #else RecvPropInt(RECVINFO_NAME(m_hNetworkMoveParent, moveparent), 0, RecvProxy_IntToMoveParent), +RecvPropBool(RECVINFO(m_bActive)), +RecvPropInt(RECVINFO(m_iAngleZ)), +RecvPropInt(RECVINFO(m_iAngleZIncrement)), +RecvPropFloat(RECVINFO(m_iModelScale)), #endif END_NETWORK_TABLE() @@ -64,14 +72,23 @@ int CNEOPredictedViewModelMuzzleFlash::DrawModel(int flags) CBaseViewModel* vm = pOwner->GetViewModel(0, false); if (vm == NULL) return -1; + + if (m_iModelScale != GetModelScale()) + SetModelScale(m_iModelScale); // NEOTODO (Adam) model scale is a networked property in cbaseanimating, but for some reason its not being networked when set on the server side when initially spawning/respawning the player, so sometimes muzzle flash size can be incorrect if using SetModelScale in Weapon_Equip() + int iAttachment = vm->LookupAttachment("muzzle"); + if (iAttachment < 0) + return -1; + Vector localOrigin; QAngle localAngle; vm->GetAttachment(iAttachment, localOrigin, localAngle); - UncorrectViewModelAttachment(localOrigin); - localAngle.z += RandomFloat(-5.f, 5.f); + UncorrectViewModelAttachment(localOrigin); // Need position of muzzle without fov modifications & viewmodel offset + m_iAngleZ = (m_iAngleZ + m_iAngleZIncrement) % 360; // NEOTODO (Adam) ? Speed of rotation depends on how often DrawModel() is called. Should this be tied to global time? + localAngle.z = m_iAngleZ; SetAbsOrigin(localOrigin); SetAbsAngles(localAngle); + int ret = BaseClass::DrawModel(flags); return ret; } diff --git a/mp/src/game/shared/neo/neo_predicted_viewmodel_muzzleflash.h b/mp/src/game/shared/neo/neo_predicted_viewmodel_muzzleflash.h index 7e6273c83..32cc9fe49 100644 --- a/mp/src/game/shared/neo/neo_predicted_viewmodel_muzzleflash.h +++ b/mp/src/game/shared/neo/neo_predicted_viewmodel_muzzleflash.h @@ -21,20 +21,40 @@ class CNEOPredictedViewModelMuzzleFlash : public CPredictedViewModel CNEOPredictedViewModelMuzzleFlash() { m_bActive = true; + m_iAngleZ = 0; + m_iAngleZIncrement = -5; + m_flTimeSwitchOffMuzzleFlash = gpGlobals->curtime; + m_iModelScale = 1; } #ifdef CLIENT_DLL ShadowType_t ShadowCastType() override { return SHADOWS_NONE; }; RenderGroup_t GetRenderGroup() override { return RENDER_GROUP_VIEW_MODEL_TRANSLUCENT; }; int DrawModel(int flags) override; - void ProcessMuzzleFlashEvent() override { m_flTimeSwitchOffMuzzleFlash = gpGlobals->curtime + 0.02f; } + void ProcessMuzzleFlashEvent() override + { + if (!m_bActive) + return; + m_flTimeSwitchOffMuzzleFlash = gpGlobals->curtime + 0.01f; + BaseClass::ProcessMuzzleFlashEvent(); + } #endif void Spawn(void); void Precache(void); +#ifdef GAME_DLL + CNetworkVar(bool, m_bActive); + CNetworkVar(int, m_iAngleZ); + CNetworkVar(int, m_iAngleZIncrement); + CNetworkVar(float, m_iModelScale); +#else bool m_bActive; - float m_flTimeSwitchOffMuzzleFlash; + int m_iAngleZ; + int m_iAngleZIncrement; + float m_iModelScale; +#endif // GAME_DLL + float m_flTimeSwitchOffMuzzleFlash; // If the server can fire a user's weapon (maybe some kind of server triggered weapon cook off or something), this will need to be networked too. }; #endif // NEO_PREDICTED_VIEWMODEL_MUZZLEFLASH_H \ No newline at end of file diff --git a/mp/src/game/shared/neo/weapons/weapon_neobasecombatweapon.cpp b/mp/src/game/shared/neo/weapons/weapon_neobasecombatweapon.cpp index 37c178d97..03698a5a8 100644 --- a/mp/src/game/shared/neo/weapons/weapon_neobasecombatweapon.cpp +++ b/mp/src/game/shared/neo/weapons/weapon_neobasecombatweapon.cpp @@ -672,7 +672,8 @@ void CNEOBaseCombatWeapon::PrimaryAttack(void) return; } - pPlayer->DoMuzzleFlash(); + if (!(GetNeoWepBits() & NEO_WEP_SUPPRESSED)) + pPlayer->DoMuzzleFlash(); SendWeaponAnim(GetPrimaryAttackActivity()); @@ -713,7 +714,7 @@ void CNEOBaseCombatWeapon::PrimaryAttack(void) info.m_flDistance = MAX_TRACE_LENGTH; info.m_iAmmoType = m_iPrimaryAmmoType; - info.m_iTracerFreq = 2; + info.m_iTracerFreq = 0; #if !defined( CLIENT_DLL ) // Fire the bullets From d60a026913d92619dbbcb38ee2f761f062271392 Mon Sep 17 00:00:00 2001 From: AdamTadeusz Date: Mon, 26 Aug 2024 12:26:38 +0100 Subject: [PATCH 08/14] no tracers for any weapons --- mp/src/game/shared/neo/weapons/weapon_aa13.cpp | 1 + mp/src/game/shared/neo/weapons/weapon_kyla.cpp | 1 + mp/src/game/shared/neo/weapons/weapon_supa7.cpp | 1 + 3 files changed, 3 insertions(+) diff --git a/mp/src/game/shared/neo/weapons/weapon_aa13.cpp b/mp/src/game/shared/neo/weapons/weapon_aa13.cpp index 29cc6cf6f..6707f2485 100644 --- a/mp/src/game/shared/neo/weapons/weapon_aa13.cpp +++ b/mp/src/game/shared/neo/weapons/weapon_aa13.cpp @@ -203,6 +203,7 @@ void CWeaponAA13::PrimaryAttack(void) Vector vecSpread = GetBulletSpread(); FireBulletsInfo_t info(5, vecSrc, vecAiming, vecSpread, MAX_TRACE_LENGTH, m_iPrimaryAmmoType); info.m_pAttacker = pPlayer; + info.m_iTracerFreq = 0; // Fire the bullets, and force the first shot to be perfectly accurate pPlayer->FireBullets(info); diff --git a/mp/src/game/shared/neo/weapons/weapon_kyla.cpp b/mp/src/game/shared/neo/weapons/weapon_kyla.cpp index 9d9b7f8d4..068de9e47 100644 --- a/mp/src/game/shared/neo/weapons/weapon_kyla.cpp +++ b/mp/src/game/shared/neo/weapons/weapon_kyla.cpp @@ -79,6 +79,7 @@ void CWeaponKyla::PrimaryAttack(void) FireBulletsInfo_t info(1, vecSrc, vecAiming, vec3_origin, MAX_TRACE_LENGTH, m_iPrimaryAmmoType); info.m_pAttacker = pPlayer; + info.m_iTracerFreq = 0; // Fire the bullets, and force the first shot to be perfectly accuracy pPlayer->FireBullets(info); diff --git a/mp/src/game/shared/neo/weapons/weapon_supa7.cpp b/mp/src/game/shared/neo/weapons/weapon_supa7.cpp index d760485f2..1ebd5af18 100644 --- a/mp/src/game/shared/neo/weapons/weapon_supa7.cpp +++ b/mp/src/game/shared/neo/weapons/weapon_supa7.cpp @@ -325,6 +325,7 @@ void CWeaponSupa7::PrimaryAttack(void) FireBulletsInfo_t info(numBullets, vecSrc, vecAiming, bulletSpread, MAX_TRACE_LENGTH, ammoType); info.m_pAttacker = pPlayer; + info.m_iTracerFreq = 0; pPlayer->DoMuzzleFlash(); From af1cb780d666918ff34fd36c1cb4a13c9f9fd063 Mon Sep 17 00:00:00 2001 From: AdamTadeusz Date: Mon, 26 Aug 2024 13:27:40 +0100 Subject: [PATCH 09/14] cleanup --- mp/src/game/client/c_baseanimating.cpp | 6 +- mp/src/game/server/neo/neo_player.cpp | 8 +- mp/src/game/shared/baseplayer_shared.cpp | 93 ++++++++++--------- .../shared/neo/neo_predicted_viewmodel.cpp | 1 - .../game/shared/neo/neo_predicted_viewmodel.h | 2 - .../neo/neo_predicted_viewmodel_muzzleflash.h | 2 + 6 files changed, 56 insertions(+), 56 deletions(-) diff --git a/mp/src/game/client/c_baseanimating.cpp b/mp/src/game/client/c_baseanimating.cpp index 174fafe7a..5a224e47f 100644 --- a/mp/src/game/client/c_baseanimating.cpp +++ b/mp/src/game/client/c_baseanimating.cpp @@ -3391,7 +3391,6 @@ void C_BaseAnimating::ProcessMuzzleFlashEvent() { Vector vAttachment; QAngle dummyAngles; - #ifdef NEO GetAttachment( 2, vAttachment, dummyAngles ); @@ -3405,19 +3404,20 @@ void C_BaseAnimating::ProcessMuzzleFlashEvent() dl->color.g = 192; dl->color.b = 64; dl->color.exponent = 5; -#endif +#else GetAttachment( 1, vAttachment, dummyAngles ); // Make an elight dlight_t *el = effects->CL_AllocElight( LIGHT_INDEX_MUZZLEFLASH + index ); el->origin = vAttachment; - el->radius = random->RandomInt( 32, 64 ); + el->radius = random->RandomInt( 32, 64 ); el->decay = el->radius / 0.05f; el->die = gpGlobals->curtime + 0.05f; el->color.r = 255; el->color.g = 192; el->color.b = 64; el->color.exponent = 5; +#endif } } } diff --git a/mp/src/game/server/neo/neo_player.cpp b/mp/src/game/server/neo/neo_player.cpp index 0c8f13f09..e44ec31ef 100644 --- a/mp/src/game/server/neo/neo_player.cpp +++ b/mp/src/game/server/neo/neo_player.cpp @@ -3,6 +3,7 @@ #include "neo_playeranimstate.h" #include "neo_predicted_viewmodel.h" +#include "neo_predicted_viewmodel_muzzleflash.h" #include "in_buttons.h" #include "neo_gamerules.h" #include "team.h" @@ -1543,8 +1544,7 @@ bool CNEO_Player::ClientCommand( const CCommand &args ) void CNEO_Player::CreateViewModel( int index ) { Assert( index >= 0 && index < MAX_VIEWMODELS ); - static int constexpr VIEWMODELMUZZLEFLASH_INDEX = 1; - Assert(VIEWMODELMUZZLEFLASH_INDEX != index && VIEWMODELMUZZLEFLASH_INDEX < MAX_VIEWMODELS); + Assert(MUZZLE_FLASH_VIEW_MODEL_INDEX != index && MUZZLE_FLASH_VIEW_MODEL_INDEX < MAX_VIEWMODELS); if ( !GetViewModel( index ) ) { @@ -1560,7 +1560,7 @@ void CNEO_Player::CreateViewModel( int index ) } } - if ( !GetViewModel(VIEWMODELMUZZLEFLASH_INDEX)) + if ( !GetViewModel(MUZZLE_FLASH_VIEW_MODEL_INDEX)) { CNEOPredictedViewModelMuzzleFlash* vmm = (CNEOPredictedViewModelMuzzleFlash*)CreateEntityByName("neo_predicted_viewmodel_muzzleflash"); if (!vmm) @@ -1574,7 +1574,7 @@ void CNEO_Player::CreateViewModel( int index ) vmm->SetOwner(this); vmm->SetParent(vm); DispatchSpawn(vmm); - m_hViewModel.Set(VIEWMODELMUZZLEFLASH_INDEX, vmm); + m_hViewModel.Set(MUZZLE_FLASH_VIEW_MODEL_INDEX, vmm); } } diff --git a/mp/src/game/shared/baseplayer_shared.cpp b/mp/src/game/shared/baseplayer_shared.cpp index 6cd97bf3d..dcbf8e79f 100644 --- a/mp/src/game/shared/baseplayer_shared.cpp +++ b/mp/src/game/shared/baseplayer_shared.cpp @@ -54,6 +54,7 @@ #ifdef NEO #include "neo_gamerules.h" #include "weapon_neobasecombatweapon.h" +#include "neo_predicted_viewmodel_muzzleflash.h" #ifdef GAME_DLL #include "neo_player.h" #else @@ -877,53 +878,53 @@ void CBasePlayer::UpdateMuzzleFlashProperties(CBaseCombatWeapon* pWeapon) if (!neoWep) return; - CNEOPredictedViewModelMuzzleFlash* neoViewModelMuzzleflash = static_cast(m_hViewModel[1].Get()); - if (neoViewModelMuzzleflash) + CNEOPredictedViewModelMuzzleFlash* neoViewModelMuzzleflash = static_cast(m_hViewModel[MUZZLE_FLASH_VIEW_MODEL_INDEX].Get()); + if (!neoViewModelMuzzleflash) + return; + + if (neoWep->GetNeoWepBits() & (NEO_WEP_DETPACK | NEO_WEP_GHOST | NEO_WEP_FRAG_GRENADE | NEO_WEP_KNIFE | NEO_WEP_SMOKE_GRENADE | NEO_WEP_SUPPRESSED | NEO_WEP_EXPLOSIVE)) { - if (neoWep->GetNeoWepBits() & (NEO_WEP_DETPACK | NEO_WEP_GHOST | NEO_WEP_FRAG_GRENADE | NEO_WEP_KNIFE | NEO_WEP_SMOKE_GRENADE | NEO_WEP_SUPPRESSED | NEO_WEP_EXPLOSIVE)) - { - neoViewModelMuzzleflash->m_bActive = false; - } - else if (neoWep->GetNeoWepBits() & (NEO_WEP_PZ | NEO_WEP_TACHI | NEO_WEP_KYLA)) - { - neoViewModelMuzzleflash->m_bActive = true; - neoViewModelMuzzleflash->m_nSkin = 1; - neoViewModelMuzzleflash->m_iAngleZ = 0; - neoViewModelMuzzleflash->m_iAngleZIncrement = -90; - neoViewModelMuzzleflash->m_iModelScale = 0.75; - } - else if (neoWep->GetNeoWepBits() & NEO_WEP_SUPA7) - { - neoViewModelMuzzleflash->m_bActive = true; - neoViewModelMuzzleflash->m_nSkin = 1; - neoViewModelMuzzleflash->m_iAngleZ = 0; - neoViewModelMuzzleflash->m_iAngleZIncrement = -90; - neoViewModelMuzzleflash->m_iModelScale = 1; - } - else if (neoWep->GetNeoWepBits() & (NEO_WEP_SRM | NEO_WEP_JITTE)) - { - neoViewModelMuzzleflash->m_bActive = true; - neoViewModelMuzzleflash->m_nSkin = 0; - neoViewModelMuzzleflash->m_iAngleZ = 0; - neoViewModelMuzzleflash->m_iAngleZIncrement = -90; - neoViewModelMuzzleflash->m_iModelScale = 0.75; - } - else if (neoWep->GetNeoWepBits() & (NEO_WEP_MX)) - { - neoViewModelMuzzleflash->m_bActive = true; - neoViewModelMuzzleflash->m_nSkin = 0; - neoViewModelMuzzleflash->m_iAngleZ = 0; - neoViewModelMuzzleflash->m_iAngleZIncrement = -95; - neoViewModelMuzzleflash->m_iModelScale = 0.6; - } - else - { - neoViewModelMuzzleflash->m_bActive = true; - neoViewModelMuzzleflash->m_nSkin = 0; - neoViewModelMuzzleflash->m_iAngleZ = 0; - neoViewModelMuzzleflash->m_iAngleZIncrement = -90; - neoViewModelMuzzleflash->m_iModelScale = 0.75; - } + neoViewModelMuzzleflash->m_bActive = false; + } + else if (neoWep->GetNeoWepBits() & (NEO_WEP_PZ | NEO_WEP_TACHI | NEO_WEP_KYLA)) + { + neoViewModelMuzzleflash->m_bActive = true; + neoViewModelMuzzleflash->m_nSkin = 1; + neoViewModelMuzzleflash->m_iAngleZ = 0; + neoViewModelMuzzleflash->m_iAngleZIncrement = -90; + neoViewModelMuzzleflash->m_iModelScale = 0.75; + } + else if (neoWep->GetNeoWepBits() & NEO_WEP_SUPA7) + { + neoViewModelMuzzleflash->m_bActive = true; + neoViewModelMuzzleflash->m_nSkin = 1; + neoViewModelMuzzleflash->m_iAngleZ = 0; + neoViewModelMuzzleflash->m_iAngleZIncrement = -90; + neoViewModelMuzzleflash->m_iModelScale = 1; + } + else if (neoWep->GetNeoWepBits() & (NEO_WEP_SRM | NEO_WEP_JITTE)) + { + neoViewModelMuzzleflash->m_bActive = true; + neoViewModelMuzzleflash->m_nSkin = 0; + neoViewModelMuzzleflash->m_iAngleZ = 0; + neoViewModelMuzzleflash->m_iAngleZIncrement = -90; + neoViewModelMuzzleflash->m_iModelScale = 0.75; + } + else if (neoWep->GetNeoWepBits() & (NEO_WEP_MX)) + { + neoViewModelMuzzleflash->m_bActive = true; + neoViewModelMuzzleflash->m_nSkin = 0; + neoViewModelMuzzleflash->m_iAngleZ = 0; + neoViewModelMuzzleflash->m_iAngleZIncrement = -95; + neoViewModelMuzzleflash->m_iModelScale = 0.6; + } + else + { + neoViewModelMuzzleflash->m_bActive = true; + neoViewModelMuzzleflash->m_nSkin = 0; + neoViewModelMuzzleflash->m_iAngleZ = 0; + neoViewModelMuzzleflash->m_iAngleZIncrement = -90; + neoViewModelMuzzleflash->m_iModelScale = 0.75; } } #endif // NEO diff --git a/mp/src/game/shared/neo/neo_predicted_viewmodel.cpp b/mp/src/game/shared/neo/neo_predicted_viewmodel.cpp index c870e7113..07e3cb3c2 100644 --- a/mp/src/game/shared/neo/neo_predicted_viewmodel.cpp +++ b/mp/src/game/shared/neo/neo_predicted_viewmodel.cpp @@ -17,7 +17,6 @@ #else #include "neo_player.h" #endif -#include "neo_predicted_viewmodel_muzzleflash.h" // memdbgon must be the last include file in a .cpp file!!! #include "tier0/memdbgon.h" diff --git a/mp/src/game/shared/neo/neo_predicted_viewmodel.h b/mp/src/game/shared/neo/neo_predicted_viewmodel.h index 49ee62866..8594a9c12 100644 --- a/mp/src/game/shared/neo/neo_predicted_viewmodel.h +++ b/mp/src/game/shared/neo/neo_predicted_viewmodel.h @@ -5,7 +5,6 @@ #endif #include "predicted_viewmodel.h" -#include "neo_predicted_viewmodel_muzzleflash.h" #ifdef CLIENT_DLL //#include "clienteffectprecachesystem.h" @@ -44,7 +43,6 @@ class CNEOPredictedViewModel : public CPredictedViewModel virtual int DrawModel(int flags); virtual RenderGroup_t GetRenderGroup(); - #endif #ifdef CLIENT_DLL diff --git a/mp/src/game/shared/neo/neo_predicted_viewmodel_muzzleflash.h b/mp/src/game/shared/neo/neo_predicted_viewmodel_muzzleflash.h index 32cc9fe49..43cea0ee5 100644 --- a/mp/src/game/shared/neo/neo_predicted_viewmodel_muzzleflash.h +++ b/mp/src/game/shared/neo/neo_predicted_viewmodel_muzzleflash.h @@ -11,6 +11,8 @@ #define CNEO_Player C_NEO_Player #endif +#define MUZZLE_FLASH_VIEW_MODEL_INDEX 1 + class CNEO_Player; class CNEOPredictedViewModelMuzzleFlash : public CPredictedViewModel { From f6b11286b57d1fb9e08c34a8d478917061c3bff5 Mon Sep 17 00:00:00 2001 From: AdamTadeusz Date: Tue, 27 Aug 2024 10:04:40 +0100 Subject: [PATCH 10/14] adjusted muzzle flash properties for some weapons --- mp/src/game/shared/baseplayer_shared.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/mp/src/game/shared/baseplayer_shared.cpp b/mp/src/game/shared/baseplayer_shared.cpp index dcbf8e79f..0932178ae 100644 --- a/mp/src/game/shared/baseplayer_shared.cpp +++ b/mp/src/game/shared/baseplayer_shared.cpp @@ -891,7 +891,7 @@ void CBasePlayer::UpdateMuzzleFlashProperties(CBaseCombatWeapon* pWeapon) neoViewModelMuzzleflash->m_bActive = true; neoViewModelMuzzleflash->m_nSkin = 1; neoViewModelMuzzleflash->m_iAngleZ = 0; - neoViewModelMuzzleflash->m_iAngleZIncrement = -90; + neoViewModelMuzzleflash->m_iAngleZIncrement = -100; neoViewModelMuzzleflash->m_iModelScale = 0.75; } else if (neoWep->GetNeoWepBits() & NEO_WEP_SUPA7) @@ -900,7 +900,7 @@ void CBasePlayer::UpdateMuzzleFlashProperties(CBaseCombatWeapon* pWeapon) neoViewModelMuzzleflash->m_nSkin = 1; neoViewModelMuzzleflash->m_iAngleZ = 0; neoViewModelMuzzleflash->m_iAngleZIncrement = -90; - neoViewModelMuzzleflash->m_iModelScale = 1; + neoViewModelMuzzleflash->m_iModelScale = 2; } else if (neoWep->GetNeoWepBits() & (NEO_WEP_SRM | NEO_WEP_JITTE)) { @@ -910,12 +910,12 @@ void CBasePlayer::UpdateMuzzleFlashProperties(CBaseCombatWeapon* pWeapon) neoViewModelMuzzleflash->m_iAngleZIncrement = -90; neoViewModelMuzzleflash->m_iModelScale = 0.75; } - else if (neoWep->GetNeoWepBits() & (NEO_WEP_MX)) + else if (neoWep->GetNeoWepBits() & (NEO_WEP_MX | NEO_WEP_AA13)) { neoViewModelMuzzleflash->m_bActive = true; neoViewModelMuzzleflash->m_nSkin = 0; neoViewModelMuzzleflash->m_iAngleZ = 0; - neoViewModelMuzzleflash->m_iAngleZIncrement = -95; + neoViewModelMuzzleflash->m_iAngleZIncrement = -100; neoViewModelMuzzleflash->m_iModelScale = 0.6; } else From 4f8b9d08bdb3c470d160fcab67e9880502ede151 Mon Sep 17 00:00:00 2001 From: AdamTadeusz Date: Tue, 27 Aug 2024 10:20:12 +0100 Subject: [PATCH 11/14] move custom muzzle world flash to neo_predicted_viewmodel --- mp/src/game/client/c_baseanimating.cpp | 15 -------------- .../shared/neo/neo_predicted_viewmodel.cpp | 20 +++++++++++++++++++ .../game/shared/neo/neo_predicted_viewmodel.h | 1 + 3 files changed, 21 insertions(+), 15 deletions(-) diff --git a/mp/src/game/client/c_baseanimating.cpp b/mp/src/game/client/c_baseanimating.cpp index 5a224e47f..428c87dd9 100644 --- a/mp/src/game/client/c_baseanimating.cpp +++ b/mp/src/game/client/c_baseanimating.cpp @@ -3391,20 +3391,6 @@ void C_BaseAnimating::ProcessMuzzleFlashEvent() { Vector vAttachment; QAngle dummyAngles; -#ifdef NEO - GetAttachment( 2, vAttachment, dummyAngles ); - - // Make a dlight - dlight_t* dl = effects->CL_AllocDlight(LIGHT_INDEX_MUZZLEFLASH + index); - dl->origin = vAttachment; - dl->radius = random->RandomInt(64, 96); - dl->decay = dl->radius / 0.1f; - dl->die = gpGlobals->curtime + 0.1f; - dl->color.r = 255; - dl->color.g = 192; - dl->color.b = 64; - dl->color.exponent = 5; -#else GetAttachment( 1, vAttachment, dummyAngles ); // Make an elight @@ -3417,7 +3403,6 @@ void C_BaseAnimating::ProcessMuzzleFlashEvent() el->color.g = 192; el->color.b = 64; el->color.exponent = 5; -#endif } } } diff --git a/mp/src/game/shared/neo/neo_predicted_viewmodel.cpp b/mp/src/game/shared/neo/neo_predicted_viewmodel.cpp index 07e3cb3c2..7d229ef5c 100644 --- a/mp/src/game/shared/neo/neo_predicted_viewmodel.cpp +++ b/mp/src/game/shared/neo/neo_predicted_viewmodel.cpp @@ -14,6 +14,8 @@ #include "model_types.h" #include "prediction.h" #include "viewrender.h" +#include "r_efx.h" +#include "dlight.h" #else #include "neo_player.h" #endif @@ -429,6 +431,24 @@ void CNEOPredictedViewModel::CalcViewModelView(CBasePlayer *pOwner, } #ifdef CLIENT_DLL +void CNEOPredictedViewModel::ProcessMuzzleFlashEvent() +{ + Vector vAttachment; + QAngle dummyAngles; + GetAttachment(2, vAttachment, dummyAngles); + + // Make a dlight + dlight_t* dl = effects->CL_AllocDlight(LIGHT_INDEX_MUZZLEFLASH + index); + dl->origin = vAttachment; + dl->radius = random->RandomInt(64, 96); + dl->decay = dl->radius / 0.1f; + dl->die = gpGlobals->curtime + 0.1f; + dl->color.r = 255; + dl->color.g = 192; + dl->color.b = 64; + dl->color.exponent = 5; +} + RenderGroup_t CNEOPredictedViewModel::GetRenderGroup() { auto pPlayer = static_cast(GetOwner()); diff --git a/mp/src/game/shared/neo/neo_predicted_viewmodel.h b/mp/src/game/shared/neo/neo_predicted_viewmodel.h index 8594a9c12..5fa8c4a71 100644 --- a/mp/src/game/shared/neo/neo_predicted_viewmodel.h +++ b/mp/src/game/shared/neo/neo_predicted_viewmodel.h @@ -41,6 +41,7 @@ class CNEOPredictedViewModel : public CPredictedViewModel virtual void ClientThink() override; virtual int DrawModel(int flags); + virtual void ProcessMuzzleFlashEvent() override; virtual RenderGroup_t GetRenderGroup(); #endif From 93a9ee20237ceef3c950d56aa385a8a6c8b6128b Mon Sep 17 00:00:00 2001 From: AdamTadeusz Date: Fri, 13 Sep 2024 12:04:02 +0100 Subject: [PATCH 12/14] merge master, do not network most of the muzzleflash properties --- .../shared/neo/neo_predicted_viewmodel_muzzleflash.cpp | 8 -------- .../game/shared/neo/neo_predicted_viewmodel_muzzleflash.h | 8 -------- 2 files changed, 16 deletions(-) diff --git a/mp/src/game/shared/neo/neo_predicted_viewmodel_muzzleflash.cpp b/mp/src/game/shared/neo/neo_predicted_viewmodel_muzzleflash.cpp index f2e6acf6d..b4a0e0829 100644 --- a/mp/src/game/shared/neo/neo_predicted_viewmodel_muzzleflash.cpp +++ b/mp/src/game/shared/neo/neo_predicted_viewmodel_muzzleflash.cpp @@ -15,16 +15,8 @@ IMPLEMENT_NETWORKCLASS_ALIASED(NEOPredictedViewModelMuzzleFlash, DT_NEOPredicted BEGIN_NETWORK_TABLE(CNEOPredictedViewModelMuzzleFlash, DT_NEOPredictedViewModelMuzzleFlash) #ifndef CLIENT_DLL SendPropEHandle(SENDINFO_NAME(m_hMoveParent, moveparent)), -SendPropBool(SENDINFO(m_bActive)), -SendPropInt(SENDINFO(m_iAngleZ)), -SendPropInt(SENDINFO(m_iAngleZIncrement)), -SendPropFloat(SENDINFO(m_iModelScale)), #else RecvPropInt(RECVINFO_NAME(m_hNetworkMoveParent, moveparent), 0, RecvProxy_IntToMoveParent), -RecvPropBool(RECVINFO(m_bActive)), -RecvPropInt(RECVINFO(m_iAngleZ)), -RecvPropInt(RECVINFO(m_iAngleZIncrement)), -RecvPropFloat(RECVINFO(m_iModelScale)), #endif END_NETWORK_TABLE() diff --git a/mp/src/game/shared/neo/neo_predicted_viewmodel_muzzleflash.h b/mp/src/game/shared/neo/neo_predicted_viewmodel_muzzleflash.h index 43cea0ee5..79aaf9c83 100644 --- a/mp/src/game/shared/neo/neo_predicted_viewmodel_muzzleflash.h +++ b/mp/src/game/shared/neo/neo_predicted_viewmodel_muzzleflash.h @@ -44,18 +44,10 @@ class CNEOPredictedViewModelMuzzleFlash : public CPredictedViewModel void Spawn(void); void Precache(void); - -#ifdef GAME_DLL - CNetworkVar(bool, m_bActive); - CNetworkVar(int, m_iAngleZ); - CNetworkVar(int, m_iAngleZIncrement); - CNetworkVar(float, m_iModelScale); -#else bool m_bActive; int m_iAngleZ; int m_iAngleZIncrement; float m_iModelScale; -#endif // GAME_DLL float m_flTimeSwitchOffMuzzleFlash; // If the server can fire a user's weapon (maybe some kind of server triggered weapon cook off or something), this will need to be networked too. }; From 6445f71110fe51c9e72161d74130bcaf2d8d14b5 Mon Sep 17 00:00:00 2001 From: AdamTadeusz Date: Mon, 16 Sep 2024 15:51:09 +0100 Subject: [PATCH 13/14] review suggestions, use setscale once now that initial weapon selection is communicated to client --- mp/src/game/server/neo/neo_player.cpp | 8 +++++++- mp/src/game/shared/baseplayer_shared.cpp | 14 +++++++------- mp/src/game/shared/neo/neo_predicted_viewmodel.h | 2 +- .../neo/neo_predicted_viewmodel_muzzleflash.cpp | 14 ++++---------- .../neo/neo_predicted_viewmodel_muzzleflash.h | 14 ++++++-------- 5 files changed, 25 insertions(+), 27 deletions(-) diff --git a/mp/src/game/server/neo/neo_player.cpp b/mp/src/game/server/neo/neo_player.cpp index 04e7f3898..8d30a8bed 100644 --- a/mp/src/game/server/neo/neo_player.cpp +++ b/mp/src/game/server/neo/neo_player.cpp @@ -1487,13 +1487,19 @@ void CNEO_Player::CreateViewModel( int index ) if ( !GetViewModel(MUZZLE_FLASH_VIEW_MODEL_INDEX)) { - CNEOPredictedViewModelMuzzleFlash* vmm = (CNEOPredictedViewModelMuzzleFlash*)CreateEntityByName("neo_predicted_viewmodel_muzzleflash"); + auto* vmm = (CNEOPredictedViewModelMuzzleFlash*)CreateEntityByName("neo_predicted_viewmodel_muzzleflash"); if (!vmm) + { + Assert(false); return; + } CBaseViewModel* vm = GetViewModel(); if (!vm) + { + Assert(false); return; + } vmm->SetAbsOrigin(vm->GetAbsOrigin()); vmm->SetOwner(this); diff --git a/mp/src/game/shared/baseplayer_shared.cpp b/mp/src/game/shared/baseplayer_shared.cpp index 0932178ae..50ee1962b 100644 --- a/mp/src/game/shared/baseplayer_shared.cpp +++ b/mp/src/game/shared/baseplayer_shared.cpp @@ -878,11 +878,11 @@ void CBasePlayer::UpdateMuzzleFlashProperties(CBaseCombatWeapon* pWeapon) if (!neoWep) return; - CNEOPredictedViewModelMuzzleFlash* neoViewModelMuzzleflash = static_cast(m_hViewModel[MUZZLE_FLASH_VIEW_MODEL_INDEX].Get()); + auto* neoViewModelMuzzleflash = static_cast(m_hViewModel[MUZZLE_FLASH_VIEW_MODEL_INDEX].Get()); if (!neoViewModelMuzzleflash) return; - if (neoWep->GetNeoWepBits() & (NEO_WEP_DETPACK | NEO_WEP_GHOST | NEO_WEP_FRAG_GRENADE | NEO_WEP_KNIFE | NEO_WEP_SMOKE_GRENADE | NEO_WEP_SUPPRESSED | NEO_WEP_EXPLOSIVE)) + if (neoWep->GetNeoWepBits() & (NEO_WEP_THROWABLE | NEO_WEP_GHOST | NEO_WEP_KNIFE | NEO_WEP_SUPPRESSED)) { neoViewModelMuzzleflash->m_bActive = false; } @@ -892,7 +892,7 @@ void CBasePlayer::UpdateMuzzleFlashProperties(CBaseCombatWeapon* pWeapon) neoViewModelMuzzleflash->m_nSkin = 1; neoViewModelMuzzleflash->m_iAngleZ = 0; neoViewModelMuzzleflash->m_iAngleZIncrement = -100; - neoViewModelMuzzleflash->m_iModelScale = 0.75; + neoViewModelMuzzleflash->SetModelScale(0.75); } else if (neoWep->GetNeoWepBits() & NEO_WEP_SUPA7) { @@ -900,7 +900,7 @@ void CBasePlayer::UpdateMuzzleFlashProperties(CBaseCombatWeapon* pWeapon) neoViewModelMuzzleflash->m_nSkin = 1; neoViewModelMuzzleflash->m_iAngleZ = 0; neoViewModelMuzzleflash->m_iAngleZIncrement = -90; - neoViewModelMuzzleflash->m_iModelScale = 2; + neoViewModelMuzzleflash->SetModelScale(2); } else if (neoWep->GetNeoWepBits() & (NEO_WEP_SRM | NEO_WEP_JITTE)) { @@ -908,7 +908,7 @@ void CBasePlayer::UpdateMuzzleFlashProperties(CBaseCombatWeapon* pWeapon) neoViewModelMuzzleflash->m_nSkin = 0; neoViewModelMuzzleflash->m_iAngleZ = 0; neoViewModelMuzzleflash->m_iAngleZIncrement = -90; - neoViewModelMuzzleflash->m_iModelScale = 0.75; + neoViewModelMuzzleflash->SetModelScale(0.75); } else if (neoWep->GetNeoWepBits() & (NEO_WEP_MX | NEO_WEP_AA13)) { @@ -916,7 +916,7 @@ void CBasePlayer::UpdateMuzzleFlashProperties(CBaseCombatWeapon* pWeapon) neoViewModelMuzzleflash->m_nSkin = 0; neoViewModelMuzzleflash->m_iAngleZ = 0; neoViewModelMuzzleflash->m_iAngleZIncrement = -100; - neoViewModelMuzzleflash->m_iModelScale = 0.6; + neoViewModelMuzzleflash->SetModelScale(0.6); } else { @@ -924,7 +924,7 @@ void CBasePlayer::UpdateMuzzleFlashProperties(CBaseCombatWeapon* pWeapon) neoViewModelMuzzleflash->m_nSkin = 0; neoViewModelMuzzleflash->m_iAngleZ = 0; neoViewModelMuzzleflash->m_iAngleZIncrement = -90; - neoViewModelMuzzleflash->m_iModelScale = 0.75; + neoViewModelMuzzleflash->SetModelScale(0.75); } } #endif // NEO diff --git a/mp/src/game/shared/neo/neo_predicted_viewmodel.h b/mp/src/game/shared/neo/neo_predicted_viewmodel.h index 5fa8c4a71..1df52a9c5 100644 --- a/mp/src/game/shared/neo/neo_predicted_viewmodel.h +++ b/mp/src/game/shared/neo/neo_predicted_viewmodel.h @@ -41,7 +41,7 @@ class CNEOPredictedViewModel : public CPredictedViewModel virtual void ClientThink() override; virtual int DrawModel(int flags); - virtual void ProcessMuzzleFlashEvent() override; + virtual void ProcessMuzzleFlashEvent() final override; virtual RenderGroup_t GetRenderGroup(); #endif diff --git a/mp/src/game/shared/neo/neo_predicted_viewmodel_muzzleflash.cpp b/mp/src/game/shared/neo/neo_predicted_viewmodel_muzzleflash.cpp index b4a0e0829..19233cb0a 100644 --- a/mp/src/game/shared/neo/neo_predicted_viewmodel_muzzleflash.cpp +++ b/mp/src/game/shared/neo/neo_predicted_viewmodel_muzzleflash.cpp @@ -27,7 +27,7 @@ END_PREDICTION_DATA() LINK_ENTITY_TO_CLASS(neo_predicted_viewmodel_muzzleflash, CNEOPredictedViewModelMuzzleFlash); -#define MUZZLE_FLASH_ENTITY_MODEL "models/effect/fpmf/fpmf01.mdl" +constexpr const char* MUZZLE_FLASH_ENTITY_MODEL = "models/effect/fpmf/fpmf01.mdl"; //----------------------------------------------------------------------------- // Purpose: Precache assets used by the entity @@ -47,10 +47,8 @@ void CNEOPredictedViewModelMuzzleFlash::Spawn(void) Precache(); SetModel(MUZZLE_FLASH_ENTITY_MODEL); SetSolid(SOLID_NONE); - AddEffects(EF_NOSHADOW); - AddEffects(EF_NORECEIVESHADOW); - RemoveEffects(EF_NODRAW); - RemoveEffects(EF_BONEMERGE); + AddEffects(EF_NOSHADOW | EF_NORECEIVESHADOW); + RemoveEffects(EF_NODRAW | EF_BONEMERGE); } #ifdef CLIENT_DLL @@ -65,9 +63,6 @@ int CNEOPredictedViewModelMuzzleFlash::DrawModel(int flags) if (vm == NULL) return -1; - if (m_iModelScale != GetModelScale()) - SetModelScale(m_iModelScale); // NEOTODO (Adam) model scale is a networked property in cbaseanimating, but for some reason its not being networked when set on the server side when initially spawning/respawning the player, so sometimes muzzle flash size can be incorrect if using SetModelScale in Weapon_Equip() - int iAttachment = vm->LookupAttachment("muzzle"); if (iAttachment < 0) return -1; @@ -81,8 +76,7 @@ int CNEOPredictedViewModelMuzzleFlash::DrawModel(int flags) SetAbsOrigin(localOrigin); SetAbsAngles(localAngle); - int ret = BaseClass::DrawModel(flags); - return ret; + return BaseClass::DrawModel(flags); } return -1; } diff --git a/mp/src/game/shared/neo/neo_predicted_viewmodel_muzzleflash.h b/mp/src/game/shared/neo/neo_predicted_viewmodel_muzzleflash.h index 79aaf9c83..14c5789c9 100644 --- a/mp/src/game/shared/neo/neo_predicted_viewmodel_muzzleflash.h +++ b/mp/src/game/shared/neo/neo_predicted_viewmodel_muzzleflash.h @@ -26,14 +26,13 @@ class CNEOPredictedViewModelMuzzleFlash : public CPredictedViewModel m_iAngleZ = 0; m_iAngleZIncrement = -5; m_flTimeSwitchOffMuzzleFlash = gpGlobals->curtime; - m_iModelScale = 1; } #ifdef CLIENT_DLL - ShadowType_t ShadowCastType() override { return SHADOWS_NONE; }; - RenderGroup_t GetRenderGroup() override { return RENDER_GROUP_VIEW_MODEL_TRANSLUCENT; }; - int DrawModel(int flags) override; - void ProcessMuzzleFlashEvent() override + virtual ShadowType_t ShadowCastType() final override { return SHADOWS_NONE; }; + virtual RenderGroup_t GetRenderGroup() final override { return RENDER_GROUP_VIEW_MODEL_TRANSLUCENT; }; + virtual int DrawModel(int flags) final override; + virtual void ProcessMuzzleFlashEvent() final override { if (!m_bActive) return; @@ -42,12 +41,11 @@ class CNEOPredictedViewModelMuzzleFlash : public CPredictedViewModel } #endif - void Spawn(void); - void Precache(void); + virtual void Spawn(void) override; + virtual void Precache(void) override; bool m_bActive; int m_iAngleZ; int m_iAngleZIncrement; - float m_iModelScale; float m_flTimeSwitchOffMuzzleFlash; // If the server can fire a user's weapon (maybe some kind of server triggered weapon cook off or something), this will need to be networked too. }; From b317181db7f7b1b57d01ae0cdbab798195c46d7f Mon Sep 17 00:00:00 2001 From: AdamTadeusz Date: Mon, 16 Sep 2024 17:31:57 +0100 Subject: [PATCH 14/14] unused define, neowepbits const --- mp/src/game/shared/baseplayer_shared.cpp | 11 ++++++----- .../shared/neo/neo_predicted_viewmodel_muzzleflash.h | 2 -- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/mp/src/game/shared/baseplayer_shared.cpp b/mp/src/game/shared/baseplayer_shared.cpp index 50ee1962b..ddc7ef790 100644 --- a/mp/src/game/shared/baseplayer_shared.cpp +++ b/mp/src/game/shared/baseplayer_shared.cpp @@ -882,11 +882,12 @@ void CBasePlayer::UpdateMuzzleFlashProperties(CBaseCombatWeapon* pWeapon) if (!neoViewModelMuzzleflash) return; - if (neoWep->GetNeoWepBits() & (NEO_WEP_THROWABLE | NEO_WEP_GHOST | NEO_WEP_KNIFE | NEO_WEP_SUPPRESSED)) + const auto neoWepBits = neoWep->GetNeoWepBits(); + if (neoWepBits & (NEO_WEP_THROWABLE | NEO_WEP_GHOST | NEO_WEP_KNIFE | NEO_WEP_SUPPRESSED)) { neoViewModelMuzzleflash->m_bActive = false; } - else if (neoWep->GetNeoWepBits() & (NEO_WEP_PZ | NEO_WEP_TACHI | NEO_WEP_KYLA)) + else if (neoWepBits & (NEO_WEP_PZ | NEO_WEP_TACHI | NEO_WEP_KYLA)) { neoViewModelMuzzleflash->m_bActive = true; neoViewModelMuzzleflash->m_nSkin = 1; @@ -894,7 +895,7 @@ void CBasePlayer::UpdateMuzzleFlashProperties(CBaseCombatWeapon* pWeapon) neoViewModelMuzzleflash->m_iAngleZIncrement = -100; neoViewModelMuzzleflash->SetModelScale(0.75); } - else if (neoWep->GetNeoWepBits() & NEO_WEP_SUPA7) + else if (neoWepBits & NEO_WEP_SUPA7) { neoViewModelMuzzleflash->m_bActive = true; neoViewModelMuzzleflash->m_nSkin = 1; @@ -902,7 +903,7 @@ void CBasePlayer::UpdateMuzzleFlashProperties(CBaseCombatWeapon* pWeapon) neoViewModelMuzzleflash->m_iAngleZIncrement = -90; neoViewModelMuzzleflash->SetModelScale(2); } - else if (neoWep->GetNeoWepBits() & (NEO_WEP_SRM | NEO_WEP_JITTE)) + else if (neoWepBits & (NEO_WEP_SRM | NEO_WEP_JITTE)) { neoViewModelMuzzleflash->m_bActive = true; neoViewModelMuzzleflash->m_nSkin = 0; @@ -910,7 +911,7 @@ void CBasePlayer::UpdateMuzzleFlashProperties(CBaseCombatWeapon* pWeapon) neoViewModelMuzzleflash->m_iAngleZIncrement = -90; neoViewModelMuzzleflash->SetModelScale(0.75); } - else if (neoWep->GetNeoWepBits() & (NEO_WEP_MX | NEO_WEP_AA13)) + else if (neoWepBits & (NEO_WEP_MX | NEO_WEP_AA13)) { neoViewModelMuzzleflash->m_bActive = true; neoViewModelMuzzleflash->m_nSkin = 0; diff --git a/mp/src/game/shared/neo/neo_predicted_viewmodel_muzzleflash.h b/mp/src/game/shared/neo/neo_predicted_viewmodel_muzzleflash.h index 14c5789c9..397ae99eb 100644 --- a/mp/src/game/shared/neo/neo_predicted_viewmodel_muzzleflash.h +++ b/mp/src/game/shared/neo/neo_predicted_viewmodel_muzzleflash.h @@ -8,12 +8,10 @@ #ifdef CLIENT_DLL #define CNEOPredictedViewModelMuzzleFlash C_NEOPredictedViewModelMuzzleFlash -#define CNEO_Player C_NEO_Player #endif #define MUZZLE_FLASH_VIEW_MODEL_INDEX 1 -class CNEO_Player; class CNEOPredictedViewModelMuzzleFlash : public CPredictedViewModel { DECLARE_CLASS(CNEOPredictedViewModelMuzzleFlash, CPredictedViewModel);