class SchlonzSniperFire extends InstantFire; #EXEC OBJ LOAD FILE=SchlonzUTSounds.uax var() float HeadShotDamageMult; var() float HeadShotRadius; var() class DamageTypeHeadShot; function DoFireEffect() { local Vector StartTrace; local Rotator R, Aim; local bool bDone; Instigator.MakeNoise(1.0); // the to-hit trace always starts right in front of the eye StartTrace = Instigator.Location + Instigator.EyePosition(); bDone = false; if( Instigator.PlayerReplicationInfo != None ) { if( Instigator.PlayerReplicationInfo.bBot ) { Aim = AdjustAim( StartTrace, 1000 ); R = rotator(vector(Aim) + VRand()*FRand()*Spread); bDone = true; } } if( bDone == false ) { Aim = AdjustAim( StartTrace, 100 ); // much more precise !!! R = rotator( vector( Aim ) ); } DoTrace( StartTrace, R ); } // DoFireEffect function DoTrace(Vector Start, Rotator Dir) { local Vector X, End, HitLocation, HitNormal, RefNormal; local Actor Other; local int Damage; local bool bDoReflect; local int ReflectNum; local float dist; ReflectNum = 0; while (true) { bDoReflect = false; X = Vector( Dir ); End = Start + TraceRange * X; Other = Trace( HitLocation, HitNormal, End, Start, true ); if ( Other != None && ( Other != Instigator || ReflectNum > 0 ) ) { if( bReflective && Other.IsA( 'xPawn' ) && xPawn(Other).CheckReflect( HitLocation, RefNormal, DamageMin*0.25 ) ) { bDoReflect = true; HitNormal = Vect( 0,0,0 ); } else if ( !Other.bWorldGeometry ) { Damage = (DamageMin + Rand(DamageMax - DamageMin)) * DamageAtten; if ( ( Pawn( Other ) != None ) && Other.GetClosestBone( HitLocation, X, dist, 'head', HeadShotRadius ) == 'head' ) { Other.TakeDamage( Damage * HeadShotDamageMult, Instigator, HitLocation, Momentum*X, DamageTypeHeadShot ); } else { Other.TakeDamage( Damage, Instigator, HitLocation, Momentum*X, DamageType ); ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// if( Pawn( Other ).PlayerReplicationInfo != None ) { if( Pawn( Other ).PlayerReplicationInfo.bBot ) { SchlonzXPawnBot( Other ).SetPawnBotSize( -0.4 ); if( SchlonzXPawnBot( Other ).PlayerSize < 1 ) { Pawn( Other ).Velocity.Z += 1000; Pawn( Other ).Velocity.X = 0; Pawn( Other ).Velocity.Y = 0; Pawn( Other ).SetPhysics( PHYS_Falling ); } } } ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// } } else if ( WeaponAttachment(Weapon.ThirdPersonActor) != None ) { WeaponAttachment( Weapon.ThirdPersonActor ).UpdateHit( Other,HitLocation,HitNormal ); } } else { HitLocation = End; HitNormal = Vect(0,0,0); } SpawnBeamEffect( Start, Dir, HitLocation, HitNormal, ReflectNum ); if( bDoReflect && ++ReflectNum < 4 ) { //Log("reflecting off"@Other@Start@HitLocation); Start = HitLocation; Dir = Rotator( RefNormal ); //Rotator( X - 2.0*RefNormal*(X dot RefNormal) ); } else { break; } } } // DoTrace defaultproperties { HeadShotDamageMult=2.300000 HeadShotRadius=16.000000 DamageTypeHeadShot=Class'SchlonzUT.SchlonzDamTypeSniperHeadShot' DamageType=Class'SchlonzUT.SchlonzDamTypeSniperShot' DamageMin=45 DamageMax=45 TraceRange=30000.000000 FireAnimRate=1.110000 FireSound=Sound'SchlonzUTSounds.SniperFire' FireForce="LightningGunFire" FireRate=0.700000 AmmoClass=Class'SchlonzUT.SchlonzSniperAmmo' AmmoPerFire=1 ShakeOffsetMag=(X=-8.000000,Z=8.000000) ShakeOffsetRate=(X=-4000.000000,Z=4000.000000) ShakeOffsetTime=1.600000 BotRefireRate=5.000000 aimerror=850.000000 }