| Home Page | Recent Changes

VitalOverdose/SFX Painful

UT2004 :: Actor >> Emitter >>SFX_painful (Package: custom)
 

by VitalOverdose

Part of Vital'sPMT

Overview

This is a custom emitter actor that can track up to 20 particles from 1 of its emitters (ActiveEmitterNumb) and cause pain to any pawn they collide with. Using an iterator in this way to scan the particles locations is fairly stressful to the CPU so I've capped the particles to 20. Its totally untested as yet as to how many can be tracked without out any significant drop in game play speed. If anyone does get round to testing it please let me know.

Properties

Note any changes to the properties will have to be made in the default properties by the mapper. Although you could write a custom spawner that can set the properties as the emitters are spawned (you cant change MaxParticles this way its a constant)

       
 ActiveEmitterNumb        access by DefaultProperties - The number of the emitter that is to be tracked.   
 TimerFrequency           access by DefaultProperties - The Scanning frequency capped to 0.1 of a second max 
                                                       (10x Scans a second);            
 ScanSize                 access by DefaultProperties - the scan radius for each particle
 TheDamageType            access by DefaultProperties - The damagetype to apply on contact with a pawn
 DamageToVec              access by DefaultProperties - The damage amount for vehicles
 DamageToPawn             access by DefaultProperties - The damage amount for xpawns
 DamageToMonster          access by DefaultProperties - The Damage Amount for monsters
 VecCollisionFx           access by DefaultProperties - The Collision FX for vehicles
 PawnCollisionFx          access by DefaultProperties - The Collision FX for xpawns
 MonsterCollisionFx       access by DefaultProperties - The Collision FX for monsters
 VecCollisionSound        access by DefaultProperties - The collision Sound For vehicles
 PawnCollisionSound       access by DefaultProperties - The collision Sound For xpawns
 MonsterCollisionSound    access by DefaultProperties - The collision Sound For monsters

Simulated Function PostBeginPlay()

OK here is where the capping takes place any value set outside the range of the programmer has set results in the value being set at its max for the scan size and for its min on the timerfrequency.

The call to destroy the actor if set wrong may seem a little harsh but its not possible to alter the maxparticle count after game-play has started as its a constant variable;

The timer is started at the end of this function. Set to run continuously being called every timerFrequency seconds. This is of course the 'Scan Rate' for the tracked particles.

Simulated Function PostBeginPlay()
{
 Super.PostBeginPlay();
 
 If ( Emitters[ActiveEmitterNumb].MaxParticles > 20)
    {
     Destroyed();
    }

 if (ScanSize < 64 )
    {
     ScanSize=64;
    }

 if (TimerFrequency < 0.1)
    {
     TimerFrequency = 0.1;
    }
    
 SetTimer( TimerFrequency , true );
}

Simulated Function Timer()

Every time this function is called (once every Timerfrequency Seconds) the particles from the tracked emitter have their locations scanned with an iterator for any pawns. If one is found the valid ref for the pawn is bundled together with the velocity the particle was traveling at x 500 and set to the function ProcessCollision()

Simulated Function Timer()
{
 local Pawn           FoundPawn;
 Local Int            Counter;

 for ( Counter=0 ; Counter < Emitters[ActiveEmitterNumb].Particles.Length ; Counter++ )
     {
      foreach visiblecollidingActors(Class'Pawn', FoundPawn , ScanSize , Emitters[ActiveEmitterNumb].Particles[Counter].Location )
              {
               ProcessCollision (FoundPawn ,Emitters[ActiveEmitterNumb].Particles[Counter].Velocity*500);
              }
     }
}

Simulated Function ProcessCollision(Pawn CollidedWith, Vector ParticleMomentum)

Here the valid ref of the pawn the particle came in contact with is received along with a slightly increased velocity which comes in the form of a vector. Here the ProcessCollision is really just dealing out the pain ,sound and FX to the unlucky pawn who came in contact with the particle. As there's 3 different possible sets of sounds ,pain amount and fx (one of each for xpawn , monster and vec) it results in 3 lots of code. Ive used local variables to store what has to be played , spawned and ..er applied for each eventuality and then just applied it to one set of actions. This is about the only thing i could come up with to make this function slightly more efficient the just writing out 3 lots of the same code. If you know of a more efficient way of doing it please let me know. CaseSwitch may be more efficient IDK i haven't got round to using it yet.

Simulated function ProcessCollision(Pawn CollidedWith, vector Particlemomentum)
{
Local Int            ThePain;
local Emitter        SpawnedFX;
local Sound          CollisionSound;
local Class<emitter> Collisionfxclass;

if ((CollidedWith.IsA('Vehicle')) && (DamageTovec !=0 ))     
   {
    ThePain = DamageTovec;
    if (VecCollisionSound!=None)
       {
        CollisionSound=VecCollisionSound;
       }
    if ( VecCollisionFx != None )
       {
        Collisionfxclass = VecCollisionFx;
       }
   }

else
if ((CollidedWith.IsA('monster')) && (DamageTomonster !=0 )) 
   {
    ThePain = DamageTomonster;
    if (MonsterCollisionSound!=None)
       {
        CollisionSound=MonsterCollisionSound;
       }
    if ( VecCollisionFx != None )
       {
        Collisionfxclass = MonsterCollisionFx;
       }
   }

else
 if ( (CollidedWith.IsA('xPawn') ) && (DamageToPawn !=0 ))    
    {
     ThePain = DamageToPawn;
     if (VecCollisionSound!=None)
        {
         CollisionSound=PawnCollisionSound;
        }
     if ( PawnCollisionFx != None )
        {
         Collisionfxclass = PawnCollisionFx;
        }
   }
    
 if ( CollisionSound != none )   // dealing out the pain,the fx,and the sound
    {
     CollidedWith.PlaySound( CollisionSound );
    }
 if ( Collisionfxclass != None )
    {
     SpawnedFX = spawn(Collisionfxclass,CollidedWith,,CollidedWith.location,CollidedWith.rotation);
    }     
 if ( ThePain != 0 )
    {
     CollidedWith.TakeDamage( DamageToPawn, Instigator, CollidedWith.Location , Particlemomentum, TheDamageType );
    }
}

