Worst-case scenario: the UEd Goblin wipes the map and burns down your house.
Legacy:VitalOverdose/SFXPawnTeleporting
Contents
Overview[edit]
This custom emitter emits particles that teleport a pawn to a random destination when the pawn touches them. The exit points for the teleporter can be any non solid actors in the map. NavigationPoints work quite well for this propose. The emitter scans the entire level when it is spawned, checking for anything that has 'tp' in for its tag properties. The valid actor refs of these TP points get recorded in an array called TPact.
Global Variables[edit]
TotalParticles - Internal counter for the number of active particles to track. TpAct - Internal Dynamic array of type actor that gets emptied then populated every time scapTPAct() is called. ActiveEmitterNumb - The Number of the emitter within this emitter actor that will be tracked. BPlaySpawnEffect - A simple flag for triggering the pawns existing teleport fx. TimerFrequency - The scan rate for the particles. ScanSize - The scan radius of each particle that's being tracked. ReScanTime - How long between rescans of the available 'tp' points in the level.
Var bool bScanning; // The mapper has no access to these values In UnrealEd Var int TotalParticles; // The mapper has no access to these values In UnrealEd var Array<Actor> TpAct; // The mapper has no access to these values In UnrealEd Var () int ActiveEmitterNumb; // The mapper can set these values In UnrealEd Var () bool BPlaySpawnEffect; // The mapper can set these values In UnrealEd Var () float TimerFrequency; // The mapper can set these values In UnrealEd Var () float ScanSize; // The mapper can set these values In UnrealEd Var () float ReScanTime; // The mapper can set these values In UnrealEd var () Array< Class<Emitter> > TagFxPoolPawn; // The mapper can set these values In UnrealEd
Function PostBeginPlay()[edit]
In this function the .super function has been put before the modified code so we get anything from the parent class gets dealt with right away and leaves the rest of the function free for whatever code we need to add to it.
We are using the PostbeginPlay() function to check some of the data entered by the mapper before we start scanning the particle locations.
- TheMaxParticles on the active emitter is checked to see if it is higher than the Limit of 20.
- (true) it is it gets set to 20.
- The scansize Radius is checked to see it hasn't been set to low.
- (true) then it gets set to 64.
- Then the timerfrequency is checked to see if it lower < then 0.1 if it is.
- (true)it gets set to 0.1.
- Finally the Timer is set to be called every TimerFrequency seconds on a continuous loop.
Simulated function PostBeginPlay() { Super.PostBeginPlay(); //Copies code from the parent class relating to this function to this point. ScanTelPoint(); //The first scan for the TP point is performed if ( TpAct.length == 0 ) { Warn('The initial scan for actors TP (actors with TP in their tag fields) came up with nothing. This actor cannot function with out a TP list and had to be destroyed to avoid any other unexpected complications during game play'}; if ( Emitters[ActiveEmitterNumb].MaxParticles > 20) { Warn('The emitter U have chosen as the active emitter Emitters["$ActiveEmitterNumb$"] has its MaxParticle rate set TO high. It has been set to max (20) as a result. If you are having problems with game speed at all this may be something you want to address..'); Emitters[ActiveEmitterNumb].MaxParticles = 20; } If (TimerFrequency < 0.1 ) // 0.1 is the min but its better to set this value a high as possible { TimerFrequency = 0.1; Warn('The timerfrequency for this actor ("$timerfrequency$") is set to LOW and has been set to the min (0.1) as a result. If you are experiencing any problems with game speed them this may be something might want to address...) } SetTimer( TimerFrequency , True ); }
Function ScanTpAct()[edit]
when is function is called the emitter will perform a scan and record the valid actor refs of
all the actors in the level that have Tp in their Tag field.
- a local variable of type actor is declared to store the result of the scan.
- if the array of TP point is not empty..
- (true) -empty the array ready for re-population.
- Using an Iterator check though all the actors in the level with tp in their tag field and store their valid actor ref in the variable FoundTelPoint.
- a new space in the array is created at position 0 and and existing refs already present in the array get shuffled up one place to make room.
Simulated function ScanTpAct() { Local Actor FoundTelPoint; if ( TpAct.Length !=0 ) TpAct.Remove( 0,TpAct.Length ); foreach AllActors( Class'Actor' , FoundTelPoint, 'TP' ) { TpAct.Insert( 0,1 ); TpAct[0] = FoundTelPoint; } }
Function Timer()[edit]
The timer function is rather like an alarm clock, we can set it to go off after a certain amount of time. Whats really handy about this is we can also set it to run continuously which means any code we us the value timerfrequency and tell it to run continuously then the timer function will get called once every 'timerfrequency' seconds. This is particularly useful for scanning for things at regular intervals and timing delays.
The reason for using timer() rather than tick() is because tick runs at a set rate. As timerfrequency can be set by the mapper in unrealed hes has some control of the amount of cpu strain this actor is causing whilst playing and with an actor such as this that has the capability of slowing the whole game to a crawl if not use correctly that control is very important.
- first a local variable of type pawn is made to store the valid ref of any pawn that the iterator finds when scanning.
- A local variable of type Int is created to use as a counter in the for next loop that will cycle though the emitted particles currently being scanned.
- A for loop is ude to scan each emitted particle with an iterator and the valid actor ref of any pawn that gets detected get stored in the variable FoundPawn.
. This iterator works differently from the last one because this on is looking for a physical collision.
-
- If a pawn is found the function process contact is called and the valid actor ref of what was touched gets passes to the function to.
Simulated Function Timer() { Local Actor FoundActor; Local Int Counter; if ( bScanning == false) { for ( Counter=0 ; Counter < Emitters[0].Particles.Length ; Counter++ ) foreach visiblecollidingActors(Class'Actor', FoundActor , ScanSize , Emitters[ActiveEmitterNumb].Particles[Counter].Location ) ProcessCollision(FoundActor); } }
Function Tport()[edit]
The final script dealls with the actual Teleporting of the pawn + the fx. The code for it is very small
as by this point most of the variables have been qualified by earlyer functions.
Simulated Function Bool TPort(Pawn TPPawn) { local float exraheight; local Int Pickednumber; local vector NewOffsetposition; Pickednumber=FindSafeSpawnLoc(exraheight); NewOffsetposition=tpact[Pickednumber].location; NewOffsetposition.z =+ NewOffsetposition; TPPawn.SetLocation( NewOffsetposition); TPPawn.SetRotation( TelPoint.Rotation ); TPPawn.OldRotYaw = TPPawn.Rotation.Yaw; If ( BPlaySpawnEffect ) TPPawn.PlayTelePortEffect( False,True ); }
Function FindSafeSpawnLocs()[edit]
the teleporter will try very hard to find a safe place for the Pawn to spawn so that nothing gets telefragged. It does this by first scanning the destination tp point and if there is a possibility of a telefrag it moves on to the next random spawn point. if in the unlikely event of all the spawn spawnpoints are unsuitable then it will go t through another random list but adding 90 (location.z) in height each time the list gets looped.
Function Int FindSafeSpawnLoc(out float Extraheight) // this function checks for pawns being to close to the spawn point { // this way no one should get telefraged. If a suitab Local Pawn Foundpawn; Local Int Counter; Local int PickedRNDNo; Templist.Length = TPActors.Length; while( Foundpawn == None ) { for ( Counter = 0 ; Counter < TPActors.Length ; Counter++ ) Templist[Counter]=Counter; for ( Counter=0 ; Counter < TPActors.Length ; Counter++ ) // Here i want to pick Numbs at Random from a list { // First west up the Numbs in sequential order and then PickedRNDNo = Rand(Templist.Length -1)+1; // Pick a RND No based on the Length of the list. foreach radiusActors( Class'pawn' , Foundpawn , ScanRadius , TPActors[PickedRNDNo].location + (Vect( 0,0,1) * Extraheight); { if ( Foundpawn.bCollideActors == True ) PickedRNDNo = -10; TempList.remove( PickedRNDNo ,1 ); } } Extraheight += 90; } return PickedRNDNo; }
Final Script[edit]
Here Is the complete script
//////////////////////////////////////////////// //Class SFXTeleporting for Unrealtournament 2004 //by VitalOverdose Jan 2006 //Http://vitaloverdose.zapme.to.org //This actor is also Part of Vitals Pro Mapping Tools. //Http://ProMappingTools.zapto.org /////////////////////////////////////////////// Class SFXPawnTeleporting extends Emitter placeable; Var bool bScanning; // The mapper has no access to these values In UnrealEd Var int TotalParticles; // The mapper has no access to these values In UnrealEd var Array<Actor> TpAct; // The mapper has no access to these values In UnrealEd Var () int ActiveEmitterNumb; // The mapper can set these values In UnrealEd Var () bool BPlaySpawnEffect; // The mapper can set these values In UnrealEd Var () float TimerFrequency; // The mapper can set these values In UnrealEd Var () float ScanSize; // The mapper can set these values In UnrealEd Var () float ReScanTime; // The mapper can set these values In UnrealEd var () Array< Class<Emitter> > TagFxPoolPawn; // The mapper can set these values In UnrealEdFunction Simulated function PostBeginPlay() { Super.PostBeginPlay(); //Copies code from the parent class relating to this function to this point. ScanTelPoint(); //The first scan for the TP point is performed if ( TpAct.length == 0 ) { Warn('The initial scan for actors TP (actors with TP in their tag fields) came up with nothing. This actor cannot function with out a TP list and had to be destroyed to avoid any other unexpected complications during game play'}; if ( Emitters[ActiveEmitterNumb].MaxParticles > 20) { Warn('The emitter U have chosen as the active emitter Emitters["$ActiveEmitterNumb$"] has its MaxParticle rate set TO high. It has been set to max (20) as a result. If you are having problems with game speed at all this may be something you want to address..'); Emitters[ActiveEmitterNumb].MaxParticles = 20; } If (TimerFrequency < 0.1 ) // 0.1 is the min but its better to set this value a high as possible { TimerFrequency = 0.1; Warn('The timerfrequency for this actor ("$timerfrequency$") is set to LOW and has been set to the min (0.1) as a result. If you are experiencing any problems with game speed them this may be something might want to address...) } SetTimer( TimerFrequency , True ); } Simulated function ScanTpAct() { Local Actor FoundTelPoint; if ( TpAct.Length !=0 ) TpAct.Remove( 0,TpAct.Length ); foreach AllActors( Class'Actor' , FoundTelPoint, 'TP' ) { TpAct.Insert( 0,1 ); TpAct[0] = FoundTelPoint; } } Simulated Function Timer() { Local Actor FoundActor; Local Int Counter; if ( bScanning == false) { for ( Counter=0 ; Counter < Emitters[0].Particles.Length ; Counter++ ) foreach visiblecollidingActors(Class'Actor', FoundActor , ScanSize , Emitters[ActiveEmitterNumb].Particles[Counter].Location ) ProcessCollision(FoundActor); } } Simulated Function Bool TPort(Pawn TPPawn) { local float exraheight; local Int Pickednumber; local vector NewOffsetposition; Pickednumber=FindSafeSpawnLoc(exraheight); NewOffsetposition=tpact[Pickednumber].location; NewOffsetposition.z =+ NewOffsetposition; TPPawn.SetLocation( NewOffsetposition); TPPawn.SetRotation( TelPoint.Rotation ); TPPawn.OldRotYaw = TPPawn.Rotation.Yaw; If ( BPlaySpawnEffect ) TPPawn.PlayTelePortEffect( False,True ); } Function Int FindSafeSpawnLoc(out float Extraheight) // this function checks for pawns being to close to the spawn point { // this way no one should get telefraged. If a suitab Local Pawn Foundpawn; Local Int Counter; Local int PickedRNDNo; Templist.Length = TPActors.Length; while( Foundpawn == None ) { for ( Counter = 0 ; Counter < TPActors.Length ; Counter++ ) Templist[Counter]=Counter; for ( Counter=0 ; Counter < TPActors.Length ; Counter++ ) // Here i want to pick Numbs at Random from a list { // First west up the Numbs in sequential order and then PickedRNDNo = Rand(Templist.Length -1)+1; // Pick a RND No based on the Length of the list. foreach radiusActors( Class'pawn' , Foundpawn , ScanRadius , TPActors[PickedRNDNo].location + (Vect( 0,0,1) * Extraheight); { if ( Foundpawn.bCollideActors == True ) PickedRNDNo = -10; TempList.remove( PickedRNDNo ,1 ); } } Extraheight += 90; } return PickedRNDNo; } defaultproperties { bNoDelete=False RemoteRole=ROLE_SimulatedProxy }
Related Topcs[edit]
- Emitter
- Particle System
- ParticleEmitter
- ParticleEmitter Cookbook
- udn2:EmittersReference
- udn2:EmittersExamples
More custom emitter scipts[edit]
- VitalOverdose/SFXVecTeleporting
- VitalOverdose/SFXTriggering
- VitalOverdose/SFXBoosting
- VitalOverdose/SFXMonsterSpawning
- VitalOverdose/SFXHealing
- Vitaloverdose/SFXUltraLight
- VitalOverdose/InventoryFlare