Class Inheritance: Difference between revisions

From Bohemia Interactive Community
Jump to navigation Jump to search
m (changed children to child (singular))
(Almost complete rewrite to improve grammatical phrasing, spelling, and legibility, as well as to fix incorrectly written examples and provide further elaboration.)
Line 2: Line 2:
Inheriting classes within the config is a concept that can easily go wrong.
Inheriting classes within the config is a concept that can easily go wrong.
The purpose of this document is to clarify the cause of some common errors and contains instructions on how to resolve these mistakes.
The purpose of this document is to clarify the cause of some common errors and contains instructions on how to resolve these mistakes.


== Terms ==
== Terms ==


* A '''config''' is a config.cpp or config.bin file that is loaded during the game start. It is does not refer to a [[Model Config]].
* A '''config''' refers to a config.cpp or config.bin file that is loaded during the game start. It does ''not'' refer to a [[Model Config]].
* The '''bin\config.bin''' is the father of all other configs. It forms the first state of the master config.bin and consists of the root classes.
* The '''bin\config.bin''' is the father of all other configs. It forms the first state of the master config.bin and consists of the base game's root classes.
* The '''master''' config is the in-game one and built from the merging of ''all configs'' to the bin\config.bin. This includes both the base game addons as well as user addons. It can be viewed through the Splendid Config
* The '''master''' config is built from the merging of ''all'' configs to the bin\config.bin, and it is what is seen through the Splendid Config Viewer. This includes both the base game addons as well as user-made addons.
Viewer.
* '''Child configs''' are the configs that are merged into the master config.bin during game load. The order in which they are added is defined by the requiredAddons array within each CfgPatches (see [[#Addon_loading_order|addon loading order]]).
* '''child configs''' are merged into the master config.bin during game load. The order in which they get added is defined by the requiredAddons array within each CfgPatches (see [[#Addon_loading_order|addon loading order]]).
*CfgPatches is a necessary prerequisite for '''all''' child configs so that its addon name and required addons (if any) are known.
* Missions and campaigns are not configs, as the pbo they are in may or may not contain a config. This makes them mission pbos or mission addons respectively.


**CfgPatches is a necessary prerequisite for '''all''' child configs so that it's addon name is known and required addons (if any)


* be aware that missions and campaigns are not configs. The pbo they are in, may or may not contain a config. Thus making them mission pbos or mission addons respectively.
== Basic Config Concepts ==


The config is a hierarchical structure based on classes that provide almost all information necessary for the game. Objects, their behavior, user interface elements, and even which functions to run on game start are defined through the config.


== Basic config concepts ==
Classes can contain either child classes (see below) or properties. Properties work similarly to script variables, they have a name and are assigned a value.
However, unlike script variables, properties can only have number values, string values, or (one or multidimensional) arrays that are made up of number or string values.


The config is a hierarchical structure based on classes that provides almost all information necessary for the game.
Objects, their behaviour, user interface elements and even which functions to run on game start are defined through the config.


Classes can contain either child classes (see below) or contain properties. Properties work similar to script variables, they have a name and a value.
=== Parent and Child Classes ===
However unlike script variables properties can only have either number or string values, or (one- or multidimensional) arrays of number or string values.


=== Parent and child classes ===
Due to the hierarchical nature of the config, classes can have '''parent''', '''child''' and '''sibling''' classes.
 
Due to the hierarchical nature of the config, classes can have '''parent''', '''child''' and '''sibling''' classes:


<syntaxhighlight lang="cpp">
<syntaxhighlight lang="cpp">
Line 46: Line 42:
};
};
</syntaxhighlight>
</syntaxhighlight>
In this example, the classes "Esau" and "Jacob" are '''child''' classes of "Isaac". This makes them '''sibling''' classes.




In this example, the parent classes Esau and Jacob are child classes of Isaac. They are siblings.
In a more practical example, "arifle_MX_F" and "arifle_Katiba_F" are both '''child''' classes of CfgWeapons, and as a result, they too are '''sibling''' classes.
<syntaxhighlight lang="cpp">
class CfgWeapons
{
class arifle_MX_F
{
// ...
};
class arifle_Katiba_F
{
// ...
};
};
</syntaxhighlight>
 


=== Inheritance ===
=== Basic Inheritance ===


A class can inherit properties from sibling classes by defining it as a base class.
A class can inherit properties from sibling classes by defining it as a base class. All properties of the inherited base class will also exist within your class and, unless you overwrite them, they will have the same values as the base class. This is extremely useful for quickly writing sibling classes that share properties, or to build a class on top of another class that has the same properties with only minor value changes.
This means that all properties of that base class will also exist within your class and, unless you overwrite them, will have the same values as in the base class.
This is extremly useful for quickly writing sibling classes that share properties, or to build a class on top of another class that has the same properties with only minor value changes.


Taking the example from above we can either create a common ''ChildMaleBase'' base class:


Taking the example from above we can create a common "ChildMaleBase" base class.
<syntaxhighlight lang="cpp">
<syntaxhighlight lang="cpp">
class Isaac
class Isaac
Line 65: Line 74:
gender = "male";
gender = "male";
};
};
class Esau : ChildMaleBase
class Esau: ChildMaleBase
{
{
firstborn = 1;
firstborn = 1;
// ...
// ...
};
};
class Jacob : ChildMaleBase
class Jacob: ChildMaleBase
{
{
firstborn = 0;
firstborn = 0;
Line 77: Line 86:
};
};
</syntaxhighlight>
</syntaxhighlight>
In this example, both "Esau" and "Jacob" will inherit the gender property from "ChildMaleBase".




Or we can use ''Esau'' as a base class for ''Jacob'' and overwrite the ''firstborn'' property:
Alternatively, we can use "Esau" as a base class for "Jacob" and overwrite the "firstborn" property:
 
<syntaxhighlight lang="cpp">
<syntaxhighlight lang="cpp">
class Isaac
class Isaac
Line 86: Line 95:
class Esau
class Esau
{
{
gender = "male";
gender = "Male";
firstborn = 1;
firstborn = 1;
// ...
// ...
};
};
class Jacob : Esau
class Jacob: Esau
{
{
firstborn = 0;
firstborn = 0;
// ...
// ...
};
};
class Mary : Esau
class Mary: Esau
{
{
gender = "Female"; // firstborn too
gender = "Female";
// ...
};
};
};
};
</syntaxhighlight>
</syntaxhighlight>
In the above example, while "Mary" overwrites the gender property, the class would still inherit the firstborn value of 1 from sibling class "Esau".


