Adding a class

This is a guide for adding a new major class to the SotE simulation. If you just quickly want a class or struct to throw some data and functions in, no need to do all this. This is for full-on-classes with all the bells and whistles. As an example we'll add a Province class, which is a grouping of Tiles with further functionality.

The first thing to consider is its smart pointer/ID type, which is based on how many of this new class you're going to have simultaneously.

It is possible to correct this later on. If you need more than fits in a uint32_t, or something even weirder, contact Redbeard, he'll figure something out for you. If Redbeard is no longer available to help, contact his successor. If you are his successor, good luck. In this example, we'll be going with uint16_t as ID type.

Then, create some files for your class, you'll need a header and a main source file. We'll call our files province.hxx and province.cxx.

Now, create some skeleton code for the header, it should look like this:
 * 1) ifndef PROVINCE_HXX
 * 2) define PROVINCE_HXX


 * 1) include "libsote.hxx"

class Province : public SGroup {	SCRIPT_START(Province); public: Province(std::vector& tiles) : SGroup(tiles) {}

SCRIPT_END(Province); };


 * 1) endif // PROVINCE_HXX

Let's break this down a bit, shall we? The first two lines and the last line form what is called a header guard, which prevents the file from being processed multiple times.

The #include directive includes libsote.hxx, which contains the declarations of the structural code everything is build on, it also includes a good deal of the C++ standard library, so that's not needed everywhere. Later on you might also want to include tile.hxx here, or any other header that describes some of the things you want to work on.

Then the "class Province" line creates a class called Province and derives it from SGroup, which has the common functionality for groupings of things. In particular, it derives from the instantiation of SGroup that forms a Province, which has an ID type of uint16_t and it groups together Tiles, which have an ID type of uint32_t. Getting this correct is very important!

Next up are SCRIPT_START and SCRIPT_END, those lines tell the various lua-scripts that they need to start watching out for exposed variables and functions that handle messages between them.

Finally, we have a constructor that just passes on the vector of TilePtrs to the SGroup constructor.

We also need to fill the province.cxx file, like this:
 * 1) include "province.hxx"
 * 2) include "tile.hxx"

template <> std::vector SPointer::table = std::vector(0); template <> SPointer Tile::* const SGroup::revID = &Tile::province; The first two lines include the declarations we need. Then there is a line to initialise the table used for the smart pointers to the Provinces. The final line is a very complicated way of telling the SGroup where in the Tile it can find the smart pointer to the province. Make sure you get the types right in the latter two.

Then we need to make certain there is a province variable it can find, so add a ProvincePtr to the Tile class, like this: EXPOSE ProvincePtr province; Make sure it is accessible to the Province class, either by making it public, or by making Province a friend.

Now, we need to set up the SPointer and SMessage definitions for the new class, go to the bottom of libsote.hxx and add these lines, with the ones for other classes already there. class Province; typedef SPointer ProvincePtr; typedef SMessage ProvinceMsg; The first "class Province" is needed because this is processed before the main class definition comes along, the next two lines are typedefs that make sure we no longer need to remember the correct ID type every time, and make things more readable.

Next up, add province.hxx to the list of files to process to the various lua scripts.

Finally, run the scripts, and compile to see if it worked.