Page 1 of 1

A_SprayDecal As A Replacement For Blood Decal Generation

Posted: Fri May 20, 2022 8:11 pm
by 22alpha22
Because of issues outlined in these two threads, (viewtopic.php?f=18&t=74509) (viewtopic.php?f=15&t=73639) I am trying implement my own blood decal generation system. A_SprayDecal used from within DamageMObj looks like it will accomplish the task but I am having trouble figuring out precisely how it works. The wiki doesn't seem to know how the offset or direction parameters work and has no examples. With some tinkering and testing, I've got the offset parameter figured out but I still don't understand the direction parameter.

I've checked the source and found this which I think is what A_SprayDecal calls natively but I'm not sure.

Code: Select all

void SprayDecal(AActor *shooter, const char *name, double distance, DVector3 offset, DVector3 direction, bool useBloodColor, uint32_t decalColor)
{
   //just in case
   if (!shooter)
      return;

   FTraceResults trace;
   DVector3 off(0, 0, 0), dir(0, 0, 0);

   //use vanilla offset only if "custom" equal to zero
   if (offset.isZero() )
      off = shooter->PosPlusZ(shooter->Height / 2);

   else
      off = shooter->Pos() + offset;

   //same for direction
   if (direction.isZero() )
   {
      DAngle ang = shooter->Angles.Yaw;
      DAngle pitch = shooter->Angles.Pitch;
      double c = pitch.Cos();
      dir = DVector3(c * ang.Cos(), c * ang.Sin(), -pitch.Sin());
   }
   
   else
      dir = direction;

   uint32_t bloodTrans = useBloodColor ? shooter->BloodTranslation : 0;
   PalEntry entry = !useBloodColor ? (PalEntry)decalColor : shooter->BloodColor;

   if (Trace(off, shooter->Sector, dir, distance, 0, ML_BLOCKEVERYTHING, shooter, trace, TRACE_NoSky))
   {
      if (trace.HitType == TRACE_HitWall)
      {
         DImpactDecal::StaticCreate(shooter->Level, name, trace.HitPos, trace.Line->sidedef[trace.Side], NULL, entry, bloodTrans);
      }
   }
}

I'm not a programmer and I'm having a bit of trouble figuring out exactly how this function works. I searched around in the source to see if I could find where exactly an actor calls whatever function is used to generate blood decals but I couldn't find it.

Here is what I know about A_SprayDecal and what I need help with:

Name: Fairly obvious, the name of the decal to spawn. I already have my own function which can supply the appropriate decal name.

Distance: Also obvious, the maximum distance from the calling actor that the decal can spawn. It would however be nice to know what the max distance value is that the hardcoded blood decal generation system uses.

Offset: Required a bit of testing to figure it out but it seems that the Vector is an offset based on the calling actors current position. Vector.X is the offset on the X axis, Vector.Y is the offset on the Y axis, and Vector.Z is the offset on the Z axis. Makes sense but note that the offsets are NOT relative to the actors facing. Like distance, it would be helpful to know exactly how the hardcoded blood decal generation handles offsets.

Direction: I haven't been able to figure out how this parameter works. If it was a Vector2, then I would assume one value would be for Angle and the other for Pitch, but since it is a Vector3, I have no idea. Understanding how this parameter works and how exactly the hardcoded blood generation calculates the direction is the single most important part of getting my custom blood generation working.

Thanks ahead of time for any help on this. :)