diff --git a/src/playsim/p_actionfunctions.cpp b/src/playsim/p_actionfunctions.cpp index 851b72b834..c1a891a0db 100644 --- a/src/playsim/p_actionfunctions.cpp +++ b/src/playsim/p_actionfunctions.cpp @@ -1676,6 +1676,72 @@ DEFINE_ACTION_FUNCTION(AActor, A_SpawnParticle) return 0; } +DEFINE_ACTION_FUNCTION(AActor, A_SpawnParticleEx) +{ + PARAM_SELF_PROLOGUE(AActor); + PARAM_COLOR (color); + PARAM_INT (i_texid) + PARAM_INT (style) + PARAM_INT (flags) + PARAM_INT (lifetime) + PARAM_FLOAT (size) + PARAM_ANGLE (angle) + PARAM_FLOAT (xoff) + PARAM_FLOAT (yoff) + PARAM_FLOAT (zoff) + PARAM_FLOAT (xvel) + PARAM_FLOAT (yvel) + PARAM_FLOAT (zvel) + PARAM_FLOAT (accelx) + PARAM_FLOAT (accely) + PARAM_FLOAT (accelz) + PARAM_FLOAT (startalpha) + PARAM_FLOAT (fadestep) + PARAM_FLOAT (sizestep) + + startalpha = clamp(startalpha, 0., 1.); + if (fadestep > 0) fadestep = clamp(fadestep, 0., 1.); + size = fabs(size); + if (lifetime != 0) + { + if (flags & SPF_RELANG) angle += self->Angles.Yaw; + double s = angle.Sin(); + double c = angle.Cos(); + DVector3 pos(xoff, yoff, zoff + self->GetBobOffset()); + DVector3 vel(xvel, yvel, zvel); + DVector3 acc(accelx, accely, accelz); + //[MC] Code ripped right out of A_SpawnItemEx. + if (flags & SPF_RELPOS) + { + // in relative mode negative y values mean 'left' and positive ones mean 'right' + // This is the inverse orientation of the absolute mode! + pos.X = xoff * c + yoff * s; + pos.Y = xoff * s - yoff * c; + } + if (flags & SPF_RELVEL) + { + vel.X = xvel * c + yvel * s; + vel.Y = xvel * s - yvel * c; + } + if (flags & SPF_RELACCEL) + { + acc.X = accelx * c + accely * s; + acc.Y = accelx * s - accely * c; + } + + FTextureID texid; + texid.SetIndex(i_texid); + + if(style < 0 || style >= STYLE_Count) + { + style = STYLE_None; + } + + P_SpawnParticle(self->Level, self->Vec3Offset(pos), vel, acc, color, startalpha, lifetime, size, fadestep, sizestep, flags, texid, ERenderStyle(style)); + } + return 0; +} + //=========================================================================== // // A_CheckSight diff --git a/src/playsim/p_effect.cpp b/src/playsim/p_effect.cpp index 38fa616515..ee8abf7aa3 100644 --- a/src/playsim/p_effect.cpp +++ b/src/playsim/p_effect.cpp @@ -278,7 +278,7 @@ enum PSFlag }; void P_SpawnParticle(FLevelLocals *Level, const DVector3 &pos, const DVector3 &vel, const DVector3 &accel, PalEntry color, double startalpha, int lifetime, double size, - double fadestep, double sizestep, int flags) + double fadestep, double sizestep, int flags, FTextureID texture, ERenderStyle style) { particle_t *particle = NewParticle(Level); @@ -296,6 +296,8 @@ void P_SpawnParticle(FLevelLocals *Level, const DVector3 &pos, const DVector3 &v particle->size = size; particle->sizestep = sizestep; particle->notimefreeze = !!(flags & PS_NOTIMEFREEZE); + particle->texture = texture; + particle->style = style; } } diff --git a/src/playsim/p_effect.h b/src/playsim/p_effect.h index 9d2d16ef0c..92176541a7 100644 --- a/src/playsim/p_effect.h +++ b/src/playsim/p_effect.h @@ -35,6 +35,7 @@ #include "vectors.h" #include "doomdef.h" +#include "renderstyle.h" enum { @@ -65,6 +66,8 @@ struct particle_t int color; uint16_t tnext; uint16_t snext; + FTextureID texture; + ERenderStyle style; }; const uint16_t NO_PARTICLE = 0xffff; @@ -80,7 +83,7 @@ particle_t *JitterParticle (FLevelLocals *Level, int ttl); particle_t *JitterParticle (FLevelLocals *Level, int ttl, double drift); void P_ThinkParticles (FLevelLocals *Level); -void P_SpawnParticle(FLevelLocals *Level, const DVector3 &pos, const DVector3 &vel, const DVector3 &accel, PalEntry color, double startalpha, int lifetime, double size, double fadestep, double sizestep, int flags = 0); +void P_SpawnParticle(FLevelLocals *Level, const DVector3 &pos, const DVector3 &vel, const DVector3 &accel, PalEntry color, double startalpha, int lifetime, double size, double fadestep, double sizestep, int flags = 0, FTextureID texture = FNullTextureID(), ERenderStyle style = STYLE_None); void P_InitEffects (void); void P_RunEffect (AActor *actor, int effects); diff --git a/src/rendering/hwrenderer/scene/hw_sprites.cpp b/src/rendering/hwrenderer/scene/hw_sprites.cpp index 97fe05738e..480b31c848 100644 --- a/src/rendering/hwrenderer/scene/hw_sprites.cpp +++ b/src/rendering/hwrenderer/scene/hw_sprites.cpp @@ -1277,7 +1277,16 @@ void HWSprite::ProcessParticle (HWDrawInfo *di, particle_t *particle, sector_t * } trans=particle->alpha; - RenderStyle = STYLE_Translucent; + + if(particle->style != STYLE_None) + { + RenderStyle = particle->style; + } + else + { + RenderStyle = STYLE_Translucent; + } + OverrideShader = 0; ThingColor = particle->color; @@ -1289,17 +1298,21 @@ void HWSprite::ProcessParticle (HWDrawInfo *di, particle_t *particle, sector_t * bottomclip = -LARGE_VALUE; index = 0; + bool has_texture = !particle->texture.isNull(); + + int particle_style = has_texture ? 2 : gl_particles_style; // Treat custom texture the same as smooth particles + // [BB] Load the texture for round or smooth particles - if (gl_particles_style) + if (particle_style) { FTextureID lump; - if (gl_particles_style == 1) + if (particle_style == 1) { lump = TexMan.glPart2; } - else if (gl_particles_style == 2) + else if (particle_style == 2) { - lump = TexMan.glPart; + lump = has_texture ? particle -> texture : TexMan.glPart; } else lump.SetNull(); @@ -1329,8 +1342,8 @@ void HWSprite::ProcessParticle (HWDrawInfo *di, particle_t *particle, sector_t * z = float(particle->Pos.Z) + zvf; float factor; - if (gl_particles_style == 1) factor = 1.3f / 7.f; - else if (gl_particles_style == 2) factor = 2.5f / 7.f; + if (particle_style == 1) factor = 1.3f / 7.f; + else if (particle_style == 2) factor = 2.5f / 7.f; else factor = 1 / 7.f; float scalefac=particle->size * factor; @@ -1351,7 +1364,7 @@ void HWSprite::ProcessParticle (HWDrawInfo *di, particle_t *particle, sector_t * fullbright = !!particle->bright; // [BB] Translucent particles have to be rendered without the alpha test. - if (gl_particles_style != 2 && trans>=1.0f-FLT_EPSILON) hw_styleflags = STYLEHW_Solid; + if (particle_style != 2 && trans>=1.0f-FLT_EPSILON) hw_styleflags = STYLEHW_Solid; else hw_styleflags = STYLEHW_NoAlphaTest; if (sector->e->XFloor.lightlist.Size() != 0 && !di->isFullbrightScene() && !fullbright) diff --git a/wadsrc/static/zscript/actors/actor.zs b/wadsrc/static/zscript/actors/actor.zs index 68fc53dd64..903cc880d4 100644 --- a/wadsrc/static/zscript/actors/actor.zs +++ b/wadsrc/static/zscript/actors/actor.zs @@ -1128,6 +1128,7 @@ class Actor : Thinker native native void A_FadeTo(double target, double amount = 0.1, int flags = 0); native void A_SpawnDebris(class spawntype, bool transfer_translation = false, double mult_h = 1, double mult_v = 1); native void A_SpawnParticle(color color1, int flags = 0, int lifetime = TICRATE, double size = 1, double angle = 0, double xoff = 0, double yoff = 0, double zoff = 0, double velx = 0, double vely = 0, double velz = 0, double accelx = 0, double accely = 0, double accelz = 0, double startalphaf = 1, double fadestepf = -1, double sizestep = 0); + native void A_SpawnParticleEx(color color1, TextureID texture, int style = STYLE_None, int flags = 0, int lifetime = TICRATE, double size = 1, double angle = 0, double xoff = 0, double yoff = 0, double zoff = 0, double velx = 0, double vely = 0, double velz = 0, double accelx = 0, double accely = 0, double accelz = 0, double startalphaf = 1, double fadestepf = -1, double sizestep = 0); native void A_ExtChase(bool usemelee, bool usemissile, bool playactive = true, bool nightmarefast = false); native void A_DropInventory(class itemtype, int amount = -1); native void A_SetBlend(color color1, double alpha, int tics, color color2 = 0, double alpha2 = 0.);