Well, I'm assuming population capacity is something that can be expressed as an equation based on other variables. So there should only be one place in code that evaluates it.
You're right that money is different. Generally you would have one time events that subtract or add an amount to this - so there is no equation that gives you the current amount of money. So yes, my claim that multiple systems shouldn't modify the same property of a Component isn't correct. It really depends on what that property expresses. For something like Money, I might make that only accessible through methods (e.g. GetMoney(), AddMoney(), SubtractMoney()).
Each building would also have bonuses that would take effect when the building is completed. Say a building increases attacking effect by x%, then some AttackSubSystem would need this information when a player attacks. But the building's bonus does not go into effect until it is completed. How does one model this state change best, while still maintaining high cohesion in the AttackSubSystem (not having to know too much about the building's logic)? I have two options here that spring to mind: 1) The AttackComponent has two columns, one for active value, and one for "desired/aim/target"-value. The subsystem always uses the active value, while the BuildingSubSystem copies target value to active value when the building is completed. 2) Another AttackModifierComponent is introduced: AttackModifiedInProgressComponent. This component would be connected to the building when first constructed and then later converted to an AttackModifierComponent.
Option 2 looks really ugly and adds complexity IMO. Any other options?
Here are my thoughts:
So, AttackSystem needs to know the multiplier. But we don't want AttackSystem to know about buildings.
I think it's reasonable that there could be an AttackMultiplier component. When we want to figure out the overall attack multiplier, we enumerate all AttackMultipliers for entities associated with that player, and combine them together (the AttackSystem could do this once per cycle). AttackMultipliers don't need to be associated with buildings of course, they could be attached to any entity.
The question now becomes when does the AttackMultiplier component get added to buildings? Seems like the BuildingSystem code could have some logic that does this when construction is completed. Or better yet, buildings always have an AttackMultiplier component. The BuildingSystem (it's ok that the BuidlingSystem knows about AttackMultiplier - someone needs to) checks the current state of the building (constructed/rundown/etc) and assigns an appropriate value to AttackMultiplier (this could be 0% if the building isn't constructed, for instance).
The AttackMultiplier component could be generalized to BonusMultiplier component, and contain other types of bonuses. Then you might actually consider a BonusCalculationSystem that enumerates all the BonusMultiplier components each cycle, and adds them up for the final tally. Other systems would request this info from the BonusCalculationSystem.
I think your last paragraph is the best option! If the building is not yet completed, then no bonus should exist at all. Representing them as 0:s in the model would add complexity when doing the actual calculations: Say you'd have a spell which would cancel a player's attack modifier, then you'd want a row in there where a zero actually meant "cancel all attacker modifiers", and then this would conflict with having a non-finished building's bonuses also represented by a zero.
I'd like some advice on naming my components as well. If a unit is able to be trained, is it prefable to name that component TrainableComponent, or CanBeTrainedComponent? Any pros cons with the naming scheme?