Either method is stored, as written, in the master config, and either one achieves the same result for any other classes that accesses Isaac.




== External base classes ==
Either method is stored, as written, in the master config, and either one achieves the same result for any other classes that access "Isaac".


{{Feature|important|The concept of external base classes only applies to addon configs. For mission configs the [[import]] keyword fulfills a similar purpose.}}
== External Base Classes ==
Especially when writing the config for a new vehicle or changing the config of an existing vehicle, you will sooner or later come on contact with external base classes.
External base classes are simply base classes that you did ''not define within your own config'' but were defined either by the base game or another addon.


It's a simple concept to understand but not as easy to implement correctly.
{{Feature|important|The concept of external base classes only applies to addon configs. For mission configs, the [[import]] keyword fulfills a similar purpose.}}


When using an external base class the first thing you have to do is declare it in what is termed a 'template' or 'skeleton'. These do NOT affect those classes, they merely tell the compiler how they are constructed.
External base classes are essentially base classes that are first defined ''outside'' of your config, either by the base game or another addon. It's a simple concept to understand but not so simple to implement correctly.
Stated wrongly, the game engine ill throw a fit if it discovers what-you-say, is not-the-truth. It does this as it is progressively builds the master config.
 
Secondly, IF the class(es) you declare are not yet 'discovered' by the engine, it will build empty classes waiting to be filled later, based on what you say here. Thus, it is important to get the inheritance (if any) right!.
 
When using an external base class the first thing you have to do is declare it in what is termed a "template" or "skeleton". These do NOT affect those classes, they merely tell the compiler how they are constructed. If the classes you declare are not yet discovered by the engine, it will build empty classes waiting to be filled later, based on what inheritance you've written. As a result, it is important to get the inheritance (if any) right!


<syntaxhighlight lang="cpp">
<syntaxhighlight lang="cpp">
class externalBaseClass; // Declare an external base class "skeleton"
class myClass: externalBaseClass // Define that your class inherits from it
{
// ... // Start using it
};
</syntaxhighlight>


// the external 'skeleton'
 
