From 98d7380b229d8603dadffa0351497c5c1ea59ca8 Mon Sep 17 00:00:00 2001 From: Alice Date: Sat, 2 May 2026 23:59:47 -0400 Subject: [PATCH 1/5] Add color customization for physgun beam and model Signed-off-by: Alice --- src/game/client/jbmod/c_weapon_physgun.cpp | 117 ++++++++++++++++++++- 1 file changed, 116 insertions(+), 1 deletion(-) diff --git a/src/game/client/jbmod/c_weapon_physgun.cpp b/src/game/client/jbmod/c_weapon_physgun.cpp index a6e19902952..9124e60fdff 100644 --- a/src/game/client/jbmod/c_weapon_physgun.cpp +++ b/src/game/client/jbmod/c_weapon_physgun.cpp @@ -12,10 +12,19 @@ #include "c_weapon__stubs.h" #include "clienteffectprecachesystem.h" #include "c_jbmod_player.h" +#include "c_baseplayer.h" +#include "usercmd.h" +#include "materialsystem/imaterial.h" +#include "materialsystem/imaterialvar.h" + // memdbgon must be the last include file in a .cpp file!!! #include "tier0/memdbgon.h" +ConVar physgun_beam_color( "physgun_beam_color", "255 255 255", FCVAR_ARCHIVE ); +ConVar physgun_model_color( "physgun_model_color", "255 0 255", FCVAR_ARCHIVE ); + + CLIENTEFFECT_REGISTER_BEGIN( PrecacheEffectGravityGun ) CLIENTEFFECT_MATERIAL( "sprites/physbeam" ) CLIENTEFFECT_REGISTER_END() @@ -80,9 +89,88 @@ class C_WeaponGravityGun : public C_BaseCombatWeapon return BaseClass::KeyInput( down, keynum, pszCurrentBinding ); } + void CreateMove( float flInputSampleTime, CUserCmd *pCmd, const QAngle &vecOldViewAngles ) + { + BaseClass::CreateMove( flInputSampleTime, pCmd, vecOldViewAngles ); + + if ( !pCmd ) + return; + + C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer(); + if ( !pPlayer ) + return; + + if ( pPlayer->GetActiveWeapon() != this ) + return; + + if ( !m_beam.m_active ) + return; + + if ( !( pCmd->buttons & IN_USE ) ) + return; + + const short nMouseX = pCmd->mousedx; + const short nMouseY = pCmd->mousedy; + if ( nMouseX == 0 && nMouseY == 0 ) + return; + + // Use the raw mouse deltas for server-side physgun rotation, but keep the local + // camera from turning while we're in rotate mode. + pCmd->mousedx = nMouseX; + pCmd->mousedy = nMouseY; + pCmd->viewangles = vecOldViewAngles; + QAngle localViewAngles = vecOldViewAngles; + engine->SetViewAngles( localViewAngles ); + } + +static void ApplyPhysgunModelColor() +{ + int ir = 255, ig = 0, ib = 255; + + if ( sscanf( physgun_model_color.GetString(), "%d %d %d", &ir, &ig, &ib ) != 3 ) + return; + + ir = clamp( ir, 0, 255 ); + ig = clamp( ig, 0, 255 ); + ib = clamp( ib, 0, 255 ); + + float r = ir / 255.0f; + float g = ig / 255.0f; + float b = ib / 255.0f; + + + +// Basically the only way I could really think of, of doing this: + + IMaterial *pMat = materials->FindMaterial( + "models/weapons/v_physcannon/v_superphyscannon_sheet", + TEXTURE_GROUP_MODEL + ); + + if ( !pMat || pMat->IsErrorMaterial() ) + + return; + + bool found = false; + IMaterialVar *pTint = pMat->FindVar( "$selfillumtint", &found ); + + if ( found && pTint ) + { + + pTint->SetVecValue( r, g, b ); + } +} + + + + + void OnDataChanged( DataUpdateType_t updateType ) { + + BaseClass::OnDataChanged( updateType ); + ApplyPhysgunModelColor(); m_beam.Update( this ); } @@ -135,6 +223,9 @@ void C_BeamQuadratic::Update( C_BaseEntity *pOwner ) } + + + int C_BeamQuadratic::DrawModel( int ) { Vector points[3]; @@ -149,6 +240,10 @@ int C_BeamQuadratic::DrawModel( int ) return 0; pEnt->GetAttachment( 1, points[0], tmpAngle ); + + + + points[1] = 0.5 * ( m_targetPosition + points[0] ); // a little noise 11t & 13t should be somewhat non-periodic looking @@ -157,13 +252,32 @@ int C_BeamQuadratic::DrawModel( int ) IMaterial *pMat = materials->FindMaterial( "sprites/physbeam", TEXTURE_GROUP_CLIENT_EFFECTS ); Vector color; + if ( m_glueTouching ) { color.Init( 1, 0, 0 ); } else { - color.Init( 1, 1, 1 ); + int ir = 255, ig = 255, ib = 255; + + + if ( sscanf( physgun_beam_color.GetString(), "%d %d %d", &ir, &ig, &ib ) != 3 ) + { + ir = ig = ib = 255; + } + + + ir = clamp( ir, 0, 255 ); + ig = clamp( ig, 0, 255 ); + ib = clamp( ib, 0, 255 ); + + + float r = ir / 255.0f; + float g = ig / 255.0f; + float b = ib / 255.0f; + + color.Init( r, g, b ); } float scrollOffset = gpGlobals->curtime - (int)gpGlobals->curtime; @@ -179,3 +293,4 @@ const matrix3x4_t &C_BeamQuadratic::RenderableToWorldTransform() AngleMatrix( GetRenderAngles(), GetRenderOrigin(), mat ); return mat; } + From 0cadbe1b9fe440721bd4c678715a5f7c91a67236 Mon Sep 17 00:00:00 2001 From: Alice Date: Fri, 19 Jun 2026 10:20:36 -0400 Subject: [PATCH 2/5] Improve comments in c_weapon_physgun.cpp Refactor comments for clarity and maintainability. Signed-off-by: Alice --- src/game/client/jbmod/c_weapon_physgun.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/game/client/jbmod/c_weapon_physgun.cpp b/src/game/client/jbmod/c_weapon_physgun.cpp index 9124e60fdff..8c34be0a400 100644 --- a/src/game/client/jbmod/c_weapon_physgun.cpp +++ b/src/game/client/jbmod/c_weapon_physgun.cpp @@ -140,7 +140,7 @@ static void ApplyPhysgunModelColor() -// Basically the only way I could really think of, of doing this: + IMaterial *pMat = materials->FindMaterial( "models/weapons/v_physcannon/v_superphyscannon_sheet", @@ -261,18 +261,18 @@ int C_BeamQuadratic::DrawModel( int ) { int ir = 255, ig = 255, ib = 255; - + // Try to read 3 integers if ( sscanf( physgun_beam_color.GetString(), "%d %d %d", &ir, &ig, &ib ) != 3 ) { - ir = ig = ib = 255; + ir = ig = ib = 255; // fallback to white } - + // Clamp to valid 0–255 range ir = clamp( ir, 0, 255 ); ig = clamp( ig, 0, 255 ); ib = clamp( ib, 0, 255 ); - + // Convert to 0.0–1.0 float r = ir / 255.0f; float g = ig / 255.0f; float b = ib / 255.0f; From a043ac31d0e444b7b3284be3c20666781c6c7adb Mon Sep 17 00:00:00 2001 From: Alice Date: Fri, 19 Jun 2026 10:22:12 -0400 Subject: [PATCH 3/5] Enhance physgun functionality Added new ConVars for rotation sensitivity and sound control. Increased MAX_PELLETS limit and added comments for clarity. Signed-off-by: Alice --- src/game/server/jbmod/weapon_physgun.cpp | 195 ++++++++++++++++------- 1 file changed, 139 insertions(+), 56 deletions(-) diff --git a/src/game/server/jbmod/weapon_physgun.cpp b/src/game/server/jbmod/weapon_physgun.cpp index da82a27ed4d..84df57104be 100644 --- a/src/game/server/jbmod/weapon_physgun.cpp +++ b/src/game/server/jbmod/weapon_physgun.cpp @@ -23,6 +23,7 @@ #include "SoundEmitterSystem/isoundemittersystembase.h" #include "ai_basenpc.h" #include "physics_prop_ragdoll.h" +#include "usercmd.h" // memdbgon must be the last include file in a .cpp file!!! #include "tier0/memdbgon.h" @@ -33,11 +34,14 @@ ConVar phys_gunforce( "phys_gunforce", "20e20", FCVAR_REPLICATED | FCVAR_NOTIFY ConVar phys_guntorque( "phys_guntorque", "100", FCVAR_REPLICATED | FCVAR_NOTIFY ); ConVar phys_gunglueradius( "phys_gunglueradius", "128", FCVAR_REPLICATED | FCVAR_NOTIFY ); ConVar phys_gunjank( "phys_gunjank", "0", FCVAR_REPLICATED | FCVAR_NOTIFY ); +ConVar phys_gunrotate_sensitivity( "phys_gunrotate_sensitivity", "0.5", FCVAR_REPLICATED | FCVAR_NOTIFY ); +ConVar phys_gunsounds("phys_gunsounds", "1", FCVAR_ARCHIVE); + static int g_physgunBeam; #define PHYSGUN_BEAM_SPRITE "sprites/physbeam.vmt" -#define MAX_PELLETS 512 +#define MAX_PELLETS 2048 #define MAX_FREEZE 2048 class CWeaponGravityGun; @@ -199,6 +203,7 @@ class CGravControllerPoint : public IMotionEvent } void SetTargetOrientation( const QAngle &targetOrientation ) { + m_targetRotation = targetOrientation; m_shadow.targetRotation = targetOrientation; m_timeToArrive = gpGlobals->frametime; @@ -300,12 +305,12 @@ void CGravControllerPoint::AttachEntity( CBasePlayer *pPlayer, CBaseEntity *pEnt { if ( phys_gunjank.GetFloat() == 0 ) { - Vector vposition; - QAngle vangles; - pPhys->GetPosition( &vposition, &vangles ); - Pickup_GetPreferredCarryAngles( pEntity, pPlayer, pPlayer->EntityToWorldTransform(), vangles ); - m_controller = physenv->CreateMotionController( this ); - m_controller->AttachObject( pPhys, true ); + Vector vposition; // We first get the position and angles of the prop + QAngle vangles; // THen angles of set prop + pPhys->GetPosition( &vposition, &vangles ); // Then we get the position + Pickup_GetPreferredCarryAngles( pEntity, pPlayer, pPlayer->EntityToWorldTransform(), vangles ); // Get perfered carry angles + m_controller = physenv->CreateMotionController( this ); // Create a motion controller to control the motion of the prop + m_controller->AttachObject( pPhys, true ); // Attach the prop m_attachedEntity = pEntity; pPhys->Wake(); PhysSetGameFlags( pPhys, FVPHYSICS_PLAYER_HELD ); @@ -717,6 +722,11 @@ class CWeaponGravityGun : public CBaseCombatWeapon int m_freezeCount; int m_objectPelletCount; + QAngle m_lastViewAngles; + QAngle m_rotateStartObjectAngles; + bool m_wasRotating; + + int m_pelletHeld; int m_pelletAttract; float m_glueTime; @@ -800,10 +810,12 @@ enum physgun_soundIndex { SI_LOCKEDON = 0, SI_SCANNING = 1, SI_LIGHTOBJECT = 2, CWeaponGravityGun::CWeaponGravityGun() { - m_active = false; - m_bFiresUnderwater = true; - m_pelletAttract = -1; - m_pelletHeld = -1; + m_active = false; + m_bFiresUnderwater = true; + m_pelletAttract = -1; + m_pelletHeld = -1; + + m_wasRotating = false; } //========================================================= @@ -867,17 +879,17 @@ void CWeaponGravityGun::EffectUpdate( void ) if ( !pOwner ) return; - pOwner->EyeVectors( &forward, &right, NULL ); + pOwner->EyeVectors( &forward, &right, NULL ); // First we get the eye vectors - start = pOwner->Weapon_ShootPosition(); - Vector end = start + forward * 4096; + start = pOwner->Weapon_ShootPosition(); // Then we get the weapon shoot position where the physics gun beam is aimming + Vector end = start + forward * 4096; // Then the end is set, the end position of the player's current view where they are aimming times 4096 for some reason UTIL_TraceLine( start, end, MASK_SHOT, pOwner, COLLISION_GROUP_NONE, &tr ); end = tr.endpos; float distance = tr.fraction * 4096; if ( tr.fraction != 1 ) { - // too close to the player, drop the object + // too close to the player, drop the object Should I Remove this? if ( distance < 36 ) { DetachObject(); @@ -896,18 +908,14 @@ void CWeaponGravityGun::EffectUpdate( void ) m_lastYaw = pOwner->EyeAngles().y; } - // Add the incremental player yaw to the target transform - if ( phys_gunjank.GetFloat() > 0 ) - { - matrix3x4_t curMatrix, incMatrix, nextMatrix; - AngleMatrix( m_gravCallback.m_targetRotation, curMatrix ); - AngleMatrix( QAngle( 0, pOwner->EyeAngles().y - m_lastYaw, 0 ), incMatrix ); - ConcatTransforms( incMatrix, curMatrix, nextMatrix ); - MatrixAngles( nextMatrix, m_gravCallback.m_targetRotation ); - m_lastYaw = pOwner->EyeAngles().y; - } - CBaseEntity *pObject = m_hObject; + const CUserCmd *pCmd = pOwner->GetCurrentUserCommand(); + + + + + + if ( pObject ) { if ( phys_gunjank.GetFloat() == 0 ) @@ -943,31 +951,78 @@ void CWeaponGravityGun::EffectUpdate( void ) } Vector newPosition = start + forward * m_distance; - // 24 is a little larger than 16 * sqrt(2) (extent of player bbox) - // HACKHACK: We do this so we can "ignore" the player and the object we're manipulating - // If we had a filter for tracelines, we could simply filter both ents and start from "start" - Vector awayfromPlayer = start + forward * 24; - UTIL_TraceLine( start, awayfromPlayer, MASK_SOLID, pOwner, COLLISION_GROUP_NONE, &tr ); - if ( tr.fraction == 1 ) - { - UTIL_TraceLine( awayfromPlayer, newPosition, MASK_SOLID, pObject, COLLISION_GROUP_NONE, &tr ); - Vector dir = tr.endpos - newPosition; - float distance = VectorNormalize( dir ); - float maxDist = m_gravCallback.m_maxVel * gpGlobals->frametime; - if ( distance > maxDist ) - { - newPosition += dir * maxDist; - } - else - { - newPosition = tr.endpos; - } - } - else - { - newPosition = tr.endpos; - } + +Vector awayfromPlayer = start + forward * 24; + +UTIL_TraceLine( start, awayfromPlayer, MASK_SOLID, pOwner, COLLISION_GROUP_NONE, &tr ); + +if ( tr.fraction == 1 ) +{ + UTIL_TraceLine( awayfromPlayer, newPosition, MASK_SOLID, pObject, COLLISION_GROUP_NONE, &tr ); + + Vector dir = tr.endpos - newPosition; + float distance = VectorNormalize( dir ); + float maxDist = m_gravCallback.m_maxVel * gpGlobals->frametime; + + + + if ( distance > maxDist ) + newPosition += dir * maxDist; + else + newPosition = tr.endpos; +} +else +{ + newPosition = tr.endpos; +} + + m_gravCallback.SetTargetPosition( newPosition ); + +bool bRotateMode = ( pObject && ( pOwner->m_nButtons & IN_USE ) && pCmd != NULL ); + +if ( bRotateMode && !m_wasRotating ) +{ + m_lastViewAngles = pOwner->EyeAngles(); + m_rotateStartObjectAngles = m_gravCallback.m_targetRotation; + + m_wasRotating = true; +} +else if ( !bRotateMode ) +{ + m_wasRotating = false; +} + + + + +if ( bRotateMode ) +{ + float flRotateSensitivity = phys_gunrotate_sensitivity.GetFloat(); + + float flPitchDelta = (float)pCmd->mousedy * flRotateSensitivity; + float flYawDelta = -(float)pCmd->mousedx * flRotateSensitivity; + + flPitchDelta = clamp( flPitchDelta, -8.0f, 8.0f ); + flYawDelta = clamp( flYawDelta, -8.0f, 8.0f ); + + QAngle rotateDelta; + rotateDelta.Init( flPitchDelta, flYawDelta, 0.0f ); + + matrix3x4_t curMatrix, incMatrix, nextMatrix; + + AngleMatrix( m_gravCallback.m_targetRotation, curMatrix ); + AngleMatrix( rotateDelta, incMatrix ); + + ConcatTransforms( curMatrix, incMatrix, nextMatrix ); + + MatrixAngles( nextMatrix, m_gravCallback.m_targetRotation ); + + m_gravCallback.SetTargetOrientation( m_gravCallback.m_targetRotation ); +} + + + CreatePelletAttraction( phys_gunglueradius.GetFloat(), pObject ); @@ -998,7 +1053,7 @@ void CWeaponGravityGun::EffectUpdate( void ) } } - m_gravCallback.SetTargetPosition( newPosition ); + Vector dir = ( newPosition - pObject->GetLocalOrigin() ); m_movementLength = dir.Length(); } @@ -1018,12 +1073,25 @@ void CWeaponGravityGun::EffectUpdate( void ) m_gravCallback.ClearAutoAlign(); } + + + NetworkStateChanged(); } void CWeaponGravityGun::SoundCreate( void ) { + + if(phys_gunsounds.GetFloat() == 0) + { + return; + } + + m_soundState = SS_SCANNING; + + + SoundStart(); } @@ -1078,6 +1146,13 @@ static float UTIL_LineFraction( float value, float low, float high, float scale void CWeaponGravityGun::SoundStart( void ) { + + if(phys_gunsounds.GetFloat() == 0) + { + return; + } + + CPASAttenuationFilter filter( GetOwner() ); filter.MakeReliable(); @@ -1106,6 +1181,13 @@ void CWeaponGravityGun::SoundUpdate( void ) { int newState; + if(phys_gunsounds.GetFloat() == 0) + { + return; + } + + + if ( m_hObject ) newState = SS_LOCKEDON; else @@ -1446,16 +1528,16 @@ void CWeaponGravityGun::DetachObject( void ) void CWeaponGravityGun::AttachObject( CBaseEntity *pObject, const Vector &start, const Vector &end, float distance ) { - CBasePlayer *pOwner = ToBasePlayer( GetOwner() ); + CBasePlayer *pOwner = ToBasePlayer( GetOwner() ); // Make sure it's a player that owns this if ( !pOwner ) return; - m_useDown = false; + m_useDown = false; // Use is not down IPhysicsObject *pPhysics = pObject ? ( pObject->VPhysicsGetObject() ) : NULL; - if ( pPhysics && pObject->GetMoveType() == MOVETYPE_VPHYSICS ) + if ( pPhysics && pObject->GetMoveType() == MOVETYPE_VPHYSICS ) // If it's prop_physics { - pPhysics->EnableMotion( true ); - SortFreezeList(); + pPhysics->EnableMotion( true ); // Enable motion true + SortFreezeList(); // Sort the freeze list of props if ( pObject->GetCollisionGroup() == COLLISION_GROUP_DEBRIS ) pObject->SetCollisionGroup( COLLISION_GROUP_INTERACTIVE_DEBRIS ); @@ -1715,3 +1797,4 @@ bool CWeaponGravityGun::Reload( void ) return false; } + From 62467ef66d65a309df4739c1f0b819f670e37c15 Mon Sep 17 00:00:00 2001 From: Alice Date: Fri, 19 Jun 2026 12:04:24 -0400 Subject: [PATCH 4/5] Reduce MAX_PELLETS from 2048 to 512 Signed-off-by: Alice --- src/game/server/jbmod/weapon_physgun.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/game/server/jbmod/weapon_physgun.cpp b/src/game/server/jbmod/weapon_physgun.cpp index 84df57104be..4f76e8ba1c7 100644 --- a/src/game/server/jbmod/weapon_physgun.cpp +++ b/src/game/server/jbmod/weapon_physgun.cpp @@ -41,7 +41,7 @@ ConVar phys_gunsounds("phys_gunsounds", "1", FCVAR_ARCHIVE); static int g_physgunBeam; #define PHYSGUN_BEAM_SPRITE "sprites/physbeam.vmt" -#define MAX_PELLETS 2048 +#define MAX_PELLETS 512 #define MAX_FREEZE 2048 class CWeaponGravityGun; From 2e1827bb25f85237d8bef9e35066a548d3d727ec Mon Sep 17 00:00:00 2001 From: Alice Date: Sat, 20 Jun 2026 07:56:12 -0400 Subject: [PATCH 5/5] Re-add physgun_draw_beam Re-added physgun_draw_beam Signed-off-by: Alice --- src/game/client/jbmod/c_weapon_physgun.cpp | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/game/client/jbmod/c_weapon_physgun.cpp b/src/game/client/jbmod/c_weapon_physgun.cpp index 8c34be0a400..21d1dc193eb 100644 --- a/src/game/client/jbmod/c_weapon_physgun.cpp +++ b/src/game/client/jbmod/c_weapon_physgun.cpp @@ -23,7 +23,7 @@ ConVar physgun_beam_color( "physgun_beam_color", "255 255 255", FCVAR_ARCHIVE ); ConVar physgun_model_color( "physgun_model_color", "255 0 255", FCVAR_ARCHIVE ); - +ConVar physgun_draw_beam("physgun_draw_beam", "1", FCVAR_ARCHIVE); CLIENTEFFECT_REGISTER_BEGIN( PrecacheEffectGravityGun ) CLIENTEFFECT_MATERIAL( "sprites/physbeam" ) @@ -250,8 +250,18 @@ int C_BeamQuadratic::DrawModel( int ) //points[1].z += 4*sin( gpGlobals->curtime*11 ) + 5*cos( gpGlobals->curtime*13 ); points[2] = m_worldPosition; + + if (physgun_draw_beam.GetFloat() == 0) + { + return 0; + } + IMaterial *pMat = materials->FindMaterial( "sprites/physbeam", TEXTURE_GROUP_CLIENT_EFFECTS ); Vector color; + + + + if ( m_glueTouching ) {