Closed Adrianilloo closed 5 years ago
It would be better to trace through to the desired grenade position to keep the behaviour of the grenade coming out a bit in front of the person, but back it out if need be to prevent it from passing through surfaces. If I recall correctly, CS:S or some other Source game's grenades did something like this.
Update: Finally I discovered an almost perfect fix from game code.
But now I'll be brief and just paste the patches here with explanatory comments for SP and MP branches separately, since there's an slight difference between them (different grenade model's origin). Fix for HL2MP:
--- a/mp/src/game/shared/hl2mp/weapon_frag.cpp
+++ b/mp/src/game/shared/hl2mp/weapon_frag.cpp
@@ -74,7 +74,8 @@ private:
void RollGrenade( CBasePlayer *pPlayer );
void LobGrenade( CBasePlayer *pPlayer );
// check a throw from vecSrc. If not valid, move the position back along the line to vecEye
- void CheckThrowPosition( CBasePlayer *pPlayer, const Vector &vecEye, Vector &vecSrc );
+ void CheckThrowPosition( CBasePlayer *pPlayer, const Vector &vecEye, Vector &vecSrc,
+ const QAngle& angles = vec3_angle );
CNetworkVar( bool, m_bRedraw ); //Draw the weapon again after throwing a grenade
@@ -392,12 +393,20 @@ void CWeaponFrag::ItemPostFrame( void )
}
// check a throw from vecSrc. If not valid, move the position back along the line to vecEye
-void CWeaponFrag::CheckThrowPosition( CBasePlayer *pPlayer, const Vector &vecEye, Vector &vecSrc )
+void CWeaponFrag::CheckThrowPosition( CBasePlayer *pPlayer, const Vector &vecEye, Vector &vecSrc, const QAngle& angles )
{
+ // Compute an extended AABB that takes into account the requested grenade rotation.
+ // This will prevent grenade from going through nearby solids when model initially intersects with any.
+ matrix3x4_t rotation;
+ AngleMatrix(angles, rotation);
+ Vector mins, maxs;
+ RotateAABB(rotation, -Vector(GRENADE_RADIUS + 2, GRENADE_RADIUS + 2, 2),
+ Vector(GRENADE_RADIUS + 2, GRENADE_RADIUS + 2, GRENADE_RADIUS * 2 + 2), mins, maxs);
+
trace_t tr;
- UTIL_TraceHull( vecEye, vecSrc, -Vector(GRENADE_RADIUS+2,GRENADE_RADIUS+2,GRENADE_RADIUS+2), Vector(GRENADE_RADIUS+2,GRENADE_RADIUS+2,GRENADE_RADIUS+2),
- pPlayer->PhysicsSolidMaskForEntity(), pPlayer, pPlayer->GetCollisionGroup(), &tr );
+ UTIL_TraceHull( vecEye, vecSrc, mins, maxs, pPlayer->PhysicsSolidMaskForEntity(),
+ pPlayer, pPlayer->GetCollisionGroup(), &tr );
if ( tr.DidHit() )
{
@@ -523,7 +532,6 @@ void CWeaponFrag::RollGrenade( CBasePlayer *pPlayer )
CrossProduct( tr.plane.normal, tangent, vecFacing );
}
vecSrc += (vecFacing * 18.0);
- CheckThrowPosition( pPlayer, pPlayer->WorldSpaceCenter(), vecSrc );
Vector vecThrow;
pPlayer->GetVelocity( &vecThrow, NULL );
@@ -532,6 +540,7 @@ void CWeaponFrag::RollGrenade( CBasePlayer *pPlayer )
QAngle orientation(0,pPlayer->GetLocalAngles().y,-90);
// roll it
AngularImpulse rotSpeed(0,0,720);
+ CheckThrowPosition( pPlayer, pPlayer->WorldSpaceCenter(), vecSrc, orientation );
CBaseGrenade *pGrenade = Fraggrenade_Create( vecSrc, orientation, vecThrow, rotSpeed, pPlayer, GRENADE_TIMER, false );
if ( pGrenade )
For HL2SP:
--- a/sp/src/game/server/hl2/weapon_frag.cpp
+++ b/sp/src/game/server/hl2/weapon_frag.cpp
@@ -60,7 +60,8 @@ private:
void RollGrenade( CBasePlayer *pPlayer );
void LobGrenade( CBasePlayer *pPlayer );
// check a throw from vecSrc. If not valid, move the position back along the line to vecEye
- void CheckThrowPosition( CBasePlayer *pPlayer, const Vector &vecEye, Vector &vecSrc );
+ void CheckThrowPosition( CBasePlayer *pPlayer, const Vector &vecEye, Vector &vecSrc,
+ const QAngle& angles = vec3_angle );
bool m_bRedraw; //Draw the weapon again after throwing a grenade
@@ -367,12 +368,20 @@ void CWeaponFrag::ItemPostFrame( void )
}
// check a throw from vecSrc. If not valid, move the position back along the line to vecEye
-void CWeaponFrag::CheckThrowPosition( CBasePlayer *pPlayer, const Vector &vecEye, Vector &vecSrc )
+void CWeaponFrag::CheckThrowPosition( CBasePlayer *pPlayer, const Vector &vecEye, Vector &vecSrc, const QAngle& angles )
{
+ // Compute an extended AABB that takes into account the requested grenade rotation.
+ // This will prevent grenade from going through nearby solids when model initially intersects with any.
+ matrix3x4_t rotation;
+ AngleMatrix(angles, rotation);
+ Vector mins, maxs;
+ RotateAABB(rotation, -Vector(GRENADE_RADIUS + 2, GRENADE_RADIUS + 2, GRENADE_RADIUS + 2),
+ Vector(GRENADE_RADIUS + 2, GRENADE_RADIUS + 2, GRENADE_RADIUS + 2), mins, maxs);
+
trace_t tr;
- UTIL_TraceHull( vecEye, vecSrc, -Vector(GRENADE_RADIUS+2,GRENADE_RADIUS+2,GRENADE_RADIUS+2), Vector(GRENADE_RADIUS+2,GRENADE_RADIUS+2,GRENADE_RADIUS+2),
- pPlayer->PhysicsSolidMaskForEntity(), pPlayer, pPlayer->GetCollisionGroup(), &tr );
+ UTIL_TraceHull( vecEye, vecSrc, mins, maxs, pPlayer->PhysicsSolidMaskForEntity(),
+ pPlayer, pPlayer->GetCollisionGroup(), &tr );
if ( tr.DidHit() )
{
@@ -459,7 +468,6 @@ void CWeaponFrag::RollGrenade( CBasePlayer *pPlayer )
CrossProduct( tr.plane.normal, tangent, vecFacing );
}
vecSrc += (vecFacing * 18.0);
- CheckThrowPosition( pPlayer, pPlayer->WorldSpaceCenter(), vecSrc );
Vector vecThrow;
pPlayer->GetVelocity( &vecThrow, NULL );
@@ -468,6 +476,7 @@ void CWeaponFrag::RollGrenade( CBasePlayer *pPlayer )
QAngle orientation(0,pPlayer->GetLocalAngles().y,-90);
// roll it
AngularImpulse rotSpeed(0,0,720);
+ CheckThrowPosition( pPlayer, pPlayer->WorldSpaceCenter(), vecSrc, orientation );
Fraggrenade_Create( vecSrc, orientation, vecThrow, rotSpeed, pPlayer, GRENADE_TIMER, false );
WeaponSound( SPECIAL1 );
These changes are applied to MP and SP. Shortly,
YouTube: HL2MP grenade fixes (SSDK2013)
EDIT