BlockThingsIterator + voodoo dolls + game save = CTD?

Mon Feb 22, 2021 6:06 am

This is a really weird one, so I'm not sure of my example is perfectly minimal, but here's what I managed to compile.

In Beautiful Doom I have Explosive Barrel that fires a BlockThingsIterator every second and searches for other Explosive Barrels nearby, which it then puts in an array (originally this was done to fine-tune the amount of certain visual effects when multiple barrels are close to each other; that part isn't present in the attached example, only the iterator). This resulted in Very Fatal Error when attempting to save the game in Eviternity maps with death exits, so I can only assume it was related to voodoo dolls. As soon as I disabled the iterator, crashes stopped.

Steps to reproduce:
  • Run the attached example (bti_crash.pk3) on a map with a death exit (e.g. Eviternity map 05)
  • Save the game
  • Result: crash to desktop

I was able to trigger this in 4.5.0 as well as a few later dev builds.
You do not have the required permissions to view the files attached to this post.

Re: BlockThingsIterator + voodoo dolls + game save = CTD?

Mon Feb 22, 2021 8:28 am

It has nothing to do with voodoo dolls, the provided code should not compile at all. It's a bug in compiler's type checking. Variable of actor type must not be pushed to array of class types.

Code:
Class CTDExplosiveBarrel : ExplosiveBarrel replaces ExplosiveBarrel {
   private array < Class<CTDExplosiveBarrel> > barrels;  // <-- class type
   const ddist = 14;
   override void Tick() {
      super.Tick();
      if (GetAge() % 35 == 0) {
         BlockThingsIterator itr = BlockThingsIterator.Create(self,ddist);
         while (itr.next()) {
            let obj = itr.thing;
            if (obj == self)
               continue;
            if (!(obj is "CTDExplosiveBarrel"))
               continue;
            if (barrels.Find(obj) != barrels.Size())
               continue;
            if (distance3D(obj) > ddist)
               continue;
            barrels.Push(obj);  // <-- actor type
         }
         console.printf("other barrels nearby: %d",barrels.Size());
      }
   }
}

Re: BlockThingsIterator + voodoo dolls + game save = CTD?

Mon Feb 22, 2021 8:43 am

_mental_ wrote:It has nothing to do with voodoo dolls, the provided code should not compile at all. It's a bug in compiler's type checking. Variable of actor type must not be pushed to array of class types.


...Yes, you're actually right :?

However, not only this code compiles, it actually works (the printf) gives out the correct results. So, there's still a bug there at least.

Re: BlockThingsIterator + voodoo dolls + game save = CTD?

Mon Feb 22, 2021 9:56 am

Yes, there's an elusive type checking bug in the array code. Since the actors get pushed onto the array, the count will be correct, though.

Re: BlockThingsIterator + voodoo dolls + game save = CTD?

Mon Feb 22, 2021 3:39 pm

The thing is, I started with private array < CTDExplosiveBarrel > barrels, and barrels.Push(obj) gave me a "return type mismatch". That's when I got confused and changed the array type. Apparently I simply had to cast obj.