class externalBaseClass; // declare an external base class
An example of both inheritance and the use of external base classes could be the addition of new weapon textures via "hiddenSelections".
//
<syntaxhighlight lang="cpp">
class myClass: externalBaseClass // define that you inherit from it
class CfgWeapons
{
{
// ... // start using it
class arifle_MX_F; // Declare an external base class "skeleton"
class arifle_MX_Black_F: arifle_MX_F // Define that your class inherits from the external base class
{
hiddenSelections[] = {"camo1", "camo2"};
hiddenSelectionsTextures[] = {"\A3\Weapons_F_EPB\Rifles\MX_Black\Data\XMX_Base_Black_co.paa","\A3\Weapons_F_EPB\Rifles\MX_Black\Data\XMX_short_Black_co.paa"};
// ...
};
class arifle_MX_khk_F: arifle_MX_Black_F
{
hiddenSelectionsTextures[] = {"\A3\Weapons_F_Exp\Rifles\MX\Data\XMX_Base_khk_co.paa","\A3\Weapons_F_Exp\Rifles\MX\Data\XMX_Short_khk_co.paa"};
// ...
};
};
};
</syntaxhighlight>
</syntaxhighlight>
"CfgWeapons" serves as the parent class, while "arifle_MX_F", "arifle_MX_Black_F", and "arifle_MX_khk_F" serve as sibling classes. In this instance, the "arifle_MX_Black_F" is inheriting all of its values from the "arifle_MX_F" external base class skeleton, but it changes the value for the "hiddenSelections" and "hiddenSelectionsTextures" arrays. When defining "arifle_MX_khk_F" later, instead of changing the "hiddenSelections" array value again, it inherits the changed value from its sibling class, "arifle_MX_Black_F", and changes the necessary values in the "hiddenSelectionsTextures" array for the new textures to appear.


It is not necessary to declare the base class'es inheritance tree (if any) IF you have the correct requiredaddons[]=.
=== Example two ===


Now what if you want to access a child class of the base class? At this point, you are accessing the contents of the base class, and thus you need to declare this class s being part of that base class eg a child and it's parent.
It is not necessary to declare the base class' inheritance tree (if any) ''if'' you have the correct inherited class' addon in the "requiredAddons" array.




=== External Base Child Classes ===
In the event that you want to access a child class of a base class, you must declare the child class as a part of the base class. In order to open the base class, however, you must declare what it inherits from as well. Opening the base class to declare the child class without defining what the base class inherits from will declare the base class as if it is the first time it is being defined.


<syntaxhighlight lang="cpp">
<syntaxhighlight lang="cpp">
//// the 'template'
class externalRootClass; // Declare an external base class "skeleton"
class externalRootClass
class externalBaseClass: externalRootClass // Define that the external parent base class inherits from the external base class
{
{
class externalBaseClass;
class externalChildClass; // Define the external child base class "skeleton"
};
};
///////////
 
