[solved]Can't use "is" class check in an array?

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!)
User avatar
Sir Robin
Posts: 398
Joined: Wed Dec 22, 2021 7:02 pm
Graphics Processor: Intel (Modern GZDoom)
Location: Medellin, Colombia

[solved]Can't use "is" class check in an array?

Post by Sir Robin »

This code works the way I want it to:

Code: Select all

        //make a list of actors to check
        array<actor> CheckTarget;
        ThinkerIterator it = ThinkerIterator.Create("Actor");
        Actor mo;
        while (mo = Actor(it.Next()))
        {
            if (!mo.bNoBlockMap) continue;
            if (mo is "MapMarker") continue;
            if (mo is "WireCube3d") continue;
            CheckTarget.push(mo);
        }
        console.printf("TryIt: %d actors to consider", CheckTarget.size());//DEBUG
This code does not:

Code: Select all

        //Blacklist unwanted actors
        static const string BlackList[] =
        {
            "MapMarker",
            "WireCube3d"
        };
        
        //make a list of actors to check
        array<actor> CheckTarget;
        ThinkerIterator it = ThinkerIterator.Create("Actor");
        Actor mo;
        while (mo = Actor(it.Next()))
        {
            if (!mo.bNoBlockMap) continue;
            for (int i = 0; i < BlackList.size(); i++)
            {
                if (mo is BlackList[i]) continue;
            }
            CheckTarget.push(mo);
        }
        console.printf("TryIt: %d actors to consider", CheckTarget.size());//DEBUG
Last edited by Sir Robin on Wed Jul 27, 2022 5:04 pm, edited 1 time in total.
User avatar
MartinHowe
Posts: 1963
Joined: Mon Aug 11, 2003 1:50 pm
Location: Waveney, United Kingdom

Re: Can't use "is" class check in an array?

Post by MartinHowe »

AFAIK, the compiler 'magic' that converts a string into a class<whatever> in an immediate assignment only works for immediate strings; it's a convenience by the compiler because the idiom of specifying a class immediately happens so often.

You might have replace

Code: Select all

if (mo is BlackList[i]) continue;
with

Code: Select all

class<Actor> someClass = BlackList[i]);
if (mo is someClass]) continue
I have to leave for work soon, so no time to test it, but it's worth a try; the Wiki suggests that should work.
User avatar
Graf Zahl
Lead GZDoom+Raze Developer
Lead GZDoom+Raze Developer
Posts: 48041
Joined: Sat Jul 19, 2003 10:19 am
Location: Germany

Re: Can't use "is" class check in an array?

Post by Graf Zahl »

Better put class type pointers into the array directly. to avoid the lookup completely.

Also, when you say "does not work",that doesn't mean much. How does it fail?
User avatar
Sir Robin
Posts: 398
Joined: Wed Dec 22, 2021 7:02 pm
Graphics Processor: Intel (Modern GZDoom)
Location: Medellin, Colombia

Re: Can't use "is" class check in an array?

Post by Sir Robin »

ah, I think I did something stupid. That inner continue isn't going to continue the outer loop. I'll need another boolean for that.

Meanwhile, yes, I would like to eliminate the string lookup with actual classes. I don't know how to code that. I will have a list of strings containing classes I want put on the exclude list. not all of these classes may exist - some may be defined in optional mods that are not currently loaded. So I only want to put valid classes on that list to save wasting time.

Something like:

Code: Select all

//A simple string list of things I want to exclude
array<string> DesiredExcludes;
DesiredExcludes.push("MapMarker");
DesiredExcludes.push("WireCube3d");

//A list of actual things to exclude
array<something> BlackList;
for (int i = 0; i < DesiredExcludes.size(); i++)
{
    PushIfClassIsDefined(BlackList, DesiredExcludes[i]);
}

//A list of things I want to see
array<actor> CheckTarget;
ThinkerIterator it = ThinkerIterator.Create("Actor");
Actor mo;
while (mo = Actor(it.Next()))
{
    bool ShouldAdd = true;
    ShouldAdd &= mo.bNoBlockMap;
    for (int i = 0; ShouldAdd && i < BlackList.size(); i++)
    {
        ShouldAdd = !(mo is BlackList[i]);
    }
    if (ShouldAdd) CheckTarget.push(mo);
    if (!ShouldAdd) console.printf("Ignoring %s",mo.GetCharacterName());//DEBUG
}
console.printf("TryIt: %d actors to consider", CheckTarget.size());//DEBUG
 
User avatar
MartinHowe
Posts: 1963
Joined: Mon Aug 11, 2003 1:50 pm
Location: Waveney, United Kingdom

Re: Can't use "is" class check in an array?

Post by MartinHowe »

PushIfClassIsDefined is easy; assign the string to a class variable and if the class isn't defined, the variable will be null; so change the middle part to:

Code: Select all

//A list of actual things to exclude
array<something> BlackList;
for (int i = 0; i < DesiredExcludes.size(); i++)
{
    class someClass = DesiredExcludes[i];
    if (someClass != null)
    {
        BlackList.Push(someClass);
    }
}
User avatar
Sir Robin
Posts: 398
Joined: Wed Dec 22, 2021 7:02 pm
Graphics Processor: Intel (Modern GZDoom)
Location: Medellin, Colombia

Re: Can't use "is" class check in an array?

Post by Sir Robin »

Excellent! Thank you!

Final code is here:

Code: Select all

        //Desired Excludes
        array<string> DesiredExcludes;
        DesiredExcludes.push("MapMarker");
        DesiredExcludes.push("WireCube3d");
        DesiredExcludes.push("NonexistingClassName");
        console.printf("TryIt: %d desired excludes", DesiredExcludes.size());//DEBUG
    
        //Actual Excludes
        array<class> BlackList;
        for (int i = 0; i < DesiredExcludes.size(); i++)
        {
            class someClass = DesiredExcludes[i];
            if (someClass) BlackList.push(someClass);
        }
        console.printf("TryIt: %d actual excludes", BlackList.size());//DEBUG
        
        //make a list of actors to check
        array<actor> CheckTarget;
        ThinkerIterator it = ThinkerIterator.Create("Actor");
        Actor mo;
        while (mo = Actor(it.Next()))
        {
            bool ShouldSkip = false;
            ShouldSkip |= !mo.bNoBlockMap;
            for (int i = 0; i < BlackList.size() && !ShouldSkip; i++)
            {
                ShouldSkip = mo is BlackList[i];
            }
            if (ShouldSkip) continue;
            CheckTarget.push(mo);
        }
        console.printf("TryIt: %d actors to consider", CheckTarget.size());//DEBUG
 
User avatar
Graf Zahl
Lead GZDoom+Raze Developer
Lead GZDoom+Raze Developer
Posts: 48041
Joined: Sat Jul 19, 2003 10:19 am
Location: Germany

Re: [solved]Can't use "is" class check in an array?

Post by Graf Zahl »

That's even more inefficient if you reinitialize the arrays in each call.
That makes only sense if you keep them around.

You can also do this:

Code: Select all

		static const class<Actor> choices[] =
		{
			"WraithFX1", "Demon1FX1", "Demon2FX1", "FireDemonMissile", "CentaurFX", "SerpentFX"
		};

Return to “Scripting”