// MassBuilderSaveTool // Copyright (C) 2021-2022 Guillaume Jacquemin // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program. If not, see . #include "../UESaveFile/Types/ArrayProperty.h" #include "../UESaveFile/Types/BoolProperty.h" #include "../UESaveFile/Types/ByteProperty.h" #include "../UESaveFile/Types/ColourStructProperty.h" #include "../UESaveFile/Types/GenericStructProperty.h" #include "../UESaveFile/Types/IntProperty.h" #include "../UESaveFile/Types/StringProperty.h" #include "Mass.h" using namespace Containers::Literals; auto Mass::meleeWeapons() -> Containers::ArrayView { return _weapons.melee; } void Mass::getMeleeWeapons() { getWeaponType("WeaponCC_22_0BBEC58C4A0EA1DB9E037B9339EE26A7"_s, _weapons.melee); } auto Mass::writeMeleeWeapons() -> bool { return writeWeaponType("WeaponCC_22_0BBEC58C4A0EA1DB9E037B9339EE26A7"_s, _weapons.melee); } auto Mass::shields() -> Containers::ArrayView { return _weapons.shields; } void Mass::getShields() { getWeaponType("Shield_53_839BFD7945481BAEA3E43A9C5CA8E92E"_s, _weapons.shields); } auto Mass::writeShields() -> bool { return writeWeaponType("Shield_53_839BFD7945481BAEA3E43A9C5CA8E92E"_s, _weapons.shields); } auto Mass::bulletShooters() -> Containers::ArrayView { return _weapons.bulletShooters; } void Mass::getBulletShooters() { getWeaponType("WeaponBS_35_6EF6E0104FD7A138DF47F88CB57A83ED"_s, _weapons.bulletShooters); } auto Mass::writeBulletShooters() -> bool { return writeWeaponType("WeaponBS_35_6EF6E0104FD7A138DF47F88CB57A83ED"_s, _weapons.bulletShooters); } auto Mass::energyShooters() -> Containers::ArrayView { return _weapons.energyShooters; } void Mass::getEnergyShooters() { getWeaponType("WeaponES_37_1A295D544528623880A0B1AC2C7DEE99"_s, _weapons.energyShooters); } auto Mass::writeEnergyShooters() -> bool { return writeWeaponType("WeaponES_37_1A295D544528623880A0B1AC2C7DEE99"_s, _weapons.energyShooters); } auto Mass::bulletLaunchers() -> Containers::ArrayView { return _weapons.bulletLaunchers; } void Mass::getBulletLaunchers() { getWeaponType("WeaponBL_36_5FD7C41E4613A75B44AB0E90B362846E"_s, _weapons.bulletLaunchers); } auto Mass::writeBulletLaunchers() -> bool { return writeWeaponType("WeaponBL_36_5FD7C41E4613A75B44AB0E90B362846E"_s, _weapons.bulletLaunchers); } auto Mass::energyLaunchers() -> Containers::ArrayView { return _weapons.energyLaunchers; } void Mass::getEnergyLaunchers() { getWeaponType("WeaponEL_38_9D23F3884ACA15902C9E6CA6E4995995"_s, _weapons.energyLaunchers); } auto Mass::writeEnergyLaunchers() -> bool { return writeWeaponType("WeaponEL_38_9D23F3884ACA15902C9E6CA6E4995995"_s, _weapons.energyLaunchers); } void Mass::getWeaponType(Containers::StringView prop_name, Containers::ArrayView weapon_array) { auto unit_data = _mass->at("UnitData"_s); if(!unit_data) { Utility::Error{} << "Can't find unit data in" << _filename; _state = State::Invalid; return; } auto prop = unit_data->at(prop_name); if(!prop) { Utility::Error{} << "Can't find" << prop_name << "in" << _filename; _state = State::Invalid; return; } if(prop->items.size() != weapon_array.size()) { Utility::Error{} << "Weapon arrays are not of the same size. Expected" << weapon_array.size() << Utility::Debug::nospace << ", got" << prop->items.size() << "instead."; _state = State::Invalid; return; } for(UnsignedInt i = 0; i < weapon_array.size(); i++) { auto weapon_prop = prop->at(i); auto& weapon = weapon_array[i]; weapon.name = weapon_prop->at("Name_13_7BF0D31F4E50C50C47231BB36A485D92"_s)->value; auto& weapon_type = weapon_prop->at("Type_2_35ABA8C3406F8D9BBF14A89CD6BCE976"_s)->enumValue; #define c(enumerator, strenum, name) if(weapon_type == (strenum)) { weapon.type = WeaponType::enumerator; } else #include "../Maps/WeaponTypes.hpp" #undef c { _state = State::Invalid; Utility::Warning{} << "Invalid weapon type enum value in getWeaponType()."_s; } auto parts_prop = weapon_prop->at("Element_6_8E4617CC4B2C1F1490435599784EC6E0"_s); weapon.parts = Containers::Array{ValueInit, parts_prop->items.size()}; for(UnsignedInt j = 0; j < parts_prop->items.size(); j++) { auto part_prop = parts_prop->at(j); auto& part = weapon.parts[j]; part.id = part_prop->at("ID_2_A74D75434308158E5926178822DD28EE"_s)->value; auto part_styles = part_prop->at("Styles_17_994C97C34A90667BE5B716BFD0B97588"_s); for(UnsignedInt k = 0; k < part_styles->items.size(); k++) { part.styles[k] = part_styles->at(k)->value; } auto part_decals = part_prop->at("Decals_13_8B81112B453D7230C0CDE982185E14F1"_s); if(part_decals->items.size() != part.decals.size()) { part.decals = Containers::Array{part_decals->items.size()}; } getDecals(part.decals, part_decals); auto part_accs = part_prop->at("Accessories_21_3878DE8B4ED0EA0DB725E98BCDC20E0C"_s); if(!part_accs) { part.accessories = Containers::Array{0}; continue; } if(part_accs->items.size() != part.accessories.size()) { part.accessories = Containers::Array{part_accs->items.size()}; } getAccessories(part.accessories, part_accs); } auto custom_styles = weapon_prop->at("Styles_10_8C3C82444B986AD7A99595AD4985912D"_s); if(!custom_styles) { Utility::Error{} << "Can't find weapon custom styles in" << _filename; _state = State::Invalid; return; } if(custom_styles->items.size() != weapon.customStyles.size()) { Utility::Error{} << "Weapon custom style arrays are not of the same size. Expected" << weapon.customStyles.size() << Utility::Debug::nospace << ", got" << custom_styles->items.size() << "instead."; _state = State::Invalid; return; } getCustomStyles(weapon.customStyles, custom_styles); weapon.attached = weapon_prop->at("Attach_15_D00AABBD4AD6A04778D56D81E51927B3"_s)->value; auto& damage_type = weapon_prop->at("DamageType_18_E1FFA53540591A9087EC698117A65C83"_s)->enumValue; #define c(enumerator, strenum) if(damage_type == (strenum)) { weapon.damageType = DamageType::enumerator; } else #include "../Maps/DamageTypes.hpp" #undef c { _state = State::Invalid; Utility::Warning{} << "Invalid damage type enum value in getWeaponType()."_s; } weapon.dualWield = weapon_prop->at("DualWield_20_B2EB2CEA4A6A233DC7575996B6DD1222"_s)->value; auto& effect_colour_mode = weapon_prop->at("ColorEfxMode_24_D254BCF943E852BF9ADB8AAA8FD80014"_s)->enumValue; #define c(enumerator, strenum) if(effect_colour_mode == (strenum)) { weapon.effectColourMode = EffectColourMode::enumerator; } else #include "../Maps/EffectColourModes.hpp" #undef c { _state = State::Invalid; Utility::Warning{} << "Invalid effect colour mode in getWeaponType()."_s; } auto effect_colour = weapon_prop->at("ColorEfx_26_D921B62946C493E487455A831F4520AC"_s); weapon.effectColour = Color4{effect_colour->r, effect_colour->g, effect_colour->b, effect_colour->a}; } } auto Mass::writeWeaponType(Containers::StringView prop_name, Containers::ArrayView weapon_array) -> bool { auto unit_data = _mass->at("UnitData"_s); if(!unit_data) { _state = State::Invalid; _lastError = "No unit data in "_s + _filename; return false; } auto prop = unit_data->at(prop_name); if(!prop) { _state = State::Invalid; _lastError = prop_name + " not found in "_s + _filename; return false; } if(prop->items.size() != weapon_array.size()) { _state = State::Invalid; _lastError = "Weapon type array size mismatch."_s; return false; } for(UnsignedInt i = 0; i < weapon_array.size(); i++) { auto weapon_prop = prop->at(i); auto& weapon = weapon_array[i]; weapon_prop->at("Name_13_7BF0D31F4E50C50C47231BB36A485D92"_s)->value = weapon.name; switch(weapon.type) { #define c(enumerator, strenum, name) case WeaponType::enumerator: weapon_prop->at("Type_2_35ABA8C3406F8D9BBF14A89CD6BCE976"_s)->enumValue = strenum; break; #include "../Maps/WeaponTypes.hpp" #undef c default: Utility::Warning{} << "Invalid weapon type enum value in writeWeaponType()."_s; } auto parts_prop = weapon_prop->at("Element_6_8E4617CC4B2C1F1490435599784EC6E0"_s); if(parts_prop->items.size() != weapon.parts.size()) { _state = State::Invalid; _lastError = "Weapon parts array size mismatch."_s; return false; } for(UnsignedInt j = 0; j < parts_prop->items.size(); j++) { auto part_prop = parts_prop->at(j); auto& part = weapon.parts[j]; part_prop->at("ID_2_A74D75434308158E5926178822DD28EE"_s)->value = part.id; auto part_styles = part_prop->at("Styles_17_994C97C34A90667BE5B716BFD0B97588"_s); for(UnsignedInt k = 0; k < part_styles->items.size(); k++) { part_styles->at(k)->value = part.styles[k]; } auto part_decals = part_prop->at("Decals_13_8B81112B453D7230C0CDE982185E14F1"_s); writeDecals(part.decals, part_decals); auto part_accs = part_prop->at("Accessories_21_3878DE8B4ED0EA0DB725E98BCDC20E0C"_s); if(!part_accs) { continue; } if(part_accs->items.size() != part.accessories.size()) { _state = State::Invalid; _lastError = "Accessories array size mismatch."_s; return false; } writeAccessories(part.accessories, part_accs); } auto custom_styles = weapon_prop->at("Styles_10_8C3C82444B986AD7A99595AD4985912D"_s); if(!custom_styles) { _state = State::Invalid; _lastError = "No custom styles found for weapon."_s; return false; } if(custom_styles->items.size() != weapon.customStyles.size()) { _state = State::Invalid; _lastError = "Custom styles array size mismatch."_s; return false; } for(UnsignedInt j = 0; j < weapon.customStyles.size(); j++) { writeCustomStyle(weapon.customStyles[j], j, custom_styles); } weapon_prop->at("Attach_15_D00AABBD4AD6A04778D56D81E51927B3"_s)->value = weapon.attached; switch(weapon.damageType) { #define c(enumerator, strenum) case DamageType::enumerator: weapon_prop->at("DamageType_18_E1FFA53540591A9087EC698117A65C83"_s)->enumValue = strenum; break; #include "../Maps/DamageTypes.hpp" #undef c default: Utility::Warning{} << "Unknown damage type enum value in writeWeaponType()."_s; } weapon_prop->at("DualWield_20_B2EB2CEA4A6A233DC7575996B6DD1222"_s)->value = weapon.dualWield; switch(weapon.effectColourMode) { #define c(enumerator, enumstr) case EffectColourMode::enumerator: \ weapon_prop->at("ColorEfxMode_24_D254BCF943E852BF9ADB8AAA8FD80014"_s)->enumValue = enumstr; \ break; #include "../Maps/EffectColourModes.hpp" #undef c default: Utility::Warning{} << "Unknown effect colour mode in writeWeaponType()."_s; } auto effect_colour = weapon_prop->at("ColorEfx_26_D921B62946C493E487455A831F4520AC"_s); effect_colour->r = weapon.effectColour.r(); effect_colour->g = weapon.effectColour.g(); effect_colour->b = weapon.effectColour.b(); effect_colour->a = weapon.effectColour.a(); } if(!_mass->saveToFile()) { _lastError = _mass->lastError(); return false; } return true; }