class myClass: externalRootClass
class myClass: externalBaseClass // Define that your class inherits from the external parent base class
{
{
class externalChildClass: externalChildClass // import ALL the values from the original
class myChildClass: externalChildClass // Define that your child class inherits from the external child base class
{
{
// ... add, or make, changes
// ... add or make changes
};
};
// ...
// ...
Line 154: Line 180:




=== implied child classes ===
=== Implied Child Classes ===
 
Once an external child class is defined somewhere in the inheritance tree, you will not need to redefine it later, as it is implied by the game engine that that child class is the class you are looking for.
<syntaxhighlight lang="cpp">
<syntaxhighlight lang="cpp">
class A
class A
{
{
class B
class B
{
{
/* ...whatever */
// Whatever
};
};
};
};


class C : A
class C: A
{
{
class D
class D
{
{
// whatever
// Whatever
};
};
};
};


class E : C
class E: C
{
{
class D : D // fairly standard
class D: D // Fairly standard
{
{
// change things
// Change things
};
};
class B : B // fairly strange!
class B: B // Fairly strange!
{
{
// change things
// Change things
};
};
};
};
</syntaxhighlight>
</syntaxhighlight>
The reason ''why'' you can access, and use, "B" (which is not a direct child of "E") is due to inheritance. "B" does indeed become a child of "E"!




*the reason *why* you can access, and use, B (which is not a direct child of E) is due to inheritance, it does indeed become a child of E!
Note that "A", "B", "C", and "D" could be more simply shown as a skeleton tree defined as follows:
*Note that A B C D could easily be simply a skeleton tree defined as follows:
<syntaxhighlight lang="cpp">
<syntaxhighlight lang="cpp">
//////template
class A
class A
{
{
Line 197: Line 221:
};
};


class C : A
class C: A
{
{
class D;
class D;
};
};
//// end template
</syntaxhighlight>
</syntaxhighlight>




== Addon loading order ==
== Addon Loading Order ==
When you are using external base classes it is extremely important to define what addons your addon depends on, or in other words, which external base classes need to be already loaded when your config gets loaded.


When you are using external base classes it is extremly important to define what addons your addon depends on, or in other words, which external base classes need to be already loaded when your config gets loaded.
{{Feature|important|Addons of externally defined base classes should always be defined in the load order to ensure your config is applied correctly.}}


{{Feature|important|The loading order always needs to be defined!}}
Defining which addons are required by your config is easily done through the ''"CfgPatches"'' class:
 
Defining which addons are required by your config is easily done through the ''CfgPatches'':
<syntaxhighlight lang="cpp">
<syntaxhighlight lang="cpp">
class CfgPatches
class CfgPatches
Line 218: Line 240:
{
{
// ...
// ...
requiredAddons[] = { "ExternalAddonA", "ExternalAddonB", ... };
requiredAddons[] = {"ExternalAddonA", "ExternalAddonB", ...};
// ...
// ...
};
};
Line 224: Line 246:
</syntaxhighlight>
</syntaxhighlight>


This ensures that whatever changes you made or whatever classes based on some other classes you defined are applied on top of the external addons child config.
Defining the required addons ensures that whatever changes you made, or whatever classes you defined based on external classes, are defined on top of the external addons' config.
Without this there is no guarantee that your config gets applied correctly.
Without defining the required addons and load order, there is no guarantee that your config gets applied correctly.
{{Feature|Informative|{{hl|A3_Data_F_Oldman_Loadorder}} is the last vanilla CfgPatches entry in {{arma3}} 2.00, so you can put this to overwrite some vanilla configs.}}
 
{{Feature|Informative|{{hl|A3_Data_F_Oldman_Loadorder}} is the last vanilla CfgPatches entry in {{arma3}} as of 2.12, so you can use this to overwrite some vanilla configs.}}


=== empty ===


An often misunderstood is the empty{} syntax.
== Empty ==


class thingy{}; this removes everything, including embedded classes ''within the scope'' of the parent class it is found in.
The <syntaxhighlight lang="cpp" inline>class Empty{};</syntaxhighlight> syntax can be easily misunderstood for defining an external base class. Using the empty syntax removes everything inside of the class (including embedded classes ''within the scope'' of the parent class it is found in, defining it as if it was being defined for the very first time. It cannot be used for any class that has inheritance, because that is simply seen as a skeleton tree.
* it cannot be used for any class that has inheritance, because that is simply seen as a skeleton tree.
<syntaxhighlight lang="cpp">
* it is NOT the same thing as class thingy;
class MyAddon; // Defines a skeleton class
</syntaxhighlight>


<syntaxhighlight lang="cpp">
class MyAddon{}; // Removes everything inside the class
</syntaxhighlight>


== delete ==


Within configs the <syntaxhighlight lang="cpp" inline>delete classname</syntaxhighlight> keyword is available. It can be used to delete already existing classes. '''However, classes from which other classes derive cannot be deleted unless the child classes are deleted first.'''
== Delete ==


Within configs, the <syntaxhighlight lang="cpp" inline>delete Classname;</syntaxhighlight> keyword is available. It can be used to delete already existing classes.
{{Feature|important|Classes from which other classes derive cannot be deleted unless the child classes are deleted first.}}
<syntaxhighlight lang="cpp">
<syntaxhighlight lang="cpp">
class Intel
class Intel
Line 250: Line 277:
class Attributes
class Attributes
{
{
delete Fog; // removes Fog attribute from Eden Editor
delete Fog; // removes Fog attribute from Eden Editor
};
};
};
};
Line 263: Line 290:
{
{
class Fog;
class Fog;
class TimeMultiplier : Fog
class TimeMultiplier: Fog
{
{
displayName = "Time Multiplier";
displayName = "Time Multiplier";
Line 269: Line 296:
// ...
// ...
};
};
delete Fog;//Will not work since a child of Fog still exists.
delete Fog; // Will not work since a child of Fog still exists.
};
};
};
};
</syntaxhighlight>
</syntaxhighlight>


{{GameCategory|arma1|Addon Configuration}}
{{GameCategory|arma1|Addon Configuration}}

Revision as of 11:00, 25 May 2023

Inheriting classes within the config is a concept that can easily go wrong. The purpose of this document is to clarify the cause of some common errors and contains instructions on how to resolve these mistakes.

