Multiple extends

Moderator: GZDoom Developers

User avatar
Rip and Tear
Posts: 185
Joined: Tue May 02, 2017 3:54 pm

Multiple extends

Post by Rip and Tear »

One of the limitations of ZScript's `extend` functionality is that it can only extend classes defined in the same mod. Unfortunately, this makes it significantly less useful when working with classes that share a superclass in gzdoom.pk3. Often, you will need to either include the same code in multiple places, or replicate code that already exists in gzdoom.pk3.

I believe this feature suggestion would help to somewhat alleviate that. Class extensions should be able to be used on multiple classes at once, separated with commas. This would just be a bit of syntactic sugar added to the compiler.

Code: Select all

extend class foo, bar {
    //...
}
would be exactly equivalent to

Code: Select all

extend class foo {
    //...
}
extend class bar {
    //...
}
This would help to reduce code duplication when inheriting from actor classes in gzdoom.pk3. For example, if you were to define custom classes inheriting from Hexen's three playable classes, you could then add behavior to all three of them without having to copy/paste code.
User avatar
Graf Zahl
Lead GZDoom+Raze Developer
Lead GZDoom+Raze Developer
Posts: 49053
Joined: Sat Jul 19, 2003 10:19 am
Location: Germany

Re: Multiple extends

Post by Graf Zahl »

I don't think this is a good idea. It would give modders a wrong impression of having behavior in different classes that can be accessed through a common interface. Even if this was implemented you'd still have two unrelated classes that may have copies of the same implementation but absolutely no means to access this in a common fashion.

Besides, since it still would be limited to classes in the same translation unit, it'd be better to code the common behavior properly into a base class where it is properly shared.
In short, all it'd do is allow for dirty implementations.
User avatar
Rip and Tear
Posts: 185
Joined: Tue May 02, 2017 3:54 pm

Re: Multiple extends

Post by Rip and Tear »

Graf Zahl wrote:Besides, since it still would be limited to classes in the same translation unit, it'd be better to code the common behavior properly into a base class where it is properly shared.
Though this would still require you to replicate code that already exists in gzdoom.pk3. Sticking with the Hexen class example, you would need to make make a class which inherits from PlayerPawn to include common behavior, then copy/paste the entire definitions for all three classes and inherit from the custom class.

The only other option I've come across is to make a helper class with static methods and pass `self` as the first argument. Which works, but is also very clunky.
Last edited by Rip and Tear on Wed Dec 26, 2018 8:02 pm, edited 2 times in total.
User avatar
Graf Zahl
Lead GZDoom+Raze Developer
Lead GZDoom+Raze Developer
Posts: 49053
Joined: Sat Jul 19, 2003 10:19 am
Location: Germany

Re: Multiple extends

Post by Graf Zahl »

Can you please lay out your use case? I somehow have a feeling that you are approaching this from the wrong angle conceptually.
User avatar
Rip and Tear
Posts: 185
Joined: Tue May 02, 2017 3:54 pm

Re: Multiple extends

Post by Rip and Tear »

Graf Zahl wrote:Can you please lay out your use case? I somehow have a feeling that you are approaching this from the wrong angle conceptually.
Say someone wrote improved versions of the monster 'AI' functions (such as A_Chase) and I wanted to implement it into my Doom mod. Ideally, the per-actor implementation would just be

Code: Select all

class NewZombieMan : ZombieMan replaces ZombieMan {
    States {
    See:
        POSS AABBCCDD 4 A_EnhancedChase();
        Loop;
    }
}
In actuality, I would need to either copy and paste the functions into each actor definition; include the actor functions in a base monster class to inherit from, thereby losing the ability to inherit from the monster classes already defined in gzdoom.pk3; or use the clunky helper class method I described.

Perhaps this diagram will help to explain the problem.
Diagram.png
User avatar
Caligari87
Admin
Posts: 6174
Joined: Thu Feb 26, 2004 3:02 pm
Preferred Pronouns: He/Him
Contact:

Re: Multiple extends

Post by Caligari87 »

One potential workaround is to use a static function in a separate thinker/class as a proxy. Matt does this in Hideous Destructor, for example.

Code: Select all

class NewZombieMan : ZombieMan replaces ZombieMan {
    States {
    See:
        POSS AABBCCDD 4 MyFunctions.EnhancedChase(self);
        Loop;
    }
}

