How to handle a parallel inheritance?

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

How to handle a parallel inheritance?

Post by Sir Robin »

I want to create my own object to extend the actor class. Let's call it UW_ObjectBase because my actual object will then inherit from that.
Then I want some of these objects be pickups, so I'll create a class called UW_PickupBase for those items to inherit. The thing is I want that class to inherit Inventory for it's features but also UW_ObjectBase for it's features.
Then I want to create a UW_WeaponBase that will inherit Weapon but also needs to inherit the other UW features.

What's the best way to handle this?

Also, I see this on the [wiki]Classes:Weapon[/wiki] wiki page:
A player can never carry more than one weapon of each kind.

Like with normal inventory items, an actor can have more than one sample of a weapon in its inventory.
What does that mean, only one kind but more than one sample? If I had two of the same weapon definitions, say an axe, but one had a durability of 5 and the other 20, and I want to carry both, then 5 until it breaks and then I'll switch to the 20. How would I code that?
User avatar
m8f
 
 
Posts: 1445
Joined: Fri Dec 29, 2017 4:15 am
Preferred Pronouns: He/Him
Operating System Version (Optional): Manjaro Linux
Location: Siberia (UTC+7)
Contact:

Re: How to handle a parallel inheritance?

Post by m8f »

Option one: make UW_PickupBase inherit UW_ObjectBase.
Option two: use mixins. Basically, a mixin is a piece of code that you can mix in into other classes.

Not sure about the second question.
User avatar
22alpha22
Posts: 303
Joined: Fri Feb 21, 2014 5:04 pm
Graphics Processor: nVidia with Vulkan support
Location: Montana, USA

Re: How to handle a parallel inheritance?

Post by 22alpha22 »

A player can never carry more than one weapon of each kind.
This is blatantly false or at least it used to be, I don't know if it still is. It at least used to be possible to set a weapon's Inventory.MaxAmount to something greater than 1 and be able to actually have multiple copies of the same weapon in your inventory. I used this in some of my mods before ZScript was even a thing in order to allow sharing weapons in Cooperative games.

EDIT:
Rereading it, I think it is just a poorly worded way of saying while you can multiple copies of a weapon in your inventory, you can only ever select 1 copy (probably the first you picked up) to use. Thus if you had multiple copies but they had different attributes, you would always be using the same copy with the same attributes no matter what.
User avatar
Caligari87
Admin
Posts: 6174
Joined: Thu Feb 26, 2004 3:02 pm
Preferred Pronouns: He/Him
Contact:

Re: How to handle a parallel inheritance?

Post by Caligari87 »

Note that a mixin is basically a copy-paste instruction for the compiler, it just saves you the step of doing it yourself and having duplicated code. Just be aware that the resulting classes, even though they may have identically-named methods and members, would not be part of the same inheritance chain.

You can either do this (same inheritance chain)

Code: Select all

Actor → UW_ObjectBase → UW_PickupBase 
         FunctionA    →  FunctionA
         FunctionB    →  FunctionB
                         FunctionC
Or this (separate inheritance chains)

Code: Select all

Actor → UW_ObjectBase
         MixIn
          FunctionA
          FunctionB

Actor → UW_PickupBase 
         MixIn
          FunctionA
          FunctionB
         FunctionC
TL;DR ZScript has no "parallel" or "shared" inheritance functionality.

8-)
User avatar
Sir Robin
Posts: 537
Joined: Wed Dec 22, 2021 7:02 pm
Graphics Processor: Intel (Modern GZDoom)
Location: Medellin, Colombia

Re: How to handle a parallel inheritance?

Post by Sir Robin »

I think what this means (and tell me if I'm wrong, I'm no professional programmer, just some guy trying to figure this stuff out) is that what I need to do is:

Code: Select all

Actor → UW_ObjectBase
Inventory → UW_PickupBase
Weapon → UW_WeaponBase
Then all of these will return true for is "actor" but not for is UW_ObjectBase
So even if I add the same function to each of them, say GetDescription(), I won't be able to call it universally like this:

Code: Select all