Terms

  • A config refers to a config.cpp or config.bin file that is loaded during the game start. It does not refer to a Model Config.
  • The bin\config.bin is the father of all other configs. It forms the first state of the master config.bin and consists of the base game's root classes.
  • The master config is built from the merging of all configs to the bin\config.bin, and it is what is seen through the Splendid Config Viewer. This includes both the base game addons as well as user-made addons.
  • Child configs are the configs that are merged into the master config.bin during game load. The order in which they are added is defined by the requiredAddons array within each CfgPatches (see addon loading order).
  • CfgPatches is a necessary prerequisite for all child configs so that its addon name and required addons (if any) are known.
  • Missions and campaigns are not configs, as the pbo they are in may or may not contain a config. This makes them mission pbos or mission addons respectively.


Basic Config Concepts

The config is a hierarchical structure based on classes that provide almost all information necessary for the game. Objects, their behavior, user interface elements, and even which functions to run on game start are defined through the config.

Classes can contain either child classes (see below) or properties. Properties work similarly to script variables, they have a name and are assigned a value. However, unlike script variables, properties can only have number values, string values, or (one or multidimensional) arrays that are made up of number or string values.


Parent and Child Classes

Due to the hierarchical nature of the config, classes can have parent, child and sibling classes.

class Isaac
{
	class Esau
	{
		gender = "male";
		firstborn = 1;
		// ...
	};
	class Jacob
	{
		gender = "male";
		firstborn = 0;
		// ...
	};
};

In this example, the classes "Esau" and "Jacob" are child classes of "Isaac". This makes them sibling classes.


In a more practical example, "arifle_MX_F" and "arifle_Katiba_F" are both child classes of CfgWeapons, and as a result, they too are sibling classes.

class CfgWeapons
{
	class arifle_MX_F
	{
		// ...
	};
	class arifle_Katiba_F
	{
		// ...
	};
};


Basic Inheritance

A class can inherit properties from sibling classes by defining it as a base class. All properties of the inherited base class will also exist within your class and, unless you overwrite them, they will have the same values as the base class. This is extremely useful for quickly writing sibling classes that share properties, or to build a class on top of another class that has the same properties with only minor value changes.


Taking the example from above we can create a common "ChildMaleBase" base class.

class Isaac
{
	class ChildMaleBase
	{
		gender = "male";
	};
	class Esau: ChildMaleBase
	{
		firstborn = 1;
		// ...
	};
	class Jacob: ChildMaleBase
	{
		firstborn = 0;
		// ...
	};
};

In this example, both "Esau" and "Jacob" will inherit the gender property from "ChildMaleBase".


Alternatively, we can use "Esau" as a base class for "Jacob" and overwrite the "firstborn" property:

class Isaac
{
	class Esau
	{
		gender = "Male";
		firstborn = 1;
		// ...
	};
	class Jacob: Esau
	{
		firstborn = 0;
		// ...
	};
	class Mary: Esau
	{
		gender = "Female";
		// ...
	};
};

In the above example, while "Mary" overwrites the gender property, the class would still inherit the firstborn value of 1 from sibling class "Esau".


Either method is stored, as written, in the master config, and either one achieves the same result for any other classes that access "Isaac".

External Base Classes

The concept of external base classes only applies to addon configs. For mission configs, the import keyword fulfills a similar purpose.

External base classes are essentially base classes that are first defined outside of your config, either by the base game or another addon. It's a simple concept to understand but not so simple to implement correctly.


When using an external base class the first thing you have to do is declare it in what is termed a "template" or "skeleton". These do NOT affect those classes, they merely tell the compiler how they are constructed. If the classes you declare are not yet discovered by the engine, it will build empty classes waiting to be filled later, based on what inheritance you've written. As a result, it is important to get the inheritance (if any) right!

class externalBaseClass;			// Declare an external base class "skeleton"
class myClass: externalBaseClass	// Define that your class inherits from it
{
	// ...							// Start using it
};


An example of both inheritance and the use of external base classes could be the addition of new weapon textures via "hiddenSelections".

class CfgWeapons
{
	class arifle_MX_F;						// Declare an external base class "skeleton"
	class arifle_MX_Black_F: arifle_MX_F	// Define that your class inherits from the external base class
	{
		hiddenSelections[] = {"camo1", "camo2"};
		hiddenSelectionsTextures[] = {"\A3\Weapons_F_EPB\Rifles\MX_Black\Data\XMX_Base_Black_co.paa","\A3\Weapons_F_EPB\Rifles\MX_Black\Data\XMX_short_Black_co.paa"};
		// ...
	};
	class arifle_MX_khk_F: arifle_MX_Black_F
	{
		hiddenSelectionsTextures[] = {"\A3\Weapons_F_Exp\Rifles\MX\Data\XMX_Base_khk_co.paa","\A3\Weapons_F_Exp\Rifles\MX\Data\XMX_Short_khk_co.paa"};
		// ...
	};
};

