Ahh yes, that reminds me of what the issue was, exactly. I believe this is fixed for the next release.
Spoiler
private static void loadHullSkin(String path) throws IOException, JSONException {
JSONObject json = LoadingUtils.getMergedJSON(path);
String baseId = json.getString("baseHullId");
String skinId = json.getString("skinHullId");
if (ShipHullSpecStore.hasHullSpec(skinId)) return;
if (StarfarerSettings.isRunningTC()) {
if (!ShipHullSpecStore.hasHullSpec(baseId)) {
log.info("Skipping skin [" + path + "], assuming it's a core skin not used in total conversion.");
return;
}
}
ShipHullSpec hullSpec = SpecStore.getSpec(ShipHullSpec.class, baseId).clone();
int baseOP = hullSpec.getOrdnancePoints(null);
hullSpec.getTags().clear();
JSONArray tags = json.optJSONArray("tags");
if (tags != null) {
for (int i = 0; i < tags.length(); i++) {
String tag = tags.getString(i);
tag = tag.trim();
if (tag.isEmpty()) continue;
hullSpec.addTag(tag);
}
}
hullSpec.setHullId(skinId);
hullSpec.setBaseHullId(baseId);
hullSpec.setShipFilePath(path);
boolean compatible = true;
if (json.has("coversColor")) {
Color c = JSONUtils.getColor(json, "coversColor");
hullSpec.setCoversColor(c);
}
if (json.has("spriteName")) {
hullSpec.getSpriteSpec().setSpriteName(json.getString("spriteName"));
}
if (json.has("hullName")) {
hullSpec.setHullName(json.getString("hullName"));
}
if (json.has("hullDesignation")) {
hullSpec.setDesignation(json.getString("hullDesignation"));
}
if (json.has("manufacturer")) {
hullSpec.setManufacturer(json.getString("manufacturer"));
} else if (json.has("tech")) {
hullSpec.setManufacturer(json.getString("tech"));
}
if (json.has("fleetPoints")) {
hullSpec.setFleetPoints(json.getInt("fleetPoints"));
} else if (json.has("fpMod")) {
hullSpec.setFleetPoints(hullSpec.getFleetPoints() + json.getInt("fpMod"));
}
hullSpec.setRestoreToBase(json.optBoolean("restoreToBaseHull", false));
if (json.has("fighterBays")) {
hullSpec.setFighterBays(json.getInt("fighterBays"));
}
if (json.has("ordnancePoints")) {
hullSpec.setOrdnancePoints(json.getInt("ordnancePoints"));
if (baseOP != hullSpec.getOrdnancePoints(null)) {
compatible = false;
}
}
if (json.has("baseValue")) {
hullSpec.setBaseValue(json.getInt("baseValue"));
}
if (json.has("baseValueMult")) {
hullSpec.setBaseValue((int) (hullSpec.getBaseValue() * json.getDouble("baseValueMult")));
}
if (json.has("descriptionId")) {
hullSpec.setDescriptionId(json.getString("descriptionId"));
} else {
hullSpec.setDescriptionId(baseId);
}
if (json.has("descriptionPrefix")) {
String prefix = json.getString("descriptionPrefix");
if (!prefix.endsWith(".")) prefix += ".";
hullSpec.setDescriptionPrefix(prefix);
} else {
hullSpec.setDescriptionPrefix(null);
}
if (json.has("systemId")) {
hullSpec.setShipSystemId(json.getString("systemId"));
}
// "removeWeaponSlots":[],
// "removeEngineSlots":[],
if (json.has("removeWeaponSlots")) {
JSONArray arr = json.getJSONArray("removeWeaponSlots");
for (int i = 0; i < arr.length(); i++) {
String slotId = arr.getString(i);
for (WeaponSlotSpec slot : hullSpec.getAllWeaponSlots()) {
if (slot.getId().equals(slotId)) {
hullSpec.getAllWeaponSlots().remove(slot);
compatible = false;
break;
}
}
}
}
if (json.has("removeEngineSlots")) {
JSONArray arr = json.getJSONArray("removeEngineSlots");
List<EngineSlotSpec> remove = new ArrayList<EngineSlotSpec>();
for (int i = 0; i < arr.length(); i++) {
int slotIndex = arr.getInt(i);
if (slotIndex >= 0 && slotIndex < hullSpec.getEngineSlots().size()) {
remove.add(hullSpec.getEngineSlots().get(slotIndex));
}
}
hullSpec.getEngineSlots().removeAll(remove);
}
// "removeBuiltInMods":[],
// "removeBuiltInWeapons":[],
if (json.has("removeBuiltInMods")) {
JSONArray arr = json.getJSONArray("removeBuiltInMods");
for (int i = 0; i < arr.length(); i++) {
String modId = arr.getString(i);
hullSpec.getBuiltInMods().remove(modId);
compatible = false;
}
}
if (json.has("removeBuiltInWings")) {
JSONArray arr = json.getJSONArray("removeBuiltInWings");
for (int i = 0; i < arr.length(); i++) {
String wingId = arr.getString(i);
hullSpec.getBuiltInWings().remove(wingId);
compatible = false;
}
}
if (json.has("removeBuiltInWeapons")) {
JSONArray arr = json.getJSONArray("removeBuiltInWeapons");
for (int i = 0; i < arr.length(); i++) {
String slotId = arr.getString(i);
hullSpec.getBuiltInWeapons().remove(slotId);
compatible = false;
}
}
// "removeHints":[CIVILIAN],
// "addHints":[],
if (json.has("removeHints")) {
JSONArray arr = json.getJSONArray("removeHints");
for (int i = 0; i < arr.length(); i++) {
ShipTypeHints hint = ShipTypeHints.valueOf(arr.getString(i));
hullSpec.getHints().remove(hint);
}
}
if (json.has("addHints")) {
JSONArray arr = json.getJSONArray("addHints");
for (int i = 0; i < arr.length(); i++) {
ShipTypeHints hint = ShipTypeHints.valueOf(arr.getString(i));
hullSpec.getHints().add(hint);
}
}
// "builtInMods":["tow_cable"],
if (json.has("builtInMods")) {
JSONArray arr = json.getJSONArray("builtInMods");
for (int i = 0; i < arr.length(); i++) {
String modId = arr.getString(i);
hullSpec.addBuiltInMod(modId);
//compatible = false;
}
}
if (json.has("builtInWings")) {
JSONArray arr = json.getJSONArray("builtInWings");
for (int i = 0; i < arr.length(); i++) {
String wingId = arr.getString(i);
hullSpec.addBuiltInWing(wingId);
compatible = false;
}
}
// "builtInWeapons":{
// "WS 016":"tpc",
// "WS 017":"tpc",
// },
if (json.has("builtInWeapons")) {
JSONObject builtInWeapons = json.getJSONObject("builtInWeapons");
if (JSONObject.getNames(builtInWeapons) != null) {
for (String slotId : JSONObject.getNames(builtInWeapons)) {
String weaponId = builtInWeapons.getString(slotId);
hullSpec.addBuiltInWeapon(slotId, weaponId);
compatible = false;
}
}
}
// "weaponSlotChanges":{
// "WS 001":{
// #"angle": 0,
// #"arc": 210,
// #"mount": "TURRET",
// #"size": "SMALL",
// "type": "BALLISTIC"
// }
// },
if (json.has("weaponSlotChanges")) {
JSONObject changes = json.getJSONObject("weaponSlotChanges");
if (JSONObject.getNames(changes) != null) {
for (String slotId : JSONObject.getNames(changes)) {
WeaponSlotSpec slot = hullSpec.getWeaponSlot(slotId);
JSONObject data = changes.getJSONObject(slotId);
if (data.has("angle")) {
slot.setAngle((float) data.getDouble("angle"));
}
if (data.has("arc")) {
slot.setArc((float) data.getDouble("arc"));
}
// JSONUtils.mapToEnum(weaponSlotSpecJson, "type", WeaponAPI.WeaponType.class, null),
// JSONUtils.mapToEnum(weaponSlotSpecJson, "size", WeaponAPI.WeaponSize.class, null),
// JSONUtils.mapToEnum(weaponSlotSpecJson, "mount", WeaponSlotType.class, null),
if (data.has("mount")) {
slot.setSlotType(JSONUtils.mapToEnum(data, "mount", WeaponSlotType.class, null));
}
if (data.has("size")) {
slot.setSlotSize(JSONUtils.mapToEnum(data, "size", WeaponAPI.WeaponSize.class, null));
}
if (data.has("type")) {
slot.setWeaponType(JSONUtils.mapToEnum(data, "type", WeaponAPI.WeaponType.class, null));
}
compatible = false;
}
}
}
// "engineSlotChanges":{
// "0":{
// #"width": 0,
// #"length": 210,
// #"angle": 210,
// #"style": "SMALL",
// }
// },
if (json.has("engineSlotChanges")) {
JSONObject changes = json.getJSONObject("engineSlotChanges");
if (JSONObject.getNames(changes) != null) {
for (String slotId : JSONObject.getNames(changes)) {
int index = Integer.parseInt(slotId);
EngineSlotSpec slot = hullSpec.getEngineSlots().get(index);
JSONObject data = changes.getJSONObject(slotId);
if (data.has("style")) {
String style = data.getString("style");
CustomEngineData custom = SpecStore.getSpec(CustomEngineData.class, style);
slot.setStyle(Style.CUSTOM);
slot.setCustomData(custom);
}
if (data.has("width")) {
slot.setWidth((float) data.getDouble("width"));
}
if (data.has("length")) {
slot.setLength((float) data.getDouble("length"));
}
if (data.has("angle")) {
slot.setAngle((float) data.getDouble("angle"));
}
}
}
}
hullSpec.setCompatibleWithBase(compatible);
ShipHullSpecStore.putSpec(skinId, hullSpec);
if (firstTime) {
//if (!hullSpec.isDHull()) {
//if (!hullSpec.isDHullOldMethod()) {
ShipHullSpecLoader.addDHull(hullSpec);
//}
HullVariantSpec empty = new HullVariantSpec(skinId + "_Hull", hullSpec);
if (hullSpec.getAllWeaponSlots().isEmpty()) {
empty.setVariantDisplayName("Standard");
} else {
empty.setVariantDisplayName("Custom");
}
empty.setSource(VariantSource.HULL);
ShipVariantStore.addVariant(empty);
}
}