D1938/rP22527 allowed introducing new damage types. Where unspecified, resistance was assumed to be 0. This was later extended via further refactoring to capture and status effects.
Now that we have some hindsight, I think this was/is the wrong choice, and we should instead assume that "unspecified = invulnerable".
Why:
- It's easier to control. To take concrete examples, we've added "Fire" damage, and now everything is susceptible to Fire. If a mod wants to add their own damage, they might need to change a lot of templates to counter-act that.
- Further, we can't actually mark a template as invulnerable to a given damage type. See D2044. The current workaround is to play with classes or give very large resistance, but that's annoying since they exist in parallel to the damage system & might not be a 1-1 match.
- Assuming invulnerability makes it easy to add Bonus damage against some units without multipliers: just add a damage type that a single unit type receives. Depending on i18n settings, we could make that damage somewhat invisible, too.
- This potentially makes it easier to do hard-counters, whether we want them or not.
- Again, this avoids having to work around with identity classes, which I think is good.
- Adding the appropriate receiver where needed is still quite easy, and I would argue more natural.
- As a nice side effect, it enforces not only that you need the 'receiver' for an attack effect, but also that you need the Resistance to it -> see e.g. D2994, having 'Resistance=I'm attackable' is nice.
- It might also make it possible to hide the ugly helper mapping attack effects to components in the resistance itself.
Overall, reversing that choice seems to give us more options, not fewer. The main concern would be that it would lead to increased verbosity in templates, but I think it's actually the opposite that happens.
I think this should also be extended to status effects, see e.g. structures being invulnerable to Poison by 100% blocking it, but instead we could just remove the 'Poisoned' tag there and add it to units with 0 resistance -> easier, more explicit. Yes, it requires that you add any new status effect to the resistance node of appropriate units, but that's unlikely to be more than a few templates, and I think overall it's OK, it's easier to control who gets X than who doesn't get X
(I'm including a test refactoring in test_Resistance).