"CfgWeapons" serves as the parent class, while "arifle_MX_F", "arifle_MX_Black_F", and "arifle_MX_khk_F" serve as sibling classes. In this instance, the "arifle_MX_Black_F" is inheriting all of its values from the "arifle_MX_F" external base class skeleton, but it changes the value for the "hiddenSelections" and "hiddenSelectionsTextures" arrays. When defining "arifle_MX_khk_F" later, instead of changing the "hiddenSelections" array value again, it inherits the changed value from its sibling class, "arifle_MX_Black_F", and changes the necessary values in the "hiddenSelectionsTextures" array for the new textures to appear.


It is not necessary to declare the base class' inheritance tree (if any) if you have the correct inherited class' addon in the "requiredAddons" array.


External Base Child Classes

In the event that you want to access a child class of a base class, you must declare the child class as a part of the base class. In order to open the base class, however, you must declare what it inherits from as well. Opening the base class to declare the child class without defining what the base class inherits from will declare the base class as if it is the first time it is being defined.

class externalRootClass;						// Declare an external base class "skeleton"
class externalBaseClass: externalRootClass		// Define that the external parent base class inherits from the external base class
{
	class externalChildClass;					// Define the external child base class "skeleton"
};

class myClass: externalBaseClass				// Define that your class inherits from the external parent base class
{
	class myChildClass: externalChildClass		// Define that your child class inherits from the external child base class
	{
		// ... add or make changes
	};
	// ...
};


Implied Child Classes

Once an external child class is defined somewhere in the inheritance tree, you will not need to redefine it later, as it is implied by the game engine that that child class is the class you are looking for.

class A
{
	class B
	{
		// Whatever
	};
};

class C: A
{
	class D
	{
		// Whatever
	};
};

class E: C
{
	class D: D	// Fairly standard
	{
		// Change things
	};
	class B: B	// Fairly strange!
	{
		// Change things
	};
};

The reason why you can access, and use, "B" (which is not a direct child of "E") is due to inheritance. "B" does indeed become a child of "E"!


Note that "A", "B", "C", and "D" could be more simply shown as a skeleton tree defined as follows:

class A
{
	class B;
};

class C: A
{
	class D;
};


Addon Loading Order

When you are using external base classes it is extremely important to define what addons your addon depends on, or in other words, which external base classes need to be already loaded when your config gets loaded.

Addons of externally defined base classes should always be defined in the load order to ensure your config is applied correctly.

Defining which addons are required by your config is easily done through the "CfgPatches" class:

class CfgPatches
{
	class MyAddon
	{
		// ...
		requiredAddons[] = {"ExternalAddonA", "ExternalAddonB", ...};
		// ...
	};
};

Defining the required addons ensures that whatever changes you made, or whatever classes you defined based on external classes, are defined on top of the external addons' config. Without defining the required addons and load order, there is no guarantee that your config gets applied correctly.

A3_Data_F_Oldman_Loadorder is the last vanilla CfgPatches entry in Arma 3 as of 2.12, so you can use this to overwrite some vanilla configs.


Empty

The class Empty{}; syntax can be easily misunderstood for defining an external base class. Using the empty syntax removes everything inside of the class (including embedded classes within the scope of the parent class it is found in, defining it as if it was being defined for the very first time. It cannot be used for any class that has inheritance, because that is simply seen as a skeleton tree.

class MyAddon;		// Defines a skeleton class
class MyAddon{};	// Removes everything inside the class


Delete

Within configs, the delete Classname; keyword is available. It can be used to delete already existing classes.

Classes from which other classes derive cannot be deleted unless the child classes are deleted first.
class Intel
{
	class AttributeCategories
	{
		class Date
		{
			class Attributes
			{
				delete Fog;	// removes Fog attribute from Eden Editor
			};
		};
	};
};
class Intel 
{
	class Attributes
	{
		class Fog;
		class TimeMultiplier: Fog
		{
			displayName = "Time Multiplier";
			tooltip = "Set the time multiplier";
			// ...
		};
		delete Fog;	// Will not work since a child of Fog still exists.
	};
};