[ZScript] Problems Extending A_SpawnItemEx

Ask about ACS, DECORATE, ZScript, or any other scripting questions here!

Moderator: GZDoom Developers

Forum rules
Before asking on how to use a ZDoom feature, read the ZDoom wiki first. If you still don't understand how to use a feature, then ask here.

Please bear in mind that the people helping you do not automatically know how much you know. You may be asked to upload your project file to look at. Don't be afraid to ask questions about what things mean, but also please be patient with the people trying to help you. (And helpers, please be patient with the person you're trying to help!)

[ZScript] Problems Extending A_SpawnItemEx

Postby 22alpha22 » Fri Jan 14, 2022 11:41 am

This is a somewhat difficult problem to explain because I don't know exactly what is wrong so I'll start by explaining what I'm trying to accomplish. I'm trying to extend a A_SpawnItemEx by copying it to a new function and adding the additional bits I want to it. I'm trying to add the ability to set a spawned actor's pitch and roll through parameters rather than being limited to inheriting the calling actor's pitch and roll. I'm also trying to add a flag that will automatically take the spawned actor's pitch into account when setting the actor's velocity, this will be useful projectiles for instance.

I've been working with and learning ZScript for about two or three years now and have built a fairly reasonable foundation with it, so I know how to go about adding these additional features to A_SpawnItemEx in theory. The problem is my math skills. I never finished high school because of real life reasons I won't discuss here, nonetheless, it left some real holes in my education related to Trig, Algebra, and Calculus which have caused me no end of grief in my modding career for various games, Doom being no exception. I've managed to add the ability to set the spawned actor's pitch and roll but I lack the necessary math skills to figure out how to set an actor's velocity if pitch should be taken into account for said velocity. I've attempted to figure it out myself and sometimes it seems to work right and other times the spawned actor's velocity is completely out of whack. The last feature I want is for the spawned actor's positional offsets to take the actor's pitch into account if a flag is passed. For example, if the actor is spawned pitching up at 45 degrees, the X offset should raise the actor as well as move it forward by the appropriate amount. I have absolutely no idea how to implement this so I haven't even tried.

Here is what I've got so far, if anyone can help me figure out what I've done wrong with the velocity calculations, I would greatly appreciate it. Extra kudos if someone can show me how to have the spawned offsets take into account the actor's pitch.
Code: Select allExpand view
Enum ESpawnItemExtendedFlags
{
   SXF_ABSOLUTEPITCH = 1 << 29,
   SXF_ABSOLUTEROLL = 1 << 30,
   SXF_VELOCITYFROMPITCH = 1 << 31,
   SXF_OFFSETFROMPITCH = 1 << 32,
};

Bool, Actor A_SpawnItemExtended(Class<Actor> Actr, Double XOfs = 0.0, Double YOfs = 0.0, Double ZOfs = 0.0, Double XVel = 0.0, Double YVel = 0.0, Double ZVel = 0.0, Double Angle = 0.0, Double Pitch = 0.0, Double Roll = 0.0, Int Flags = 0, Int FailChance = 0, Int TID = 0)
   {
      Vector2 Pos;
      Double S;
      Double C;
      Double NewXVel;
      Bool Res;
      Vector3 PitchSpeed;

      If (!Actr)
      {
         Return False, Null;
      }

      If (FailChance > 0 && Random[SpawnItemEx]() < FailChance)
      {
         Return True, Null;
      }

      If (DamageType == 'Massacre' && GetDefaultByType(Actr).bIsMonster)
      {
         Return True, Null;
      }

      If (!(Flags & SXF_ABSOLUTEANGLE))
      {
         Angle += Self.Angle;
      }

      If (!(Flags & SXF_ABSOLUTEPITCH))
      {
         Pitch += Clamp(Self.Pitch,-90.0,90.0);
      }

      If (!(Flags & SXF_ABSOLUTEROLL))
      {
         Roll += Self.Roll;
      }

      S = Sin(Angle);
      C = Cos(Angle);

      If (Flags & SXF_ABSOLUTEPOSITION)
      {
         Pos = Vec2Offset(XOfs,YOfs);
      }
      Else
      {
         If (Flags & SXF_OFFSETFROMPITCH)
         {
            //No idea how to implement this
         }
         Else
         {
            Pos = Vec2Offset(XOfs * C + YOfs * S,XOfs * S - YOfs * C);
         }
      }

      If (!(Flags & SXF_ABSOLUTEVELOCITY))
      {
         NewXVel = XVel * C + YVel * S;
         YVel = XVel * S - YVel * C;
         XVel = NewXVel;
         ZVel = Self.Vel.Z + ZVel;
      }

      Let MO = Spawn(Actr,(Pos,Self.Pos.Z - Floorclip + GetBobOffset() + ZOfs),ALLOW_REPLACE);
      Res = InitSpawnedItem(MO,Flags);

      If (Res)
      {
         If (TID != 0)
         {
            MO.ChangeTid(TID);
         }

         MO.Vel = (XVel, YVel, ZVel);
         Pitch = Clamp(Pitch,-90.0,90.0);

         MO.Angle = Angle;
         MO.Pitch = Pitch;
         MO.Roll = Roll;

         If (Flags & SXF_VELOCITYFROMPITCH)
         {
            PitchSpeed = (Cos(MO.Pitch) * XVel,YVel,(-Sin(MO.Pitch) * XVel) + ZVel);
            MO.Vel = PitchSpeed;
         }

         If (Flags & SXF_MULTIPLYSPEED)
         {
            MO.Vel *= MO.Speed;
         }
      }

      Return Res, MO;
   }
User avatar
22alpha22
So lonely...
 
Joined: 21 Feb 2014
Location: Montana, USA
Operating System: Windows Vista/7/2008 64-bit
Graphics Processor: nVidia (Modern GZDoom)

Return to Scripting

Who is online

Users browsing this forum: No registered users and 1 guest