class DAProjectile extends AdvancedProjectile; //var Actor Ignore; var float ImpactSoundVolume; simulated function PostBeginPlay() { super.PostBeginPlay(); if(ForceRadius == 0) ForceRadius = CollisionRadius; Velocity = GetTossVelocity(Instigator, Instigator.Controller.GetViewRotation()); } simulated function Destroyed () { Super.Destroyed (); if ( trail != None ) { trail.Kill(); } } // Hopefully this will solve that super bizarre thing that projectiles don't do damage, only // their explosion does. simulated function Touch(Actor Other) { local actor HitActor; local vector HitLocation, HitNormal, VelDir, AdjustedLocation; local bool bBeyondOther; local float BackDist, DirZ; if (Other.IsA('Pawn') == true && Instigator != Pawn(Other) && Level.NetMode != NM_DedicatedServer){ Spawn(BloodEmitter,,,location); } if ( Other == None ) // Other just got destroyed in its touch? return; if ( Other.bProjTarget || (Other.bBlockActors && Other.bBlockPlayers) ) { if ( Velocity == vect(0,0,0) || Other.IsA('Mover') ) { ProcessTouch(Other,Location); return; } //get exact hitlocation - trace back along velocity vector bBeyondOther = ( (Velocity Dot (Location - Other.Location)) > 0 ); VelDir = Normal(Velocity); DirZ = sqrt(abs(VelDir.Z)); BackDist = Other.CollisionRadius * (1 - DirZ) + Other.CollisionHeight * DirZ; if ( bBeyondOther ) BackDist += VSize(Location - Other.Location); else BackDist -= VSize(Location - Other.Location); HitActor = Trace(HitLocation, HitNormal, Location, Location - 1.1 * BackDist * VelDir, true); if (HitActor == Other) AdjustedLocation = HitLocation; else if ( bBeyondOther ) AdjustedLocation = Other.Location - Other.CollisionRadius * VelDir; else AdjustedLocation = Location; ProcessTouch(Other, AdjustedLocation); //if ( (Role < ROLE_Authority) && (Other.Role == ROLE_Authority) ) ClientSideTouch(Other, AdjustedLocation); } } simulated function ProcessTouch(Actor Other, Vector HitLocation) { super.ProcessTouch(Other, HitLocation); } simulated function ClientSideTouch(Actor Other, Vector HitLocation) { if(Other == Instigator) return; // you can't SHOOT YOURSELF with a projectile, but it's explosion could get you log(self@"ClientSideTouch"@Other); super.ClientSideTouch(Other, HitLocation); // YAY! THIS FIXES THE FUCKING ANIMATION PROBLEM! // we only should need to do it for zombies that are not our own if(AdvancedPawn(Other) != None && Pawn(Other).Health < 0) { if(!Other.IsA('DAZombieBase') && !Other.IsA('DAPawn')) { log(self@"Running special death code.."); AdvancedPawn(Other).FocusedAnimEnd(); Other.StopAnimating(); AdvancedPawn(Other).PlayDying(myDamageType, HitLocation); } } } simulated function PostNetBeginPlay() { if(Level.NetMode != NM_DedicatedServer && TrailEmitter != None) { trail = Spawn( TrailEmitter, self ); trail.SetPhysics(PHYS_TRAILER); trail.LifeSpan = 5.0; trail.SetBase( self ); } super(Projectile).PostNetBeginPlay(); } // We do a new ver of the Actor function HurtRadius so we can apply Karma. simulated function DAHurtRadius( float DamageAmount, float DamageRadius, class DamageType, float Momentum, vector HitLocation ) { local actor Victims; local float damageScale, dist; local vector dir; if( bHurtEntry || DamageRadius == 0) return; bHurtEntry = true; log(self@"DAHurtRadius"); foreach CollidingActors(class'Actor', Victims, DamageRadius, HitLocation) { // don't let blast damage affect fluid - VisibleCollisingActors doesn't really work for them - jag if( (Victims != self) && (Victims.Role == ROLE_Authority) && (!Victims.IsA('FluidSurfaceInfo')) && (Victims.Region.Zone == Region.Zone) ) { if(Victims.IsA('Pawn') && Instigator != Pawn(Victims) && Level.NetMode != NM_DedicatedServer) { Spawn(BloodEmitter,,,Victims.location); } dir = Victims.Location - HitLocation; dist = FMax(1,VSize(dir)); dir = dir/dist; damageScale = 1 - FMax(0,(dist - Victims.CollisionRadius)/DamageRadius); Victims.KAddImpulse(dir * (class(myDamageType).default.KDamageImpulse), Hitlocation); Victims.TakeDamage ( damageScale * DamageAmount, Instigator, Victims.Location - 0.5 * (Victims.CollisionHeight + Victims.CollisionRadius) * dir, (damageScale * Momentum * dir), myDamageType ); } } bHurtEntry = false; } simulated function BlowUp(vector HitLocation) { DAHurtRadius(Damage,DamageRadius, MyDamageType, MomentumTransfer, HitLocation ); if ( Role == ROLE_Authority ) MakeNoise(1.0); } simulated function Explode(vector HitLocation, vector HitNormal) { //Ignore = None; if(Level.NetMode != NM_DedicatedServer) { Spawn(ExplosionEmitter,,, location); PlaySound(ImpactSound,SLOT_NONE,ImpactSoundVolume,,1000); } /*if(Level.NetMode == NM_Client || Level.NetMode == NM_StandAlone) { Spawn(ExplosionEmitter,,, location); }*/ //if(Role == Role_Authority) { //if(Level.NetMode == NM_DedicatedServer) { // PlaySound(ImpactSound); //} BlowUp(HitLocation); Destroy(); } // Taken from the DOTZShotgunProjectile .. not sure if it's ever used, but it might be nice to have. simulated function Landed( vector HitNormal ){ HitWall( HitNormal, None ); } DefaultProperties { Acceleration=(X=0,Y=0,Z=-10) ForceType=FT_DragAlong }