Announcement

Collapse
No announcement yet.

Making stinger shard bounce.

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

    Making stinger shard bounce.

    I can't debug this thing I keep running around and around, I know I am close just missing something ><

    Code:
    /**
     * Copyright 1998-2008 Epic Games, Inc. All Rights Reserved.
     */
    
    class UTProj_zippylabsut3stonershardtwo extends UTProj_StingerShard;
    
    var int Bounces;
    
    simulated function PostBeginPlay()
    {
    	Super.PostBeginPlay();
    	bCanCreateSpike = true;
    }
    
    /**
     * Insure that our constraint is destroyed when we are destroyed
     */
    simulated event Destroyed()
    {
    	if (ShardVictimConstraint != none)
    	{
    		ShardVictimConstraint.Destroy();
    	}
    
    	Super.Destroyed();
    }
    
    static function bool FindNearestBone(UTPawn DeadPawn, vector InitialHitLocation, out name BestBone, out vector BestHitLocation)
    {
    	local int i, dist, BestDist;
    	local vector BoneLoc;
    	local name BoneName;
    
    	if (DeadPawn.Mesh.PhysicsAsset != none)
    	{
    		for (i=0;i<DeadPawn.Mesh.PhysicsAsset.BodySetup.Length;i++)
    		{
    			BoneName = DeadPawn.Mesh.PhysicsAsset.BodySetup[i].BoneName;
    			// If name is not empty and bone exists in this mesh
    			if ( BoneName != '' && DeadPawn.Mesh.MatchRefBone(BoneName) != INDEX_NONE)
    			{
    				BoneLoc = DeadPawn.Mesh.GetBoneLocation(BoneName);
    				Dist = VSize(InitialHitLocation - BoneLoc);
    				if ( i==0 || Dist < BestDist )
    				{
    					BestDist = Dist;
    					BestBone = DeadPawn.Mesh.PhysicsAsset.BodySetup[i].BoneName;
    					BestHitLocation = BoneLoc;
    				}
    			}
    		}
    
    		if (BestBone != '')
    		{
    			return true;
    		}
    	}
    	return false;
    }
    
    
    /**
     * This function creates the actual spike in the world.  A duplicate Shard projectile is spawned
     * and that projectile is used to spike the pawn.  We use a secondary actor in order to avoid
     * having to wait for replication to occur since this actor is spawned client-side
     */
    static function bool CreateSpike(UTPawn DeadPawn, vector InitialHitLocation, vector Direction)
    {
    	local UTProj_zippylabsut3stonershardtwo Shard;
    	local vector BoneLoc;
    	local name	 BoneName;
    	local TraceHitInfo 	HitInfo;
    	local vector Start, End, HitLocation, HitNormal;
    
    	if ( DeadPawn != None && !class'GameInfo'.static.UseLowGore(DeadPawn.WorldInfo) && !DeadPawn.bDeleteMe && DeadPawn.Health <= 0 && DeadPawn.Physics == PHYS_RigidBody
    		&& DeadPawn.Mesh != None && DeadPawn.Mesh.PhysicsAssetInstance != None )
    	{
    		Start = InitialHitLocation - (256.0 * Normal(Direction));
    		End = Start + (512.0 * Normal(Direction));
    
    		if ( DeadPawn.WorldInfo.TraceComponent(HitLocation, HitNormal, DeadPawn.Mesh, End, Start, vect(0,0,0), HitInfo) )
    		{
    			if (HitInfo.BoneName != '')
    			{
    				BoneLoc  = DeadPawn.Mesh.GetBoneLocation(HitInfo.BoneName);
    				BoneName = HitInfo.BoneName;
    			}
    		}
    
    		// Begin by tracing towards just this component, looking for the nearest bone it collides with (if any)
    		if ( BoneName != '' || FindNearestBone(DeadPawn, InitialHitLocation, BoneName, BoneLoc) )
    		{
    			// Spawn a shard
    			BoneLoc -= (32 * Direction);
    
    			Shard = DeadPawn.Spawn(class'UTProj_zippylabsut3stonershardtwo',,, BoneLoc, rotator(Direction));
    			if (Shard != None)
    			{
    				// Give this shard a push
    				Shard.bCanCreateSpike = false;
    				Shard.Speed = 800;
    				Shard.AccelRate = 0.0f;
    				Shard.Init(Direction);
    
    				// Attach the victim to this shard
    				Shard.SpikeVictim(DeadPawn,BoneName);
    
    				return true;
    			}
    		}
    	}
    
    	return false;
    }
    
    simulated function bool SpawnImpactEffect(vector HitLocation, vector HitNormal)
    {
    	if (EffectIsRelevant(HitLocation, false, MaxEffectDistance))
    	{
    		LastImpactEffect = new(Outer) class'UTParticleSystemComponent';
    		LastImpactEffect.SetAbsolute(true, true, true);
    		LastImpactEffect.SetTranslation(HitLocation);
    		LastImpactEffect.SetRotation(rotator(HitNormal));
    		LastImpactEffect.SetTemplate((Bounces > 0) ? BounceTemplate : RockSmokeTemplate);
    		LastImpactEffect.OnSystemFinished = MyOnParticleSystemFinished;
    		AttachComponent(LastImpactEffect);
    		return true;
    	}
    	return false;
    }
    
    /**
     * This function is called when the touch occurs locally in a remote client.  It checks
     * to see if the pawn is already ragdolling and if so, spikes it again
     */
    simulated function ClientSideTouch(Actor Other, Vector HitLocation)
    {
    	local UTPawn DeadPawn;
    
    	DeadPawn = UTPawn(Other);
    
    	if ( bCanCreateSpike && CreateSpike(DeadPawn, HitLocation, Normal(Vector(Rotation))))
    	{
    		Destroy();
    	}
    	else
    	{
    		Other.TakeDamage(Damage, InstigatorController, Location, MomentumTransfer * Normal(Velocity), MyDamageType,, self);
    	}
    }
    
    /**
     * We have to override HitWall in order to store a pointer to the actor
     * that we hit (in the case of non-world geometry).  This way we can
     * be stuck to tanks, etc.
     */
    simulated function HitWall(vector HitNormal, actor Wall, PrimitiveComponent WallComp)
    {
    
    	local audioComponent HitSoundComp;
    	local bool bSpawnedImpactEffect;
    
    	bBlockedByInstigator = true;
    	bSpawnedImpactEffect = SpawnImpactEffect(Location, HitNormal);
    	
    	{
    		ImpactSound = DefaultHitSound.Sound;
    		SetPhysics(PHYS_Falling);
    		if (Bounces > 0)
    		{
    			if ( Bounces == 1 )
    			{
    				LifeSpan += 0.5;
    			}
    			if ((!WorldInfo.bDropDetail && FRand() < 0.4) || (UTProj_FlakShardMain(self) != none))
    			{
    
    				HitSoundComp = CreateAudioComponent( ImpactSound, false, false, true, location );
    				if(HitSoundComp != none)
    				{
    					HitSoundComp.VolumeMultiplier = (Bounces > 1) ? 1.0 : 0.5;
    					HitSoundComp.Play();
    				}
    
    			}
    
    			Velocity = 0.6 * (Velocity - 2.0 * HitNormal * (Velocity dot HitNormal));
    			Bounces = Bounces - 1;
    		}
    		else
    		{
    			if (ProjEffects != None)
    			{
    				ProjEffects.DeactivateSystem();
    			}
    			bBounce = false;
    			SetPhysics(PHYS_None);
    			SetTimer(0.5 * FRand(), false, 'StartToShrink');
    		}
    	
    	
    	if (Wall != Instigator)
    	{
    		if (!Wall.bStatic && !Wall.bWorldGeometry)
    		{
    			if (DamageRadius == 0)
    			{
    				Wall.TakeDamage(Damage, InstigatorController, Location, MomentumTransfer * Normal(Velocity), MyDamageType,, self);
    			}
    			ImpactedActor = Wall;
    		}
    		else
    		{
    			BaseActor = Wall;
    		}
    
    		Explode(Location, HitNormal);
    		ImpactedActor = None;
    	}
    	
    	
    	// If we are already spiked, stick in to the wall
    	if (bSpiked)
    	{
    		// can't stick to blocking volumes
    		if (BlockingVolume(Wall) != None)
    		{
    			Destroy();
    		}
    		else
    		{
    			Velocity = vect(0,0,0);
    			SetBase(Wall);
    			SetPhysics(PHYS_None);
    		}
    	}
    }
    
    /**
     * This function is responsible for creating the constraint between the projectile
     * and the victim.
     */
    simulated function SpikeVictim(UTPawn Victim, name VictimBone)
    {
    	local UTProj_zippylabsut3stonershardtwo OtherShard;
    
    	// destroy any previous shards on the victim so we don't get nasty fighting between the two constraints
    	foreach DynamicActors(class'UTProj_zippylabsut3stonershardtwo', OtherShard)
    	{
    		if (OtherShard.ShardVictimConstraint != None && OtherShard.ShardVictimConstraint.ConstraintActor2 == Victim)
    		{
    			OtherShard.Destroy();
    		}
    	}
    
    	CollisionComponent = MyMesh;
    
    	// give projectile extent so that it collides the same way the pawn does
    	// (so we don't get the ragdoll stuck in a blocking volume, etc)
    	bSwitchToZeroCollision = false;
    	CylinderComponent.SetCylinderSize(1.0, 1.0);
    	CylinderComponent.SetActorCollision(true, false);
    
    	SetLocation(Victim.Mesh.GetBoneLocation(VictimBone));
    
    	ShardVictimConstraint = Spawn(class'RB_ConstraintActorSpawnable',,,Location);
    	ShardVictimConstraint.SetBase(self);
    	ShardVictimConstraint.InitConstraint( self, Victim, '', VictimBone, 2000.f);
    	ShardVictimConstraint.LifeSpan = 8.0;
    
    	// Add some velocity to the victim overall, to avoid the spike having to do all the work of pulling them
    	Victim.Mesh.SetRBLinearVelocity(Velocity*SpikeVictimVelFactor, TRUE);
    
    	if (WorldInfo.NetMode != NM_DedicatedServer)
    	{
    		Victim.LifeSpan += 8.0;
    	}
    
    	LifeSpan = 8.0;
    	bSpiked = true;
    	AdjustPhysicsForHit();
    
    }
    
    /**
     * We only want to process the touch if we are not spike and we are not a remote client.  In the case of
     * a remote client, ClientTouch should be used.
     */
    simulated function ProcessTouch(Actor Other, Vector HitLocation, Vector HitNormal)
    {
    	local UTPawn P;
    
    	if (!bSpiked && Role == ROLE_Authority)
    	{
    		if ( Other != Instigator )
    		{
    			P = UTPawn(Other);
    			Other.TakeDamage(Damage, InstigatorController, HitLocation, MomentumTransfer * Normal(Velocity), MyDamageType,, self);
    			if (P != None && (WorldInfo.NetMode == NM_DedicatedServer || !bCanCreateSpike || !CreateSpike(P, HitLocation, Normal(Velocity))))
    			{
    
    				if (P != None && P.Health <= 0)
    				{
    					P.TearOffMomentum = Velocity;
    					if (WorldInfo.NetMode != NM_DedicatedServer && bCanCreateSpike)
    					{
    						CreateSpike(P, HitLocation, Normal(Velocity));
    					}
    				}
    			}
    			Shutdown();
    		}
    	}
    
    	if ( (Role < ROLE_Authority) && (Other.Role == ROLE_Authority) )
    	{
    		ClientSideTouch(Other, HitLocation);
    	}
    }
    
    /**
     * Make sure to set our base properly
     */
    simulated function Shutdown()
    {
    	if (BaseActor != none)
    	{
    		SetBase(BaseActor);
    	}
    
    	if (!bSpiked)
    	{
    		Super.ShutDown();
    	}
    }
    
    /**
     * Setup this projectile's physics after it has spiked a victim
     */
    simulated function AdjustPhysicsForHit()
    {
    	Velocity = Speed * Normal(vector(Rotation));
    	Velocity.Z += 100.0;
    	SetPhysics(PHYS_Falling);
    	Acceleration = vect(0,0,0);
    	CustomGravityScaling = 0.5;
    }
    
    
    simulated function StartToShrink()
    {
    	RemoteRole = ROLE_None;
    	bShrinking = true;
    	ShrinkTimer = FMin(LifeSpan,0.75);
    	if ( WorldInfo.NetMode == NM_DedicatedServer )
    	{
    		Destroy();
    	}
    	else if ( !bWaitForEffects )
    	{
    		LifeSpan = ShrinkTimer;
    	}
    }
    
    defaultproperties
    {
    	DrawScale=1.0
    
    		
    	Components.Add(ProjectileMesh)
    	MyMesh=ProjectileMesh
    
    	ProjExplosionTemplate=ParticleSystem'WP_Stinger.Particles.P_WP_Stinger_AltFire_Surface_Impact'
    	MaxEffectDistance=7000.0
    
    	SpikeVictimVelFactor=0.5
    
    	Speed=2500
    	MaxSpeed=4000
    	AccelRate=4500.0
    
    	Damage=38
    	DamageRadius=30
    	MomentumTransfer=30000
    	CheckRadius=27.0
    	
    	bBounce=true
    	Bounces=2
    
    	MyDamageType=class'Zippylabsut3.UTDmgType_zippylabsut3stonerdamshardtwo'
    	LifeSpan=10.0
    
    	bCollideWorld=true
    	bProjTarget=false
    	bNetTemporary=true
    //	bAdvanceExplosionEffect=true
    }

    #2
    i remember using a gun like this years ago on my server
    have u looked at the flak cannon code

    Comment


      #3
      Originally posted by unrealloco View Post
      i remember using a gun like this years ago on my server
      have u looked at the flak cannon code
      I am setting up my stoner to have a shotgun like spread of stinger shards that bounce 3 or 4 times, the main fire will be very fast and small stinger shards.I'd also like them to stick into walls.
      I took some code from the simulated function HitWall(vector HitNormal, actor Wall, PrimitiveComponent WallComp) copied it over but its not working. I can not get the grammar right I'm getting phrasing but there are to many errors.


      What I need is a code that lets it bounce first then stick in everything but actors/vehicles, actors/vehicles it will always stick in.


      I have managed to copy over the flak shard code so you shot out a bunch of shards.

      Comment


        #4
        im gonna guess and say Bool, "bounces"..... - sound like a good guess?

        ^^ Your code uses "Bounce"; you forgot the "s", but then put the "s" in the next line

        As stated Above; you can look at the flak cannon. Also the Bouncy Rockets & Ripper. As for the "sticky" im guesser Bio-rifle would be a suitable weapon to look at.
        * i do not recall doing anything similar to this so cannot upload anything

        Comment


          #5
          After marking bounce I found it it was at the top of the blood page LOL. its var int bounces.

          Now heres what I am trying to do I am pretty sure this overrides how the projectile handles walls so if it were not for this code it should bounce, I am trying to tell it to count the bounces before processing the rest of the code but I can not get it to work....


          Code:
          /**
           * We have to override HitWall in order to store a pointer to the actor
           * that we hit (in the case of non-world geometry).  This way we can
           * be stuck to tanks, etc.
           */
          simulated singular function HitWall(vector HitNormal, actor Wall, PrimitiveComponent WallComp)
          {
          	if (Wall != Instigator)
          	{
          		if (!Wall.bStatic && !Wall.bWorldGeometry )
          			
                     if Bounces = Bounces - 1;			
          		{   
          		
          			else (DamageRadius == 0)
          			{
          				Wall.TakeDamage(Damage, InstigatorController, Location, MomentumTransfer * Normal(Velocity), MyDamageType,, self);
          			}
          			ImpactedActor = Wall;
          		}
          		else
          		{
          			BaseActor = Wall;
          		}
          
          		Explode(Location, HitNormal);
          		ImpactedActor = None;
          	}
          
          	// If we are already spiked, stick in to the wall
          	if (bSpiked)
          	{
          		// can't stick to blocking volumes
          		if (BlockingVolume(Wall) != None)
          		{
          			Destroy();
          		}
          		else
          		{
          			Velocity = vect(0,0,0);
          			SetBase(Wall);
          			SetPhysics(PHYS_None);
          		}
          	}
          }

          Comment


            #6
            I can not figure this out, there's a conflict somewhere I am sure.

            The error is on this line


            Other.TakeDamage(GetDamage(Other, HitLocation), InstigatorController, HitLocation, GetMomentumTransfer() * Normal(Velocity), MyDamageType,, self);



            this is the error

            C:\Games\Steam\steamapps\common\Unreal Tournament 3\Development\Src\Zippylabsut3\Classes\UTProj_zipp ylabsut3stonershardtwo.uc(272) : Error, Bad or missing expre
            ssion for token: GetDamage, in Call to 'TakeDamage', parameter 1


            Trying to get bounce to work without losing the impaling feature.
            Code:
            /**
             * Copyright 1998-2008 Epic Games, Inc. All Rights Reserved.
             */
            
            class UTProj_zippylabsut3stonershardtwo extends UTProjectile; //UTProj_StingerShard;
            
            var int Bounces;
            
            /** We need a pointer to our mesh component so we can switch collision when we create the constraint */
            var StaticMeshComponent MyMesh;
            
            /** This holds a link to our Constraint Actor */
            var RB_ConstraintActor ShardVictimConstraint;
            
            /** This is true if this projectile is currently spiking a victim */
            var bool bSpiked;
            
            /** Used to keep track of what actor to base ourselves on */
            var Actor BaseActor;
            
            var vector OldLocation;
            
            var() float SpikeVictimVelFactor;
            
            
            /** Used to prevent rare infinite recursion when spiking overlapping dead bodies */
            var bool bCanCreateSpike;
            
            
            /** if set, play camera anim for killer when kill at very short range (set to false for shards spawned by alt shell) */
            var bool bCheckShortRangeKill;
            /** the camera anim to play */
            var CameraAnim ShortRangeKillAnim;
            
            
            
            simulated function PostBeginPlay()
            {
            	Super.PostBeginPlay();
            	bCanCreateSpike = true;
            }
            
            
            /**
             * Insure that our constraint is destroyed when we are destroyed
             */
            simulated event Destroyed()
            {
            	if (ShardVictimConstraint != none)
            	{
            		ShardVictimConstraint.Destroy();
            	}
            
            	Super.Destroyed();
            }
            
            static function bool FindNearestBone(UTPawn DeadPawn, vector InitialHitLocation, out name BestBone, out vector BestHitLocation)
            {
            	local int i, dist, BestDist;
            	local vector BoneLoc;
            	local name BoneName;
            
            	if (DeadPawn.Mesh.PhysicsAsset != none)
            	{
            		for (i=0;i<DeadPawn.Mesh.PhysicsAsset.BodySetup.Length;i++)
            		{
            			BoneName = DeadPawn.Mesh.PhysicsAsset.BodySetup[i].BoneName;
            			// If name is not empty and bone exists in this mesh
            			if ( BoneName != '' && DeadPawn.Mesh.MatchRefBone(BoneName) != INDEX_NONE)
            			{
            				BoneLoc = DeadPawn.Mesh.GetBoneLocation(BoneName);
            				Dist = VSize(InitialHitLocation - BoneLoc);
            				if ( i==0 || Dist < BestDist )
            				{
            					BestDist = Dist;
            					BestBone = DeadPawn.Mesh.PhysicsAsset.BodySetup[i].BoneName;
            					BestHitLocation = BoneLoc;
            				}
            			}
            		}
            
            		if (BestBone != '')
            		{
            			return true;
            		}
            	}
            	return false;
            }
            
            
            /**
             * This function creates the actual spike in the world.  A duplicate Shard projectile is spawned
             * and that projectile is used to spike the pawn.  We use a secondary actor in order to avoid
             * having to wait for replication to occur since this actor is spawned client-side
             */
            static function bool CreateSpike(UTPawn DeadPawn, vector InitialHitLocation, vector Direction)
            {
            	local UTProj_zippylabsut3stonershardtwo Shard;
            	local vector BoneLoc;
            	local name	 BoneName;
            	local TraceHitInfo 	HitInfo;
            	local vector Start, End, HitLocation, HitNormal;
            
            	if ( DeadPawn != None && !class'GameInfo'.static.UseLowGore(DeadPawn.WorldInfo) && !DeadPawn.bDeleteMe && DeadPawn.Health <= 0 && DeadPawn.Physics == PHYS_RigidBody
            		&& DeadPawn.Mesh != None && DeadPawn.Mesh.PhysicsAssetInstance != None )
            	{
            		Start = InitialHitLocation - (256.0 * Normal(Direction));
            		End = Start + (512.0 * Normal(Direction));
            
            		if ( DeadPawn.WorldInfo.TraceComponent(HitLocation, HitNormal, DeadPawn.Mesh, End, Start, vect(0,0,0), HitInfo) )
            		{
            			if (HitInfo.BoneName != '')
            			{
            				BoneLoc  = DeadPawn.Mesh.GetBoneLocation(HitInfo.BoneName);
            				BoneName = HitInfo.BoneName;
            			}
            		}
            
            		// Begin by tracing towards just this component, looking for the nearest bone it collides with (if any)
            		if ( BoneName != '' || FindNearestBone(DeadPawn, InitialHitLocation, BoneName, BoneLoc) )
            		{
            			// Spawn a shard
            			BoneLoc -= (32 * Direction);
            
            			Shard = DeadPawn.Spawn(class'UTProj_zippylabsut3stonershardtwo',,, BoneLoc, rotator(Direction));
            			if (Shard != None)
            			{
            				// Give this shard a push
            				Shard.bCanCreateSpike = false;
            				Shard.Speed = 800;
            				Shard.AccelRate = 0.0f;
            				Shard.Init(Direction);
            
            				// Attach the victim to this shard
            				Shard.SpikeVictim(DeadPawn,BoneName);
            
            				return true;
            			}
            		}
            	}
            
            	return false;
            }
            
            /**
             * This function is called when the touch occurs locally in a remote client.  It checks
             * to see if the pawn is already ragdolling and if so, spikes it again
             */
            simulated function ClientSideTouch(Actor Other, Vector HitLocation)
            {
            	local UTPawn DeadPawn;
            
            	DeadPawn = UTPawn(Other);
            
            	if ( bCanCreateSpike && CreateSpike(DeadPawn, HitLocation, Normal(Vector(Rotation))))
            	{
            		Destroy();
            	}
            	else
            	{
            		Other.TakeDamage(Damage, InstigatorController, Location, MomentumTransfer * Normal(Velocity), MyDamageType,, self);
            	}
            }
            
            /**
             * We have to override HitWall in order to store a pointer to the actor
             * that we hit (in the case of non-world geometry).  This way we can
             * be stuck to tanks, etc.
             */
            simulated singular function HitWall(vector HitNormal, actor Wall, PrimitiveComponent WallComp)
            {
            	if (Wall != Instigator)
            	{
            		if (!Wall.bStatic && !Wall.bWorldGeometry )
            			
                      // if Bounces = Bounces - 1;			
            		{   
            		
            			if (DamageRadius == 0)
            			{
            				Wall.TakeDamage(Damage, InstigatorController, Location, MomentumTransfer * Normal(Velocity), MyDamageType,, self);
            			}
            			ImpactedActor = Wall;
            		}
            		else
            		{
            			BaseActor = Wall;
            		}
            
            		Explode(Location, HitNormal);
            		ImpactedActor = None;
            	}
            
            	// If we are already spiked, stick in to the wall
            	if (bSpiked)
            	{
            		// can't stick to blocking volumes
            		if (BlockingVolume(Wall) != None)
            		{
            			Destroy();
            		}
            		else
            		{
            			Velocity = vect(0,0,0);
            			SetBase(Wall);
            			SetPhysics(PHYS_None);
            		}
            	}
            }
            
            /**
             * This function is responsible for creating the constraint between the projectile
             * and the victim.
             */
            simulated function SpikeVictim(UTPawn Victim, name VictimBone)
            {
            	local UTProj_zippylabsut3stonershardtwo OtherShard;
            
            	// destroy any previous shards on the victim so we don't get nasty fighting between the two constraints
            	foreach DynamicActors(class'UTProj_zippylabsut3stonershardtwo', OtherShard)
            	{
            		if (OtherShard.ShardVictimConstraint != None && OtherShard.ShardVictimConstraint.ConstraintActor2 == Victim)
            		{
            			OtherShard.Destroy();
            		}
            	}
            
            	CollisionComponent = MyMesh;
            
            	// give projectile extent so that it collides the same way the pawn does
            	// (so we don't get the ragdoll stuck in a blocking volume, etc)
            	bSwitchToZeroCollision = false;
            	CylinderComponent.SetCylinderSize(1.0, 1.0);
            	CylinderComponent.SetActorCollision(true, false);
            
            	SetLocation(Victim.Mesh.GetBoneLocation(VictimBone));
            
            	ShardVictimConstraint = Spawn(class'RB_ConstraintActorSpawnable',,,Location);
            	ShardVictimConstraint.SetBase(self);
            	ShardVictimConstraint.InitConstraint( self, Victim, '', VictimBone, 2000.f);
            	ShardVictimConstraint.LifeSpan = 8.0;
            
            	// Add some velocity to the victim overall, to avoid the spike having to do all the work of pulling them
            	Victim.Mesh.SetRBLinearVelocity(Velocity*SpikeVictimVelFactor, TRUE);
            
            	if (WorldInfo.NetMode != NM_DedicatedServer)
            	{
            		Victim.LifeSpan += 8.0;
            	}
            
            	LifeSpan = 8.0;
            	bSpiked = true;
            	AdjustPhysicsForHit();
            
            }
            
            simulated function float GetMomentumTransfer()
            {
            	return MomentumTransfer;
            }
            
            simulated function ProcessTouch(Actor Other, Vector HitLocation, Vector HitNormal)
            {
            	local Vehicle V;
            	local UTPlayerController PC;
            
            	if ( (UTProj_zippylabsut3stonershardtwo(Other) == none) && (Physics == PHYS_Falling || Other != Instigator) )
            	{
            		speed = VSize(Velocity);
            		if (Speed > 400)
            		{
            			Other.TakeDamage(GetDamage(Other, HitLocation), InstigatorController, HitLocation, GetMomentumTransfer() * Normal(Velocity), MyDamageType,, self);
            			if ( Role == ROLE_Authority )
            			{
            				V = Vehicle(Other);
            				if ( V != None)
            				{
            					if ( PlayerController(V.Controller) != None )
            					{
            						PlayerController(V.Controller).ClientPlaySound(DefaultHitSound.Sound);
            					}
            					bWaitForEffects = SpawnImpactEffect(HitLocation, HitNormal);
            				}
            				else if (Pawn(Other) != None)
            				{
            					PlaySound(HitPawnSound, true);
            
            					// play camera anim if short range kill
            					if ( bCheckShortRangeKill && Pawn(Other).Health < 0 && Physics == PHYS_Projectile && Instigator != None &&
            						VSize(Instigator.Location - Other.Location) < 150.0 )
            					{
            						PC = UTPlayerController(InstigatorController);
            						if (PC != None)
            						{
            							PC.ClientPlayCameraAnim(ShortRangeKillAnim);
            						}
            					}
            				}
            				else if ( UTDeployedActor(Other) != None )
            				{
            					bWaitForEffects = SpawnImpactEffect(HitLocation, HitNormal);
            				}
            			}
            		}
            		Shutdown();
            	}
            }
            
            /**
             * Make sure to set our base properly
             */
            simulated function Shutdown()
            {
            	if (BaseActor != none)
            	{
            		SetBase(BaseActor);
            	}
            
            	if (!bSpiked)
            	{
            		Super.ShutDown();
            	}
            }
            
            /**
             * Setup this projectile's physics after it has spiked a victim
             */
            simulated function AdjustPhysicsForHit()
            {
            	Velocity = Speed * Normal(vector(Rotation));
            	Velocity.Z += 100.0;
            	SetPhysics(PHYS_Falling);
            	Acceleration = vect(0,0,0);
            	CustomGravityScaling = 0.5;
            }
            
            defaultproperties
            {
            	DrawScale=1.0
            
            		
            	Components.Add(ProjectileMesh)
            	MyMesh=ProjectileMesh
            
            	ProjExplosionTemplate=ParticleSystem'WP_Stinger.Particles.P_WP_Stinger_AltFire_Surface_Impact'
            	MaxEffectDistance=12000.0
            
            	SpikeVictimVelFactor=1.5
            
            	Speed=2500
            	MaxSpeed=4000
            	AccelRate=4500.0
            
            	Damage=10
            	DamageRadius=60
            	MomentumTransfer=30000
            	CheckRadius=27.0
            	
            	bBounce=true
            	Bounces=2
            
            	MyDamageType=class'Zippylabsut3.UTDmgType_zippylabsut3stonerdamshardtwo'
            	LifeSpan=10.0
            
            	bCollideWorld=true
            	bProjTarget=false
            	bNetTemporary=true
            //	bAdvanceExplosionEffect=true
            }

            Comment

            Working...
            X