Additional info: Simply adding a d-mod to such a ship via 'addPermaMod( "dmod_id", false )' does not cause it to lose its tags.
Having such a ship destroyed and recovered without it acquiring any d-mods also does not result in loss of tags.
My current best guess is that the on-demand creation of d-type variant hulls uses a whitelist for what tags it copies over from the base hull - presumably to avoid copying tags that would result in d-hulls getting added to blueprint packages and the like? - and that "no_auto_penalty" isn't on the whitelist because vanilla doesn't expect to see that tag set for a hull.
I assume that there
is a whitelist, rather than simply no tags being copied at all, because some tags - such as the Vanguard's "special_allows_system_use" - would result in an obvious bug if they were lost when the ship ended up in a damaged state.
However, it's also possible that the code that checks for those tags is set up to check for tags on getDParentHull(), in which case d-hull creation might reasonably
not copy any tags over. However, the Automated hullmod does not do this; it checks for tags on the hull, and on the variant, and does not test for whether that hull isDHull() or not.
As such, my conclusion is that there
may be a bug in the d-hull creation code, depending on exactly how that's implemented and what it's supposed to do. However, with the current implementation of d-hull creation, the Automated hullmod definitely doesn't quite work right; I'd suggest a bit of refactoring in Automated.java:
public static boolean isAutomatedNoPenalty(MutableShipStatsAPI stats) {
if (stats == null) return false;
return isAutomatedNoPenalty(stats.getFleetMember());
}
public static boolean isAutomatedNoPenalty(ShipAPI ship) {
if (ship == null) return false;
return isAutomatedNoPenalty(ship.getFleetMember());
}
public static boolean isAutomatedNoPenalty(FleetMemberAPI member) {
if (member == null) return false;
return member.getHullSpec().hasTag(Tags.TAG_AUTOMATED_NO_PENALTY) ||
(member.getHullSpec().isDHull() && member.getHullSpec().getDParentHull().hasTag(Tags.TAG_AUTOMATED_NO_PENALTY)) ||
member.getVariant().hasTag(Tags.TAG_AUTOMATED_NO_PENALTY);
}
This would correct the behavior for the case of d-hulls, and also refactors to have the actual check in only one place rather than having three different copies of the same code to maintain.
Edit: Or, actually, it might be better to add a hasTag() method to FleetMemberAPI that just does all this under the hood; I can't imagine that most places are likely to care if the tag originates from the hull or the variant, and being able to just ask a ship "Hey, do you have this tag?" would be significantly less error-prone than having to remember to check multiple places in every context where you want to find a tag's presence.
Edit2: And, now that I know what's going on here... for the specific ship I'm working on it's practical for me to just have code add the tag to the ship variant. I don't actually
need the tag specified on the base hull, since said base hull should never be available for sale or via blueprint. So my initial problem is... not fixed, exactly, but I have a usable workaround.