I'm currently implementing a system that moves all (unit-related) constants out of the source and into XML files.
The goal is that, for example, every nation has its own set of XML files where the unit data is stored and with which it is easy to add new nations or modify existing ones even without recompiling the source. Even savegames can be reused (to a limited extent)
For that I'd like to have some Feedback on the implementation.
Starting with buildings:
On XML side it is all straight forward: 1 Node per Building and 1 sub-Node per property (e.g. costs)
So an example looks like this:
Code:
<buildings>
<woodcutter>
<costs>
<boards>2</boards>
<stones>2</stones>
</costs>
...
</woodcutter>
...
</buildings>
The C++ implementation is trickier:
- We have a common set of buildings (every building exists in every nation)
- We have 1 class for almost every building
- We have some descendent classes for special buildings (harbor, military)
- Properties are required mainly inside the class but also in other classes
So I thought of creating a set of structs, 1 for each node/property. However a couple of them can be grouped together. For example BaseBuildingProp can contain costs, door-stuff, image(s) and size
Requirements:
1) The PropertyLoader must know which buildings to load and which property(groups) it should get.
2) A building class must have an instance or reference to its properties (decided at runtime which one to get depending on actual type and nation)
3) Another class must be able to access a buildings properties without having an instance of a building (E.g. for contruction, we cannot afford to create a building object just to check what it costs to build it)
My Solution:
When a building(type) needs a property, it contains a PropertyReference to it and "registers" it to the loader (say "BuildingType x needs property(group)x".
2) The PropertyReference takes the building type and the nation in its constructor and calls the loader to initialize itself (using some magic to actually just contain a pointer but behave like itself is one) --> The Building-class must call this constructor in its constructor
3) Any other class can just as well create an instance of the PropertyReference
So if you add a Property (say CoinCount for Military buildings) what you need to do is:
Add a struct for storing the value(s), add a PropertyReference to the class and init it in the constructor, add a call to the register function
In the PropertyLoader add a set for containing registred types, a register function, a load function and an init function.
This seems quite some stuff to do but I don't see a way around that. Besides that the amount of PropertyGroups is not that high, so this might be ok.
If anyone could comment on that design or got suggestions, he is welcome to do so. Or take a look at the code at
https://github.com/Flamefire/s25client/tree/DynamicNations
---
Github:
https://github.com/Flamefire