Get field by name+type, regardless of class

Remember, just because you request it, that doesn't mean you'll get it.

Moderator: GZDoom Developers

argv
Posts: 184
Joined: Tue Aug 30, 2016 4:47 pm

Get field by name+type, regardless of class

Post by argv »

Suppose I have an RPG mod, in which all characters (player pawns and monsters) have a set of stats:

Code: Select all

struct CharacterStats play {
	…
}

class MyRPGPlayerPawn : PlayerPawn abstract {
	CharacterStats stats;
	…
}

class MyRPGMonster : Actor abstract {
	CharacterStats stats;
	…
}
Now, any code that needs to examine a character's stats can do so by examining the “stats” field. But, given an arbitrary actor, how do we find that field? Class Actor doesn't have a “stats” field. Class MyRPGMonster does, but what if the actor is a MyRPGPlayerPawn instead, or vice versa? What if yet another class is introduced that has its own stats, yet is neither a player pawn nor a monster?

Since we're not getting multiple inheritance (even of field declarations), the only way I know of to solve this problem is with this slow, abstraction-breaking pattern:

Code: Select all

struct CharacterStats play {
	int Strength, Perception, Endurance, Charisma, Intelligence, Agility, Luck;
	
	void Copy(CharacterStats from) {
		Strength = from.Strength;
		Perception = from.Perception;
		Endurance = from.Endurance;
		Charisma = from.Charisma;
		Intelligence = from.Intelligence;
		Agility = from.Agility;
		Luck = from.Luck;
	}
	
	static bool Get(Actor actor, in out CharacterStats stats) {
		if (actor is "MyRPGPlayerPawn") {
			stats.Copy(MyRPGPlayerPawn(actor).stats);
			return true;
		}
		else if (actor is "MyRPGMonster") {
			stats.Copy(MyRPGMonster(actor).stats);
			return true;
		}
		else
			return false;
	}
	
	static bool Set(Actor actor, CharacterStats stats) {
		if (actor is "MyRPGPlayerPawn") {
			MyRPGPlayerPawn(actor).stats.Copy(stats);
			return true;
		}
		else if (actor is "MyRPGMonster") {
			MyRPGMonster(actor).stats.Copy(stats);
			return true;
		}
		else
			return false;
	}
}
Instead, how about structural types or reflective/dynamic field access, so we can access any field “CharacterStats stats” on any arbitrary object, as long as it has one?
User avatar
Zhs2
Posts: 1269
Joined: Fri Nov 07, 2008 3:29 pm
Graphics Processor: ATI/AMD with Vulkan/Metal Support
Location: Maryland, USA, but probably also in someone's mod somewhere
Contact:

Re: Get field by name+type, regardless of class

Post by Zhs2 »

The universal method to handing off any kind of variable storage to any actor you desire would be through an item. Once you have a method in place for giving a variable holding item to the actors in question (perhaps through a WorldThingSpawned override in an EventHandler class?), you can store a reference to that item on the affected actor via FindInventory and the appropriate casting, then you can manipulate its variables as you wish via the reference.
argv
Posts: 184
Joined: Tue Aug 30, 2016 4:47 pm

Re: Get field by name+type, regardless of class

Post by argv »

Indeed, but that's yet another object for the garbage collector to track, and it won't work if the actor in question is an inventory item.

Also, access to inventory is slower than access to instance fields, and storing information there has the risk of the item being accidentally removed.
User avatar
Graf Zahl
Lead GZDoom+Raze Developer
Lead GZDoom+Raze Developer
Posts: 49056
Joined: Sat Jul 19, 2003 10:19 am
Location: Germany

Re: Get field by name+type, regardless of class

Post by Graf Zahl »

Beware: Although doing named access to fields is not impossible, the necessary type checks are a very different matter
Post Reply

Return to “Feature Suggestions [GZDoom]”