Communicating between one actor and another

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.

Communicating between one actor and another

Postby Xtyfe » Sat Apr 24, 2021 8:48 am

Using code from viewtopic.php?f=122&t=70826 provided by Player701 (Thank you!). I wanted to make it so this Revenant was limited to one seeker missile at a time. I had no idea how to communicate between the Revenant and its projectile so I asked on Discord. It was suggested that I use OnDestroy to do this. However, this caused a VM abort which I had believed to be due to the fact the code for the seeker already used Destroy(). I tried another method as seen below but this also causes a VM abort.

What am I doing wrong? Sorry, this isn't a runnable example, I'd be happy to test any suggestions though.

Code: Select allExpand view
Class XtRevenant : XtCommonMonster Replaces Revenant
{
   Default
   {
      Health 300;
      Radius 20;
      Height 56;
      Mass 200;
      Speed 10;
      PainChance 100;
      MeleeThreshold 196;
      BloodColor "820000";
      Species "Revenant";
      SeeSound "skeleton/sight";
      PainSound "skeleton/pain";
      DeathSound "skeleton/death";
      ActiveSound "skeleton/active";
      HitObituary "$OB_UNDEADHIT";
      Obituary "$OB_UNDEAD";
      Tag "$FN_REVEN";
      +FLOORCLIP
   }
   
   int missile_count;
   
   States
   {
   Spawn:
      SKEL AB 10 NoDelay A_XtLook ();
      Loop;
   See:
      SKEL AABBCCDDEEFF 2 A_XtChase ();
      Loop;
   Melee:
      SKEL G 5
         {
            A_FaceTarget ();
            A_StartSound ("skeleton/swing", CHAN_WEAPON);
         }
      SKEL H 5 A_FaceTarget ();
      SKEL I 10 A_CustomMeleeAttack (Random (1, 10)*5, "skeleton/melee", "", "Melee", 1);
      Goto See;
   Missile:
      SKEL J 10 A_FaceTarget ();
      SKEL J 10 Bright
         {
            If (missile_count != 1)
            {
               A_SpawnProjectile ('XtRevenantTracerTracker', 60);
               missile_count = 1;
            }
            else
            {
               A_SpawnProjectile ('XtRevenantTracerTrackerNoSeek', 60);
            }
         }
      SKEL K 10 A_FaceTarget ();
      Goto See;
   Pain:
      SKEL L 3;
      SKEL L 3 A_Pain;
      Goto See;
   Death:
      SKEL LM 5;
      SKEL N 5 A_Scream;
      SKEL O 5 A_NoBlocking;
      SKEL P 5;
      SKEL Q -1;
      Stop;
   Raise:
      SKEL QPONML 5;
      Goto See;
   }
}

Class XtRevenantTracerTracker : Actor
{
    XtRevenantTracer t1, t2;
   XtRevenant revmaster;

    Default
    {
        Radius 1;
        Height 1;
        Projectile;
        Speed 10;
        +NOINTERACTION;
        +SEEKERMISSILE;
    }
   
    override void PostBeginPlay()
    {
        Super.PostBeginPlay();

        t1 = XtRevenantTracer (A_SpawnProjectile ('XtRevenantTracer', -1, -19, flags: CMF_TRACKOWNER));
        t2 = XtRevenantTracer (A_SpawnProjectile ('XtRevenantTracer', 1, 14, flags: CMF_TRACKOWNER));
      
        bool ok = Tracer != null && t1 != null && t2 != null;

        // Set initial velocities

        double ang = Tracer != null ? AngleTo(Tracer, true) : Angle;

        if (t1 != null)
        {
            t1.Angle = ang;           
            t1.Vel.Z = Vel.Z;
            t1.VelFromAngle();
        }

        if (t2 != null)
        {
            t2.Angle = ang;
            t2.Vel.Z = Vel.Z;
            t2.VelFromAngle();
        }

        if (ok) // both missiles present and have tracer
        {
            t1.tracker = t2.tracker = self;
        }
        else
        {
         revmaster.missile_count = 0;
         Destroy();
         return;
        }
    }

    override void Tick()
    {
        Super.Tick();

        if (t1 != null && t1.Tracer == Tracer && t2 != null && t2.Tracer == Tracer)
        {
            // Adjust the velocities of the tracked missiles
            // to match the velocity of this actor.
            t1.Angle = t2.Angle = Angle;
            t1.Vel = t2.Vel = Vel;
        }
        else
        {
         revmaster.missile_count = 0;
         Destroy();
         return;
        }
    }
   
   States
    {
        Spawn:
            TNT1 A 4
            {
               XtRevenantTracer.DoSeek(self);
            }
            Loop;
    }
}