string Description=UW_ObjectBase(ThisObject).GetDescription()
But I'd have to do it the long way, like this:

Code: Select all

string Description
if (ThisObject is "UW_ObjectBase"){Description=UW_ObjectBase(ThisObject).GetDescription()}
if (ThisObject is "UW_PickupBase"){Description=UW_PickupBase(ThisObject).GetDescription()}
if (ThisObject is "UW_WeaponBase"){Description=UW_WeaponBase(ThisObject).GetDescription()}
Am I understanding that correctly? Basically I'd need to add that "translation layer" every time I want to get a UW property or function off of an object.
I suppose I could build a class with static functions like string GetDescription(Actor ThisObject) and use that to pick up data off the UW objects so I don't have to clutter up my code with all those ifs.

Is that the way to do this or is there something better/easier?
User avatar
Caligari87
Admin
Posts: 6174
Joined: Thu Feb 26, 2004 3:02 pm
Preferred Pronouns: He/Him
Contact:

Re: How to handle a parallel inheritance?

Post by Caligari87 »

On the face of it, that seems to be the case, yes. You'd either need to cast the intended type, or use a static function with a translation later.

8-)
User avatar
Sir Robin
Posts: 537
Joined: Wed Dec 22, 2021 7:02 pm
Graphics Processor: Intel (Modern GZDoom)
Location: Medellin, Colombia

Re: How to handle a parallel inheritance?

Post by Sir Robin »

OK, I got it, I can work around that then. Another question - How do I make one mod aware of another?

Say I've got mod1 that defines "class NewActor : Actor"

then in mod2 I've got code like this:

Code: Select all

void MyFunc(Actor a){
	if (a is "NewActor"){
		let n=NewActor(a);
		//work with n
	} else {
		//work with a
	}
}
If mod1 isn't loaded and that class isn't defined, then this script won't even compile. So how to I make code so that it can use a class only if it is defined?
User avatar
Caligari87
Admin
Posts: 6174
Joined: Thu Feb 26, 2004 3:02 pm
Preferred Pronouns: He/Him
Contact:

Re: How to handle a parallel inheritance?

Post by Caligari87 »

One method which seems to be allowed is putting the classname in a variable so it's evaluated at run-time instead of compile-time. See this wiki page: ZScript_classes: Cross-Mod_Support

Code: Select all

// Checked at compile time. This will error upon loading if the class is missing.

class<Actor> cls = "MissingNameOfClass";

Code: Select all

// Checked at run time instead of compile time. 'cls' will just be null if the actor class isn't defined.

string classname = "MissingNameOfClass";
class<Actor> cls = classname;
I personally don't like this because I feel like it's a workaround or hack, rather than an intentional feature. That said, it works, and is fairly simple to understand and implement.

The other way is using the [wiki]Service[/wiki] system. Essentially this is like a "bulletin board" where one mod can put out a notice with some information, and another mod can retrieve that information without necessarily needing to be aware of how it got there. I have not used this myself (though I did implement a simple version in my own mod at one point, before this feature was added) and it seems kind of complicated to set up, but is probably the most flexible and future-proof option. Plus it's an intentional feature, not a workaround.

8-)
User avatar
phantombeta
Posts: 2089
Joined: Thu May 02, 2013 1:27 am
Operating System Version (Optional): Windows 10
Graphics Processor: nVidia with Vulkan support
Location: Brazil

Re: How to handle a parallel inheritance?

Post by phantombeta »

Caligari87 wrote:One method which seems to be allowed is putting the classname in a variable so it's evaluated at run-time instead of compile-time. See this wiki page: ZScript_classes: Cross-Mod_Support
[...]
I personally don't like this because I feel like it's a workaround or hack, rather than an intentional feature. That said, it works, and is fairly simple to understand and implement.
I think it's safe not to consider it a hack. It is intentional, and it's only a workaround here because it doesn't let you do it directly.
I believe the reason why it errors out is for user friendliness and so mistakes are easier to spot... But it gets in the way when you do mean to do that.
Post Reply

Return to “Scripting”