Classes and QuakeC
==================
By Marco Hladik
Last updated: 8th of August 2018

Introduction
============

Object Oriented Programming makes a lot of sense for game-logic.
Especially in an environment like QuakeC, where the language already
attempts an introduction of datatypes (in this case `entity`) that
are meant to represent "objects".
However, the entity type has its downsides once you attempt to 
scale the codebase.

The entity type in QuakeC uses something called `fields` to give
them their attributes. 

	self.health = 100;

Sets the field `.health` of entity `self` to 100. .health is just one 
of many fields used in the stock QuakeC codebase.
There are a set of fields that are a requirement to have, like .origin
and .angles, as they're networked by default so that the engine knows
how to render said entity. Some other fields like .weapon and .items
as well as .armor are specific to Quake 1 only.

One thing that always annoyed me about regular entities in QuakeC is that
every field was globally declared for _every_ other entity in the game.
So you end up with thousands of fields (in the case of Xonotic) that
are being allocated for the entities.
Thousands of references, most of the time not going anywhere.
This leads to some programmers committing something titled `field reuse`.
Suddenly you'll see people use one field (like .health) to store info
about something completely unrelated to what the name implies.

Each field costs each entity at least 4 bytes of memory.
Vectors are worse, because they're 3 floats bundled together.
So that's at least 12 bytes on every entity spawned - even when unused.

Anyway, classes and FTEQCC solve this problem somewhat.
Classes are, technically, by extension, entities.
They inherit all the global, standard fields any other entity gets.
So your object of class "CFunBalloon" will have all of the globally
defined fields .origin, .angles as well as .modelindex available.
Classes can also be referenced as entities and manipulated:

	CFunBallon tommy = spawn( CFunBallon );
	entity tommyreference = (entity)tommy;
	setorigin( tommyreference, '0 0 0' ); // Perfectly valid

This also works in reverse. If you know that the entity type being returned
is of a specific class, you can cast it to said class and manipulate
its exclusive fields. The compiler is fine with it.

Basic Declaration
=================

Here it is:

	class CMyClass { };
	
This officially declares a class, titled CMyClass. It has no attributes, 
other than the ones it inherits from all entities (aka all fields). 
It also has no methods associated with it.
You don't have to call it C**** anything. 
You can also call it Bob or Miguel for all the compiler cares.
That's just how most programmers, coming from other languages would declare it.

Attributes/Members/Fields
=========================

Every language calls them differently. I don't think there's an official
preference on how to call it in QuakeC, so I'll just call them attributes.

Now since we've got our CMyClass, we want to add an attribute to it.
One that no other class or entity can use.

	class CMyClass
	{
		int myattribute;
	};

Some languages have public/private declarations for attributes and methods.
QuakeC doesn't care. Let's move on.

Spawning a class
================

A class cannot just be defined and then manipulated.
Just like an entity reference, it has to be spawned first.
spawn() will take care of that.

	CMyClass tom = spawn( CMyClass );

spawn() for standard entity types does not take a parameter, however
it's a requirement here. The spawn() will also tell it to
launch the constructor. Which we'll go into next.

Map entities can also directly spawn and be initialized as a class instead
of a function.

Constructor
===========

The constructor needs to be defined first inside the class description:

	class CMyClass
	{
		int myattribute;
		
		void() CMyClass; // The constructor declaration
	};

Upon spawning the class with spawn(), it'll look for the member method
titled after said class.

	// The constructor definition
	void CMyClass :: CMyClass ( void )
	{
		if ( !myattribute )
			myattribute = 100;
	}

Inside this example constructor, it'll define myattribute to be 100 when
created via spawn() and myattribute has no value.

It's also possible to modify the attributes inside of an object
with the spawn() intrinsic before the constructor is called:

	CMyClass tom = spawn( CMyClass, myattribute: 255, model: "Tom" );

Will set the myattribute to 255. Which will prevent the constructor
from re-defining it to 100 due to the `if (!myattribute)` in the constructor.

It'll also set the `model` field it inherits from entities to "Tom". 
Just to give you an example of what defining multiple attributes looks like
when using spawn().

Methods
=======

Let's create a method titled 'Destruct'. This will teach more than one thing
in particular.

Declaration (shove that into your class description somewhere):
	virtual void() Destruct;

Definition:
	void CMyClass :: Destruct ( void )
	{
		remove( this );
	}
	
`this` effectively acts like `self`, when referring to which object is calling
its member function. 

This also changes the way you can call member functions:
	
	entity oldself = self;
	self = other_entity;
	self.FooBar();
	self = oldself;
	
Can now be replaced comfortably with:

	myobject.FooBar();

Because the compiler knows that if FooBar() is a method of a class that you'll
be wanting to execute it on `myobject` and not whatever `self` is set to.
In Stock QuakeC you always have to beware what `self` is set to when calling
entity functions. Not here.

Conversion
==========

It is indeed possible to convert an already spawned, existing entity.
This means going from entity to an object of a class.
For example, in Server-Side QuakeC there's the function PutClientInServer.
If you were to put the following line in there:

	spawnfunc_CMyClass();

It would convert the already spawned player entity into an object of the class
CMyClass.

Inheritance
===========

One of the biggest pros of classes in my opinion.
We all know that CMyClass has already inherited all the standard `entity` type
fields. However, FTEQCC supports single inheritance.

	class CCoolestClass : CMyClass
	{
		int newattribute;
		void() CCoolestClass;
	};

	void CCoolestClass :: CCoolestClass ( void )
	{
		myattribute = 666;
		newattribute = 123;
		Destruct();
	}

So now CCoolestClass inherited all of CMyClass and the basic `entity` type.
This allows an unprecedented amount of complexity conveyed in very few
pieces of code. 

Remember that if you override a method of a class you inherit, that you have to
declare that as such inside the class definition.

Problems/Workarounds
====================

As you noticed in the Chapter for Methods, we can set fields without
specifically notating `this.` before setting `myattribute`.
This results in functions like e.g. find() to complain if you were to call
it like this inside a member method:

	blargh = find( world, netname, "Tom" ); // error

It will tell you about 'netname' not being defined. The compiler thinks that
netname is a member of your class whose value you want to pass as a parameter
and not a type of field/attribute reference.

Adding a :: before netname will tell the compiler that you're
looking for a field/attribute.

	blargh = find( world, ::netname, "Tom" ); // valid

