VitalOverdose/Dynamic Emitter Control
A custom Emitter actor for UT2004
Part of Vital'sPMT
Overview
This custom emitter actor doesn't do very much by itself its more of a framework to be mod'ed from.
The functions in this class are far more portable than usual. The don't depend on any special variables to be set up in the class the are being used for so they can easily be swapped about or event added to other actor actors without much bother.
I'll do a few examples;-
MeasureTileU()
Returns the Length of A texture Side
Function Float MeasureTileU(texture T,Int usubs) { Local Float Result; IF ( usubs ==0 ) usubs = 1; Result = T.USize/usubs; Return Result; }
Function Partoverride()
Function Partoverride(Emitter Target,Float PartRateDiv,Optional Bool BFadein, Optional Bool BFadeout,Optional Bool ReSpawnDeadParts) { Local Int I; For( I =0; I <Target.Emitters.Length;I++ ) { Target.Emitters[I].InitialParticlesPerSecond = Target.Emitters[I].InitialParticlesPerSecond / PartRateDiv; Target.Emitters[I].ParticlesPerSecond = Target.Emitters[I].ParticlesPerSecond / PartRateDiv; Target.Emitters[I].ReSpawnDeadParticles = ReSpawnDeadParts; Target.Emitters[I].FadeOut = BFadein; Target.Emitters[I].FadeIn = BFadeout; } }
Function PartScale()
Returns the Amount that one text texture has to Be Scale to Be the Same Size As Another;
Function Float PartScale(Class<Emitter> Emit ,Int usubs,Optional Float TargetSize,Optional Emitter DonorEmitter ) { Local Float Result,finalResult; Local Int I; if ( Emit == None ) { If (DonorEmitter != None ) { For (I=0;I<DonorEmitter.Emitters.Length;I++) { If (DonorEmitter.Class == Class'spriteEmitter') { Emit=DonorEmitter.Class; } If (Emit != None) Break; } } Else Return FinalResult; } Result=MeasureTileU(Emit.Default.Emitters[I].texture,Emit.Default.Emitters[I].textureusubdivisions); Result = TargetSize / Result; finalResult = Result * Result; Return FinalResult; }
FindSpriteE()
Returns A Scanned List of Emitter Actors that contain At Least 1 Sprite Emitter
Function Array< Class<Emitter> > FindSpriteE (name PType,Optional Int NeedtoFind,Optional Int RequiredPTypeAmount) { Local Emitter FoundE; Local Array< Class<Emitter> > EmitterList; Local Int PTypeFound,i; if ( NeedtoFind ==0 ) { NeedtoFind=10; //checking & Correcting Sent Data } if ( RequiredPTypeAmount < 1 ) { RequiredPTypeAmount = 1; //checking & Correcting Sent Data } if (PType=='Sprite') { ForEach AllActors(Class'Emitter',FoundE) //look For All Actors of Class Emitter And Assign their valid Actor ref to A Variable of Type 'EmitterActor' Called FoundE { // PTypeFound=0; //reset counter For ( I=0; I<FoundE.Emitters.Length; I++ ) // Start Loop through Available Emitters In the Emitter Actor; { If ( FoundE.Emitters[I].Class == Class'spriteEmitter' ) // Is It A Sprite Emitter(has A texture) { PTypeFound++; // Inc counter If (PTypeFound == RequiredPTypeAmount) EmitterList[I] = FoundE.Class; // Use This Emitter Actor If We Are At Target For Sprite Emitter's per Emitter Actor } If ( EmitterList[I] == FoundE) Break; // Break Loop: If the Last Emitter was ok. } If (EmitterList.Length == NeedtoFind) Break; // Break Loop: If we Have Target Amount of Emitter Actors; } } Return EmitterList; }
Simulated Function PartPause(Emitter Target)
Particle Override Pause:This Function Is used to Create the Illusion of A particle rate of 0.
The particle rate Slowed Down to A rate of 0000.1 A Sec.
This Function Should only really Be used If you Intend to Start the
Emitter Actor Going Again At A Later time. Otherwise Use PartoverRide_Die to Achieve A SmoOther
'Faded' Alternative to Simply Calling Destroy();
Simulated Function PartPause(Emitter Target) { Local Int I; For ( I =0; I <Target.Emitters.Length ; I++ ) { Target.Emitters[I].InitialParticlesPerSecond =0000.1; Target.Emitters[I].AutomaticInitialSpawning = False; } }
Function Bool togPartPause(Emitter TargetE)
A Simple toggle Function For 'PartPause'(Emitter Target) && Partoverride_Resume(Emitter Target).
Function Bool togPo_Pause(Emitter TargetE) { Local Int I; For ( I=0; I<TargetE.Emitters.Length ;I++ ) { If (TargetE.Emitters[0].IsA('particleEmitter')) { If (TargetE.Emitters[I].InitialParticlesPerSecond ==0000.1) { Partoverride_Resume(TargetE); Return False; } PartPause(TargetE); Return True; } } }
Partoverride_Resume()
Particle override Resume: ReSets PArtRate of Specified Emitter Back to Its Default Settings
Simulated Function Partoverride_Resume(Emitter Target) { Local Int I; For ( I =0 ; I < Target.Emitters.Length; I++ ) { Target.Emitters[I].InitialParticlesPerSecond = Target.Default.Emitters[I].InitialParticlesPerSecond; Target.Emitters[I].AutomaticInitialSpawning = Target.Default.Emitters[I].AutomaticInitialSpawning; } }
Partoverride_Die();
ParticleOverride DIE: Causes Specified Emitter to Fade then Die;
Particles Have time to Fade BeFore the Destroy Function Is Called.
Results In A Much SmoOther Alternative to Calling the Destroy Function on An Emitter;
Simulated Function Partoverride_Die(Emitter Target) { Local Int I; For ( I =0; I <Target.Emitters.Length ; I++ ) { If (Target.Emitters[I].Class == Class'spriteEmitter') { Target.Emitters[I].FadeOut = True; Target.Emitters[I].FadeIn = True; } Target.Emitters[I].ReSpawnDeadParticles = False; Target.Emitters[I].AutoDestroy = True; Target.Emitters[I].AutoReset = False; } }
Completed script
Heres the full script for now. I do expect to be adding more to this soon;-
/////////////////////////////////////////////////////////////////////////////////// //DynamicEmitterControl //By VitalOverdose 2006 http://www.VitalOverdose.com //Part Of the Vitals Pro Mapping tools mod. // ////////////////////////////////////////////////////////////////////////////////// class DynamicEmitterControl extends emitter placeable; Function Float MeasureTileU(texture T,Int usubs) { Local Float Result; IF ( usubs ==0 ) usubs = 1; Result = T.USize/usubs; Return Result; } Function Partoverride(Emitter Target,Float PartRateDiv,Optional Bool BFadein, Optional Bool BFadeout,Optional Bool ReSpawnDeadParts) { Local Int I; For( I =0; I <Target.Emitters.Length;I++ ) { Target.Emitters[I].InitialParticlesPerSecond = Target.Emitters[I].InitialParticlesPerSecond / PartRateDiv; Target.Emitters[I].ParticlesPerSecond = Target.Emitters[I].ParticlesPerSecond / PartRateDiv; Target.Emitters[I].ReSpawnDeadParticles = ReSpawnDeadParts; Target.Emitters[I].FadeOut = BFadein; Target.Emitters[I].FadeIn = BFadeout; } } Function Float PartScale(Class<Emitter> Emit ,Int usubs,Optional Float TargetSize,Optional Emitter DonorEmitter ) { Local Float Result,finalResult; Local Int I; if ( Emit == None ) { If (DonorEmitter != None ) { For (I=0;I<DonorEmitter.Emitters.Length;I++) { If (DonorEmitter.Class == Class'spriteEmitter') { Emit=DonorEmitter.Class; } If (Emit != None) Break; } } Else Return FinalResult; } Result=MeasureTileU(Emit.Default.Emitters[I].texture,Emit.Default.Emitters[I].textureusubdivisions); Result = TargetSize / Result; finalResult = Result * Result; Return FinalResult; } Function Array< Class<Emitter> > FindSpriteE (name PType,Optional Int NeedtoFind,Optional Int RequiredPTypeAmount) { Local Emitter FoundE; Local Array< Class<Emitter> > EmitterList; Local Int PTypeFound,i; if ( NeedtoFind ==0 ) { NeedtoFind=10; //checking & Correcting Sent Data } if ( RequiredPTypeAmount < 1 ) { RequiredPTypeAmount = 1; //checking & Correcting Sent Data } if (PType=='Sprite') { ForEach AllActors(Class'Emitter',FoundE) //look For All Actors of Class Emitter And Assign their valid Actor ref to A Variable of Type 'EmitterActor' Called FoundE { // PTypeFound=0; //reset counter For ( I=0; I<FoundE.Emitters.Length; I++ ) // Start Loop thRough Available Emitters In the Emitter Actor; { If ( FoundE.Emitters[I].Class == Class'spriteEmitter' ) // Is It A Sprite Emitter(has A texture) { PTypeFound++; // Inc counter If (PTypeFound == RequiredPTypeAmount) EmitterList[I] = FoundE.Class; // Use This Emitter Actor If We Are At Target For Sprite Emiters per Emitter Actor } If ( EmitterList[I] == FoundE) Break; // Break Loop: If the Last Emitter was ok. } If (EmitterList.Length == NeedtoFind) Break; // Break Loop: If we Have Target Amount of Emitter Actors; } } Return EmitterList; } Simulated Function PartPause(Emitter Target) { Local Int I; For ( I =0; I <Target.Emitters.Length ; I++ ) { Target.Emitters[I].InitialParticlesPerSecond =0000.1; Target.Emitters[I].AutomaticInitialSpawning = False; } } Function Bool togPo_Pause(Emitter TargetE) { Local Int I; For ( I=0; I<TargetE.Emitters.Length ;I++ ) { If (TargetE.Emitters[0].IsA('particleEmitter')) { If (TargetE.Emitters[I].InitialParticlesPerSecond ==0000.1) { Partoverride_Resume(TargetE); Return False; } PartPause(TargetE); Return True; } } } Simulated Function Partoverride_Resume(Emitter Target) { Local Int I; For ( I =0 ; I < Target.Emitters.Length; I++ ) { Target.Emitters[I].InitialParticlesPerSecond = Target.Default.Emitters[I].InitialParticlesPerSecond; Target.Emitters[I].AutomaticInitialSpawning = Target.Default.Emitters[I].AutomaticInitialSpawning; } } Simulated Function Partoverride_Die(Emitter Target) { Local Int I; For ( I =0; I <Target.Emitters.Length ; I++ ) { If (Target.Emitters[I].Class == Class'spriteEmitter') { Target.Emitters[I].FadeOut = True; Target.Emitters[I].FadeIn = True; } Target.Emitters[I].ReSpawnDeadParticles = False; Target.Emitters[I].AutoDestroy = True; Target.Emitters[I].AutoReset = False; } }
Discussion
Tarquin: You haven't actually tried compiling this, have you? 'placeacble'.
vitaloverdose Lol...Busted! No not as a class on its own. i wrote an emitter mod a while back where i had one massive abstract actor that contained all the common functions for the entire mod. I tried to write each function to be completely self contained with no attached global variables. All the functions have been tested and work fine...so all i did was group a few together and gave it a class name. Your right its technically untested. The only reason i didn't spot it is that 'placeable' isn't a real word and always shows up as incorrect in my spell checker so i don't pay any attention to it....i Guess i should have at least given it one compile... i might have spotted it myself but about 10 mins after posting it i was locked out of wiki because id posted to many links in a short space of time... that was me adding the headers you asked for on each page...
Grrr, Dyslexia ....you win again!
SuperApe: Perhaps you should move this page to your personal subpages as well, until you are able to compile, test and confirm its functionality and usefulness. (Just a suggestion)