class MyFunctions {
    static void EnhancedChase(actor caller) {
        //do fancy movement
        caller.vel.x += 15;
    }
}
8-)
User avatar
Graf Zahl
Lead GZDoom+Raze Developer
Lead GZDoom+Raze Developer
Posts: 49053
Joined: Sat Jul 19, 2003 10:19 am
Location: Germany

Re: Multiple extends

Post by Graf Zahl »

To get here it is first necessary to scriptify all actor subclasses. Unfortunately there's still two major ones which aren't scriptable yet, namely PlayerPawn and DynamicLight, the former because it still depends on too much native functionality and the latter one because it is normally the one with the highest cumulative thinker overhead of all classes in a loaded map. To scriptify this one I first have to uncouple the light rendering from the backing actor and thanks to people hacking its properties live (since the args are modifiable even from ACS) this is not going to be easy without breaking stuff.
User avatar
Rip and Tear
Posts: 185
Joined: Tue May 02, 2017 3:54 pm

Re: Multiple extends

Post by Rip and Tear »

Caligari87 wrote:One potential workaround is to use a static function in a separate thinker/class as a proxy. Matt does this in Hideous Destructor, for example.

Code: Select all

class NewZombieMan : ZombieMan replaces ZombieMan {
    States {
    See:
        POSS AABBCCDD 4 MyFunctions.EnhancedChase(self);
        Loop;
    }
}

class MyFunctions {
    static void EnhancedChase(actor caller) {
        //do fancy movement
        caller.vel.x += 15;
    }
}
8-)
I'm aware of this method and it's definitely the best one available at the time. But having to prefix with `caller` so often leads to rather clunky syntax.
User avatar
Graf Zahl
Lead GZDoom+Raze Developer
Lead GZDoom+Raze Developer
Posts: 49053
Joined: Sat Jul 19, 2003 10:19 am
Location: Germany

Re: Multiple extends

Post by Graf Zahl »

I'm working on it. I'm almost done exporting PlayerPawn which is the last remaining blocker for allowing user-side extends of class Actor.
User avatar
Caligari87
Admin
Posts: 6174
Joined: Thu Feb 26, 2004 3:02 pm
Preferred Pronouns: He/Him
Contact:

Re: Multiple extends

Post by Caligari87 »

excited incoherent screaming

Graf you're the best. This'll be a game-changer.

8-)
User avatar
Major Cooke
Posts: 8170
Joined: Sun Jan 28, 2007 3:55 pm
Preferred Pronouns: He/Him
Location: QZDoom Maintenance Team

Re: Multiple extends

Post by Major Cooke »

How will this work when done?
User avatar
Graf Zahl
Lead GZDoom+Raze Developer
Lead GZDoom+Raze Developer
Posts: 49053
Joined: Sat Jul 19, 2003 10:19 am
Location: Germany

Re: Multiple extends

Post by Graf Zahl »

It means that 'extends' blocks to all actor classes can be done in user code. The reason why this wasn't possible yet is that all the native children would have broken if a base class was extended.

For non-actors this isn't really important because there's little to be gained by extending them.
User avatar
Rip and Tear
Posts: 185
Joined: Tue May 02, 2017 3:54 pm

Re: Multiple extends

Post by Rip and Tear »

heavy breathing
User avatar
Major Cooke
Posts: 8170
Joined: Sun Jan 28, 2007 3:55 pm
Preferred Pronouns: He/Him
Location: QZDoom Maintenance Team

Re: Multiple extends

Post by Major Cooke »

This sounds like it's eventually paving the way towards being able to inject/override states without needing to replace the actor. Removing the need to replace one actor with another just so it doesn't have to be given some little tweaks would be a godsend.

For example, if an addon modifies a state, it could TRULY replace it -- possibly even affecting the goto -- via some definition like:

Code: Select all

extends class Zombieman
{
States.MyAddonIdentifierHere
{
Spawn:
...which would be in the addon code, replacing the spawn state without replacing the actor. But the actor themselves could still use something like Goto <ClassName>::Spawn or something to make it use the original.

But then again I am effectively deluding myself into thinking its even possible. Feel free to correct me if I'm not deluding though!
User avatar
Graf Zahl
Lead GZDoom+Raze Developer
Lead GZDoom+Raze Developer
Posts: 49053
Joined: Sat Jul 19, 2003 10:19 am
Location: Germany

Re: Multiple extends

Post by Graf Zahl »

State label overrides won't be possible. That'd be too volatile.
Post Reply

Return to “Closed Feature Suggestions [GZDoom]”