The Complete Script

Here is the completed script for now;-

//=============================================================================
// SFX_Painful.
//=============================================================================
 class SFX_Painful extends emitter
Placeable;

var    int                    TotalParticles;      // The mapper has no access to these
Var () int                    ActiveEmitterNumb;   // The mapper has no access to this property
Var () int                    TimerFrequency;      // The mapper has no access to this property
Var () int                    DamageToPawn;        // The mapper has no access to this property
Var () int                    DamageToVec;         // The mapper has no access to this property 
Var () int                    DamageToMonster;     // The mapper has no access to this property 
Var () float                  ScanSize;            // The mapper has no access to this property 
var () Class<DamageType>      TheDamageType;       // The mapper has no access to this property 
var () class <emitter>        MonsterCollisionFx;
var () class <emitter>        VecCollisionFx;
var () class <emitter>        PawnCollisionFx;
var () sound                  PawnCollisionSound;  
var () Sound                  VecCollisionSound;
var () Sound                  MonsterCollisionSound;

Simulated Function PostBeginPlay()
{
 Super.PostBeginPlay();
 
 If ( Emitters[ActiveEmitterNumb].MaxParticles > 20)
    {
     Destroyed();
    }

 if (ScanSize < 64 )
    {
     ScanSize=64;
    }

 if (TimerFrequency < 0.1)
    {
     TimerFrequency = 0.1;
    }
    
 SetTimer( TimerFrequency , true );
}

Simulated Function Timer()
{
 local Pawn           FoundPawn;
 Local Int            Counter;

 for ( Counter=0 ; Counter < Emitters[ActiveEmitterNumb].Particles.Length ; Counter++ )
     {
      foreach visiblecollidingActors(Class'Pawn', FoundPawn , ScanSize , Emitters[ActiveEmitterNumb].Particles[Counter].Location )
              {
               ProcessCollision (FoundPawn ,Emitters[ActiveEmitterNumb].Particles[Counter].Velocity*500);
              }
     }
}

Simulated function ProcessCollision(Pawn CollidedWith, vector Particlemomentum)
{
Local int            ThePain;
local emitter        SpawnedFX;
local sound          CollisionSound;
local class<emitter> Collisionfxclass;

if ((CollidedWith.IsA('Vehicle')) && (DamageTovec    !=0 ))     
   {
    ThePain = DamageTovec;
    if (VecCollisionSound!=None)
       {
        CollisionSound=VecCollisionSound;
       }
    if ( VecCollisionFx != None )
       {
        Collisionfxclass = VecCollisionFx;
       }
   }

else
if ((CollidedWith.IsA('monster')) && (DamageTomonster !=0 )) 
   {
    ThePain = DamageTomonster;
    if (MonsterCollisionSound!=None)
       {
        CollisionSound=MonsterCollisionSound;
       }
    if ( VecCollisionFx != None )
       {
        Collisionfxclass = MonsterCollisionFx;
       }
   }

else
 if ( (CollidedWith.IsA('xPawn') ) && (DamageToPawn !=0 ))    
    {
     ThePain = DamageToPawn;
     if (VecCollisionSound!=None)
        {
         CollisionSound=PawnCollisionSound;
        }
     if ( PawnCollisionFx != None )
        {
         Collisionfxclass = PawnCollisionFx;
        }
   }
    
                                               // dealing out the pain,the fx,and the sound
 if ( CollisionSound != none )
    {
     CollidedWith.PlaySound( CollisionSound );
    }
 if ( Collisionfxclass != None )
    {
     SpawnedFX = spawn(Collisionfxclass,CollidedWith,,CollidedWith.location,CollidedWith.rotation);
    }     
 if ( ThePain != 0 )
    {
     CollidedWith.TakeDamage( DamageToPawn, Instigator, CollidedWith.Location , Particlemomentum, TheDamageType );
    }
}

There may be some small alterations to this at a later date i have a few ideas of making it run more efficiantly so more than 20 particles can be tracked. But its all going to need some fairly detailed testing before i make any serious changes to the way it works.

 

Related Topics

Discussion

DaWrecka: Have you considered making the emitter work server-side? If you could guarantee running on the server (which is required for dealing damage anyway) you can easily use Level.ControllerList. Since it's a linked list of nothing but controllers, you can vastly reduce the number of actors iterated through, since you can be sure that if Controller.Pawn != None, then the Pawn is a) a Pawn and not something else (obviously), b) Valid, and thus c) fair game. You're also not iterating through actors you wouldn't want damaged anyway like static meshes and brushes. The load will reduce vastly and consequently allow you to either use no cap or a much higher cap.


Category Custom Class

The Unreal Engine Documentation Site

Wiki Community

Topic Categories

Recent Changes

Offline Wiki

Unreal Engine

Console Commands

Terminology

FAQs

Help Desk

Mapping Topics

Mapping Lessons

UnrealEd Interface

UnrealScript Topics

UnrealScript Lessons

Making Mods

Class Tree

Modeling Topics

Chongqing Page

Log In