It's there for the taking. This hack should work:
Edit: Wait, no, it won't work. You'll still have to alter it so UpdateParticles() takes a camera entity as the argument instead of a Player object, and you'll also need to copy a few more functions (I think just UpdateVector and Vec_Copy), can't get the source at the moment (on my parent's PC) so I can't edit this so it works properly.
Long paste. Hm.
Edit: Wait, no, it won't work. You'll still have to alter it so UpdateParticles() takes a camera entity as the argument instead of a Player object, and you'll also need to copy a few more functions (I think just UpdateVector and Vec_Copy), can't get the source at the moment (on my parent's PC) so I can't edit this so it works properly.
; The Flag object is used by Vein to store and retrieve variables. ; A good example of its use can be found under c_particle.bb or c_sspart.bb Type Flags Field UFlag# [32] ;user flags, can be modified via the scripting engine Field VFlag# [32] ;flags set by functions in Vein Field BitFlag% [31] ;bit flags, these should only be set as 0 or 1, because that's what they'll get turned into the instant they're saved End Type ; The Vector object is used by Vein to store position, acceleration, velocity, angles, etc. ; There are also functions to modify/return these objects (such as CrossProduct, Magnitude, and Vec_Dist) Type Vector Field X#,Y#,Z# ;World position Field Pan#,Tilt#,Roll# ;Absolute Angles Field Vel_Pan#,Vel_Tilt#,Vel_Roll# ;Angle velocity Field Accel_Pan#,Accel_Tilt#,Accel_Roll# ;Angle acceleration Field Vel_X#,Vel_Y#,Vel_Z# ;Local velocity Field Accel_X#,Accel_Y#,Accel_Z# ;Local acceleration End Type ;Particle Object ;Used to record and update particles created by emitters. Type Particle Field Vert ;The upper-left corner vertex of the particle's triangle. ;Field Piv Field Life% ;The life of the particle before it dies. Field Alpha# ;The particle's current alpha. Field Size# ;The particle's current size. Field V.Vector ;The particle's position and velocity. This is copied from its parent emitter. Field Parent.Emitter ;The particle's parent emitter. Field Roll# ;The particle's current angle (roll). End Type ;Emitter Object ;Used to record and update emitters. Type Emitter Field Child.Emitter ;The emitter's child Field V.Vector ;The position, velocity, angle, and acceleration of the particles the emitter creates Field F.Flags ;Emitter flags Field Piv ;The pivot used to create the particles. Field Parent.Emitter ;The parent of the emitter. Field Bmap% ;The handle of the texture it uses. Field Mesh% ;The mesh it uses to store the particles. Field Surface% ;The surface that stores the particle triangles and vertices. End Type ;Particle Magnet object ;Used to alter the position and velocity of particles Type Magnet Field V.Vector ;Position Field Enabled ;Enabled? Field Rad# ;Radius of affection Field Mag# ;Magnitude Field Falloff% ;Falloff flag End Type Const SSPARENT = 5 Const SSCHILD = 4 Global P_TIMEBETWEEN = 4 ; Creates an emitter. ; Almost all of the parameters are self explanatory. ; P = The Parent of this emitter. Pass Null to this argument if it isn't a child. ; Blend = The blend mode of the particles. Valid constants are: B_ADD, B_MUL, B_ALF. ; Life = How long before a particle dies, regardless of the circumstances. ; SizeR = The amount by which the size of particles is reduced per frame. ; AlphaR = The amount by which the alpha of particles is reduced per frame. ; AlphaD = The distance before the particles begin to fade out. ; ARR = Toggles whether to set a random roll for the particles. ; FE = True if particles are emitted only once per so many frames, or False if particles are to be created every frame. ; return = An Emitter object if successful, Null if not. Function CreateEmitter.Emitter( V.Vector, Bmap, P.Emitter, Blend=B_ADD, Life=200, Size#=1, Alpha#=1, SizeR#=0, AlphaR#=.2, AlphaD#=1000, ARR=False, FE=False, Enabled=True) If Not V <> Null Or BMap <> 0 Then Return Null E.Emitter = New Emitter E\V.Vector = V.Vector E\Bmap = Bmap ;Color+Alpha+ClampedU+ClampedV If E\Bmap <> 0 Then E\Mesh = CreateMesh() ;create the mesh E\Surface = CreateSurface(E\Mesh) EntityTexture E\Mesh, E\Bmap EntityBlend E\Mesh, Blend EntityFX E\Mesh, 1+2+32 ;Full bright + Vertex Colors + Forced Alpha E\Piv = CreatePivot() PositionEntity E\Piv, E\V\X, E\V\Y, E\V\Z, True E\F.Flags = New Flags E\F\VFlag[1] = Blend E\F\VFlag[2] = Life E\F\VFlag[3] = Size E\F\VFlag[4] = Alpha E\F\VFlag[5] = SizeR E\F\VFlag[6] = AlphaR E\F\VFlag[7] = AlphaD E\F\VFlag[8] = ARR E\F\VFlag[9] = FE E\F\VFlag[10]= Enabled E\F\VFlag[11]= SSPARENT If P.Emitter <> Null Then P\Child.Emitter = E.Emitter E\F\VFlag[11] = SSCHILD EndIf Return E Else Delete E Return Null EndIf End Function ; Adds a particle that is a child of the emitter. ; E = The parent of the particle. ; F = If a particle, upon death, has a child emitter then pass that particle to this argument. ; return = A Particle object. Nobody keeps track of them, why should you? Function AddParticle.Particle(E.Emitter, F.Particle) P.Particle = New Particle ;P\Piv = CreatePivot() If F <> Null Then P\Parent = F\Parent\Child P\V = Vec_Copy(F\V) P\V\X = P\V\X + P\Parent\V\X P\V\Y = P\V\Y + P\Parent\V\Y P\V\Z = P\V\Z + P\Parent\V\Z Else P\Parent = E P\V = Vec_Copy(P\Parent\V) EndIf P\Size = P\Parent\F\VFlag[3] P\Alpha = P\Parent\F\VFlag[4] P\Life = P\Parent\F\VFlag[2] ;PositionEntity P\Piv, P\V\X, P\V\Y, P\V\Z P\Parent\F\VFlag[32] = P\Parent\F\VFlag[32] + 1 If P\Parent\F\VFlag[8] = True Then SeedRnd(MilliSecs()) P\Roll# = Rnd(0.000, 360.000) Else P\Roll# = P\V\Roll EndIf End Function ; Updates all particles. ; Pl = The Player object that the particles should face. ; return = True if successful, False if not. Function UpdateParticles(Pl.Player) If Not Pl <> Null Then Pl = First Player If Not Pl <> Null Then Return False EndIf For E.Emitter = Each Emitter ClearSurface E\Surface If E\F\VFlag[10] And E\F\VFlag[11] = SSPARENT And E\F\VFlag[15] = P_TIMEBETWEEN Then E\F\VFlag[15] = 0 AddParticle E, Null EndIf If E\F\VFlag[9] Then E\F\VFlag[15] = Max(E\F\VFlag[15] + 1,P_TIMEBETWEEN) Else E\F\VFlag[15] = P_TIMEBETWEEN EndIf Next For P.Particle = Each Particle If P\Parent <> Null Then P\Life = P\Life - 1 P\Alpha = P\Alpha + P\Parent\F\VFlag[6] P\Size = P\Size + P\Parent\F\VFlag[5] If (P\Parent\F\VFlag[6] <= 0 And P\Alpha <= 0) Or (P\Parent\F\VFlag[6] => 1 And P\Alpha => 1) Or (P\Parent\F\VFlag[5] <= 0 And P\Size# <= 0) Or (P\Life = 0) Then If P\Parent\Child.Emitter <> Null Then AddParticle(P\Parent\Child, P) EndIf P\Parent\F\VFlag[32] = P\Parent\F\VFlag[32] - 1 ;decrease particle count for the object Delete P\V Delete P Else For M.Magnet = Each Magnet Distance# = Min(Vec_Dist(P\V,M\V),1) If M\Enabled And Distance < M\Rad Then If M\Falloff = True Then Distance = M\Rad - Distance L.Vector = Vec_Diff(P\V,M\V) X_Factor# = L\X/Distance Y_Factor# = L\Y/Distance Z_Factor# = L\Z/Distance P\V\X = P\V\X - ( X_Factor*M\Mag ) P\V\Y = P\V\Y - ( Y_Factor*M\Mag ) P\V\Z = P\V\Z - ( Z_Factor*M\Mag ) Delete L EndIf Next P\Roll = P\Roll + P\Parent\V\Vel_Roll UpdateVector P\V PositionEntity P\Parent\Piv, P\V\X, P\V\Y, P\V\Z TranslateEntity P\Parent\Piv, P\V\Vel_X, P\V\Vel_Y, P\V\Vel_Z P\V\X = EntityX(P\Parent\Piv,True) P\V\Y = EntityY(P\Parent\Piv,True) P\V\Z = EntityZ(P\Parent\Piv,True) PointEntity P\Parent\Piv, Pl\Camera TurnEntity P\Parent\Piv, 180, 0, 0 RotateEntity P\Parent\Piv, EntityPitch(P\Parent\Piv), EntityYaw(P\Parent\Piv), P\Roll MoveEntity P\Parent\Piv, -Abs(P\Size#), -Abs(P\Size#), 0 P\Vert = AddVertex(P\Parent\Surface, EntityX(P\Parent\Piv, True), EntityY(P\Parent\Piv, True), EntityZ(P\Parent\Piv, True), 0, 1) If Not EntityInView(P\Parent\Piv,Pl\Camera) Then F = F + 1 MoveEntity P\Parent\Piv, 0, Abs(P\Size#)*2, 0 AddVertex(P\Parent\Surface, EntityX(P\Parent\Piv, True), EntityY(P\Parent\Piv, True), EntityZ(P\Parent\Piv, True), 0, 0) If Not EntityInView(P\Parent\Piv,Pl\Camera) Then F = F + 1 MoveEntity P\Parent\Piv, Abs(P\Size#)*2, 0, 0 AddVertex(P\Parent\Surface, EntityX(P\Parent\Piv, True), EntityY(P\Parent\Piv, True), EntityZ(P\Parent\Piv, True), 1, 0) If Not EntityInView(P\Parent\Piv,Pl\Camera) Then F = F + 1 MoveEntity P\Parent\Piv, 0, -Abs(P\Size#)*2, 0 AddVertex(P\Parent\Surface, EntityX(P\Parent\Piv, True), EntityY(P\Parent\Piv, True), EntityZ(P\Parent\Piv, True), 1, 1) If Not EntityInView(P\Parent\Piv,Pl\Camera) Then F = F + 1 MoveEntity P\Parent\Piv, -Abs(P\Size#), Abs(P\Size#), 0 If Not F = 4 AddTriangle(P\Parent\Surface, P\Vert, P\Vert+1, P\Vert+2) AddTriangle(P\Parent\Surface, P\Vert+2, P\Vert+3, P\Vert) EndIf F = 0 For X = 0 To 3 VertexColor P\Parent\Surface, P\Vert+X, 255, 255, 255, Min(Max(P\Alpha, 1), 0) Next P\V\X = EntityX(P\Parent\Piv, True) : P\V\Y = EntityY(P\Parent\Piv, True) : P\V\Z = EntityZ(P\Parent\Piv, True) EndIf Else Delete P EndIf Next For E.Emitter = Each Emitter UpdateNormals E\Mesh Next Return True End Function ; Frees an Emitter object. ; E = The emitter to be freed. ; return = True if successful, False if not. Function KillEmitter(E.Emitter) If E <> Null Then FreeTexture E\BMap FreeEntity E\Piv FreeEntity E\Mesh Delete E\F Delete E\V Delete E Return True EndIf Return False End Function ; Creates a Magnet object. ; Magnets affect a particle movement and speed. They typically pull particles toward them. ; V = The position of the magnet. ; Radius = The distance particles must be within before they are affected. ; Mag = The magnitude of the magnet. ; Falloff = Whether or not there's a falloff to how much the magnet affects particles. ; Enabled = True if the particles are affected by the magnet, False if not. ; return = A Magnet object, Null if not. Function CreateMagnet.Magnet(V.Vector,Radius#,Mag#,Falloff = True,Enabled=True) M.Magnet = New Magnet If V.Vector <> Null M\V = V M\Rad = Radius M\Mag = Mag M\Enabled = Enabled M\Falloff = Falloff Return M Else Delete M Return Null EndIf End Function ; Creates a vector. ; All parameters represent the fields of a Vector object. ; return = A Vector object. Function Vec.Vector(X#=0,Y#=0,Z#=0,Vel_X#=0,Vel_Y#=0,Vel_Z#=0,Accel_X#=0,Accel_Y#=0,Accel_Z#=0,Pan#=0,Tilt#=0,Roll#=0) ;a duplicate of CreateVector, except it has a shorter name which means it's more convenient to use in cases ;slowly the old name will become deprecated and left in only a few modules, which will open up complete replacement of it with Vec V.Vector = New Vector V\X = X V\Y = Y V\Z = Z V\Pan = Pan V\Tilt = Tilt V\Roll = Roll V\Vel_X = Vel_X V\Vel_Y = Vel_Y V\Vel_Z = Vel_Z V\Accel_X = Accel_X V\Accel_Y = Accel_Y V\Accel_Z = Accel_Z Return V.Vector End Function
Long paste. Hm.