diff --git a/Classes/ST_Mutator.uc b/Classes/ST_Mutator.uc index 4c9dfe6..12925fb 100644 --- a/Classes/ST_Mutator.uc +++ b/Classes/ST_Mutator.uc @@ -1053,9 +1053,27 @@ final function EnhancedHurtRadius( Source.bHurtEntry = false; } -function bool CheckHeadshot(Pawn P, vector HitLocation, vector Direction) { - local float OffsetZ; +function float GetPawnDuckFraction(Pawn P) { + local bbPlayer bbP; + bbP = bbPlayer(P); + if (bbP != none) { + return FClamp(bbP.DuckFraction, 0.0, 1.0); + } else { + return FClamp(1.0 - (P.EyeHeight / P.default.BaseEyeHeight), 0.0, 1.0); + } +} + +function float GetPawnBodyHalfHeight(Pawn P, float DuckFrac) { + return Lerp(DuckFrac, + P.CollisionHeight - WeaponSettings.HeadHalfHeight, + (1.3 * 0.5)*P.CollisionHeight + ); +} + +function bool CheckHeadShot(Pawn P, vector HitLocation, vector Direction) { local bbPlayer bbP; + local float DuckFrac; + local float BodyHalfHeight, HeadHalfHeight; local ST_HitTestHelper HitActor; local vector HitLoc, HitNorm; @@ -1067,21 +1085,75 @@ function bool CheckHeadshot(Pawn P, vector HitLocation, vector Direction) { if (WeaponSettings.bEnhancedHeadshotDetection == false) return (HitLocation.Z - P.Location.Z > 0.62 * P.CollisionHeight); + if (HitLocation.Z - P.Location.Z <= 0.3 * P.CollisionHeight) + return false; + if (CollChecker == none || CollChecker.bDeleteMe) { CollChecker = Spawn(class'ST_HitTestHelper',self, , P.Location); CollChecker.bCollideWorld = false; } - bbP = bbPlayer(P); - if (bbP != none) { - OffsetZ = Lerp(bbP.DuckFraction, WeaponSettings.HeadOffsetZ, WeaponSettings.HeadDuckOffsetZ); - } else { - OffsetZ = Lerp(P.EyeHeight / P.default.BaseEyeHeight, WeaponSettings.HeadDuckOffsetZ, WeaponSettings.HeadOffsetZ); - } + DuckFrac = GetPawnDuckFraction(P); + BodyHalfHeight = GetPawnBodyHalfHeight(P, DuckFrac); + HeadHalfHeight = Lerp(DuckFrac, + WeaponSettings.HeadHalfHeight, + 0 + ); CollChecker.SetCollision(true, false, false); CollChecker.SetCollisionSize(WeaponSettings.HeadRadius, WeaponSettings.HeadHalfHeight); - CollChecker.SetLocation(P.Location + vect(0,0,1)*WeaponSettings.HeadOffsetZ); + CollChecker.SetLocation(P.Location + vect(0,0,1)*(BodyHalfHeight + HeadHalfHeight)); + + Result = false; + + foreach TraceActors( + class'ST_HitTestHelper', + HitActor, HitLoc, HitNorm, + HitLocation + Direction * (P.CollisionRadius + P.CollisionHeight), + HitLocation - Direction * (P.CollisionRadius + P.CollisionHeight) + ) { + if (HitActor == CollChecker) { + Result = true; + break; + } + } + + CollChecker.SetCollision(false, false, false); + + return Result; +} + +function bool CheckBodyShot(Pawn P, vector HitLocation, vector Direction) { + local float DuckFrac; + local float HalfHeight; + local float OffsetZ; + local bbPlayer bbP; + + local ST_HitTestHelper HitActor; + local vector HitLoc, HitNorm; + local bool Result; + + if (P == none) + return false; + + if (WeaponSettings.bEnhancedHeadshotDetection == false) + return CheckHeadShot(P, HitLocation, Direction) == false; + + if (CollChecker == none || CollChecker.bDeleteMe) { + CollChecker = Spawn(class'ST_HitTestHelper',self, , P.Location); + CollChecker.bCollideWorld = false; + } + + DuckFrac = GetPawnDuckFraction(P); + HalfHeight = GetPawnBodyHalfHeight(P, DuckFrac); + OffsetZ = Lerp(DuckFrac, + -WeaponSettings.HeadHalfHeight, + -(0.7 * 0.5)*P.CollisionHeight + ); + + CollChecker.SetCollision(true, false, false); + CollChecker.SetCollisionSize(P.CollisionRadius, HalfHeight); + CollChecker.SetLocation(P.Location + vect(0,0,1)*OffsetZ); Result = false; diff --git a/Classes/ST_Razor2.uc b/Classes/ST_Razor2.uc index a4f465a..0f01f94 100644 --- a/Classes/ST_Razor2.uc +++ b/Classes/ST_Razor2.uc @@ -22,39 +22,37 @@ simulated function PostBeginPlay() auto state Flying { - simulated function ProcessTouch (Actor Other, Vector HitLocation) - { - if ( bCanHitInstigator || (Other != Instigator) ) - { - if ( Role == ROLE_Authority ) - { - if ( Other.bIsPawn && STM.CheckHeadshot(Pawn(Other), HitLocation, Normal(Velocity)) - && (!Instigator.IsA('Bot') || !Bot(Instigator).bNovice) ) - { + simulated function ProcessTouch (Actor Other, Vector HitLocation) { + local vector Dir; + + Dir = Normal(Velocity); + if (bCanHitInstigator || (Other != Instigator)) { + if (Role == ROLE_Authority) { + if (Other.bIsPawn && STM.CheckHeadshot(Pawn(Other), HitLocation, Dir) && + (!Instigator.IsA('Bot') || !Bot(Instigator).bNovice) + ) { STM.PlayerHit(Instigator, 11, True); // 11 = Ripper Primary Headshot Other.TakeDamage( STM.WeaponSettings.RipperHeadshotDamage, Instigator, HitLocation, - STM.WeaponSettings.RipperHeadshotMomentum * MomentumTransfer * Normal(Velocity), + STM.WeaponSettings.RipperHeadshotMomentum * MomentumTransfer * Dir, 'decapitated' ); STM.PlayerClear(); - } - else - { + } else if (Other.bIsPawn == false || STM.CheckBodyShot(Pawn(Other), HitLocation, Dir)) { STM.PlayerHit(Instigator, 11, False); // 11 = Ripper Primary Other.TakeDamage( STM.WeaponSettings.RipperPrimaryDamage, instigator, HitLocation, - STM.WeaponSettings.RipperPrimaryMomentum * MomentumTransfer * Normal(Velocity), + STM.WeaponSettings.RipperPrimaryMomentum * MomentumTransfer * Dir, 'shredded' ); STM.PlayerClear(); } } - if ( Other.bIsPawn ) + if (Other.bIsPawn) PlaySound(MiscSound, SLOT_Misc, 2.0); else PlaySound(ImpactSound, SLOT_Misc, 2.0); diff --git a/Classes/ST_SniperRifle.uc b/Classes/ST_SniperRifle.uc index d159862..3db24a0 100644 --- a/Classes/ST_SniperRifle.uc +++ b/Classes/ST_SniperRifle.uc @@ -50,24 +50,23 @@ function ProcessTraceHit(Actor Other, Vector HitLocation, Vector HitNormal, Vect local vector Momentum; PawnOwner = Pawn(Owner); - STM.PlayerFire(PawnOwner, 18); // 18 = Sniper + STM.PlayerFire(PawnOwner, 18); // 18 = Sniper s = Spawn(class'UT_ShellCase',, '', Owner.Location + CalcDrawOffset() + 30 * X + (2.8 * FireOffset.Y+5.0) * Y - Z * 1); - if ( s != None ) - { + if (s != None) { s.DrawScale = 2.0; s.Eject(((FRand()*0.3+0.4)*X + (FRand()*0.2+0.2)*Y + (FRand()*0.3+1.0) * Z)*160); } - if (Other == Level) + + if (Other == Level) { Spawn(class'UT_HeavyWallHitEffect',,, HitLocation+HitNormal, Rotator(HitNormal)); - else if ( (Other != self) && (Other != Owner) && (Other != None) ) - { - if ( Other.bIsPawn ) + } else if ((Other != self) && (Other != Owner) && (Other != None)) { + if (Other.bIsPawn) Other.PlaySound(Sound 'ChunkHit',, 4.0,,100); - if ( Other.bIsPawn && STM.CheckHeadshot(Pawn(Other), HitLocation, X) - && (instigator.IsA('PlayerPawn') || (instigator.IsA('Bot') && !Bot(Instigator).bNovice)) ) - { - STM.PlayerHit(PawnOwner, 18, True); // 18 = Sniper, Headshot + if (Other.bIsPawn && STM.CheckHeadshot(Pawn(Other), HitLocation, X) && + (instigator.IsA('PlayerPawn') || (instigator.IsA('Bot') && !Bot(Instigator).bNovice)) + ) { + STM.PlayerHit(PawnOwner, 18, True); // 18 = Sniper, Headshot Other.TakeDamage( STM.WeaponSettings.SniperHeadshotDamage, PawnOwner, @@ -75,15 +74,13 @@ function ProcessTraceHit(Actor Other, Vector HitLocation, Vector HitNormal, Vect STM.WeaponSettings.SniperHeadshotMomentum * 35000 * X, AltDamageType); STM.PlayerClear(); - } - else - { + } else if (Other.bIsPawn == false || STM.CheckBodyShot(Pawn(Other), HitLocation, X)) { if (Other.bIsPawn) Momentum = STM.WeaponSettings.SniperMomentum * 30000.0*X; else Momentum = 30000.0*X; - STM.PlayerHit(PawnOwner, 18, False); // 18 = Sniper + STM.PlayerHit(PawnOwner, 18, False); // 18 = Sniper Other.TakeDamage( STM.WeaponSettings.SniperDamage, PawnOwner, @@ -92,8 +89,8 @@ function ProcessTraceHit(Actor Other, Vector HitLocation, Vector HitNormal, Vect MyDamageType); STM.PlayerClear(); } - if ( !Other.bIsPawn && !Other.IsA('Carcass') ) - spawn(class'UT_SpriteSmokePuff',,,HitLocation+HitNormal*9); + if (!Other.bIsPawn && !Other.IsA('Carcass')) + Spawn(class'UT_SpriteSmokePuff',,,HitLocation+HitNormal*9); } } diff --git a/Classes/WeaponSettings.uc b/Classes/WeaponSettings.uc index 39735a3..c6edf7f 100644 --- a/Classes/WeaponSettings.uc +++ b/Classes/WeaponSettings.uc @@ -24,8 +24,6 @@ var config float SplashMinDiffractionDistance; var config bool bEnhancedHeadshotDetection; var config float HeadHalfHeight; var config float HeadRadius; -var config float HeadOffsetZ; -var config float HeadDuckOffsetZ; var config float WarheadSelectTime; var config float WarheadDownTime; @@ -169,8 +167,6 @@ defaultproperties bEnhancedHeadshotDetection=False HeadHalfHeight=7.5 HeadRadius=10.0 - HeadOffsetZ=31.5 - HeadDuckOffsetZ=4.2 WarheadSelectTime=0.5 WarheadDownTime=0.233333