Class XtRevenantTracer : Actor
{

    XtRevenantTracerTracker tracker;

   Default
   {
      Radius 11;
      Height 8;
      Scale 0.5;
      Speed 10;
      MaxTargetRange 16;
      DamageFunction (Random(1, 8)*5);
      DamageType "Ballistic";
      Projectile;
      SeeSound "skeleton/attack";
      DeathSound "skeleton/tracex";
      RenderStyle "Add";
      Decal "RevenantScorch";
      +FORCEXYBILLBOARD
      +NOFORWARDFALL
      +SEEKERMISSILE
      +RANDOMIZE
      +ZDOOMTRANS
   }
   
   static void DoSeek(Actor source)
    {
        source.A_SeekerMissile (10, 30, SMF_LOOK | SMF_PRECISE, 64, 16);
    }
   
    void A_XtRevenantTracerInFlight()
    {
        A_SpawnItemEx ('XtRocketSmokeTrail', 0, 0, 0, 0, 0, 0, 0, SXF_ORIGINATOR, 0, 0);
      
        if (GetAge() > 0 && (tracker == null || Tracer != tracker.Tracer))
        {
            DoSeek(self);
        }
    }
   
    States
    {
        Spawn:
            FATB AB 4 NoDelay Bright A_XtRevenantTracerInFlight ();
            Loop;
        Death:
            FBXP ABC 4 Bright;
            Stop;
    }
}

Class XtRevenantTracerTrackerNoSeek : Actor
{
    XtRevenantTracerNoSeek t1, t2;

    Default
    {
        Radius 1;
        Height 1;
        Projectile;
        Speed 10;
        +NOINTERACTION;
    }
   
    override void PostBeginPlay()
    {
        Super.PostBeginPlay();

        t1 = XtRevenantTracerNoSeek (A_SpawnProjectile ('XtRevenantTracerNoSeek', -1, -19, flags: CMF_TRACKOWNER));
        t2 = XtRevenantTracerNoSeek (A_SpawnProjectile ('XtRevenantTracerNoSeek', 1, 14, flags: CMF_TRACKOWNER));
      
        bool ok = Tracer != null && t1 != null && t2 != null;

        // Set initial velocities

        double ang = Tracer != null ? AngleTo(Tracer, true) : Angle;

        if (t1 != null)
        {
            t1.Angle = ang;           
            t1.Vel.Z = Vel.Z;
            t1.VelFromAngle();
        }

        if (t2 != null)
        {
            t2.Angle = ang;
            t2.Vel.Z = Vel.Z;
            t2.VelFromAngle();
        }

        if (ok) // both missiles present and have tracer
        {
            t1.tracker = t2.tracker = self;
        }
        else
        {
         Destroy();
         return;
        }
    }

    override void Tick()
    {
        Super.Tick();

        if (t1 != null && t1.Tracer == Tracer && t2 != null && t2.Tracer == Tracer)
        {
            // Adjust the velocities of the tracked missiles
            // to match the velocity of this actor.
            t1.Angle = t2.Angle = Angle;
            t1.Vel = t2.Vel = Vel;
        }
        else
        {
         Destroy();
         return;
        }
    }
   
   States
    {
        Spawn:
            TNT1 A 4;
            Loop;
    }
}

Class XtRevenantTracerNoSeek : Actor
{

    XtRevenantTracerTrackerNoSeek tracker;

   Default
   {
      Radius 11;
      Height 8;
      Scale 0.5;
      Speed 10;
      MaxTargetRange 16;
      DamageFunction (Random(1, 8)*5);
      DamageType "Ballistic";
      Projectile;
      SeeSound "skeleton/attack";
      DeathSound "skeleton/tracex";
      RenderStyle "Add";
      Decal "RevenantScorch";
      +FORCEXYBILLBOARD
      +NOFORWARDFALL
      +RANDOMIZE
      +ZDOOMTRANS
   }   
    States
    {
        Spawn:
            FATB AB 4 NoDelay Bright A_SpawnItemEx ('XtRocketSmokeTrail', 0, 0, 0, 0, 0, 0, 0, SXF_ORIGINATOR, 0, 0);
            Loop;
        Death:
            FBXP ABC 4 Bright;
            Stop;
    }
}
User avatar
Xtyfe
Neque Deos, Neque Dominos
 
Joined: 14 Dec 2007
Operating System: Windows 10/8.1/8/201x 64-bit
Graphics Processor: nVidia with Vulkan support

Re: Communicating between one actor and another

Postby Xtyfe » Sat Apr 24, 2021 2:02 pm

I figured this out myself thanks to the wiki. The concept I was looking for was casting https://zdoom.org/wiki/Using_pointers_in_ZScript
User avatar
Xtyfe
Neque Deos, Neque Dominos
 
Joined: 14 Dec 2007
Operating System: Windows 10/8.1/8/201x 64-bit
Graphics Processor: nVidia with Vulkan support


Return to Scripting

Who is online

Users browsing this forum: 4page and 1 guest