// MassBuilderSaveTool // Copyright (C) 2021 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 #include #include #include #include "../UESaveFile/Types/ArrayProperty.h" #include "../UESaveFile/Types/BoolProperty.h" #include "../UESaveFile/Types/ByteProperty.h" #include "../UESaveFile/Types/ColourStructProperty.h" #include "../UESaveFile/Types/FloatProperty.h" #include "../UESaveFile/Types/GenericStructProperty.h" #include "../UESaveFile/Types/IntProperty.h" #include "../UESaveFile/Types/RotatorStructProperty.h" #include "../UESaveFile/Types/StringProperty.h" #include "../UESaveFile/Types/VectorStructProperty.h" #include "../UESaveFile/Types/Vector2DStructProperty.h" #include "Mass.h" std::string Mass::_lastError; Mass::Mass(const std::string& path) { _folder = Utility::Directory::path(path); _filename = Utility::Directory::filename(path); refreshValues(); } auto Mass::lastError() -> std::string const& { return _lastError; } auto Mass::getNameFromFile(const std::string& path) -> Containers::Optional { if(!Utility::Directory::exists(path)) { _lastError = path + " couldn't be found."; return Containers::NullOpt; } UESaveFile mass{path}; if(!mass.valid()) { _lastError = "The unit file seems to be corrupt."; return Containers::NullOpt; } auto unit_data = mass.at("UnitData"); if(!unit_data) { _lastError = "Couldn't find unit data in the file."; return Containers::NullOpt; } auto name_prop = unit_data->at("Name_45_A037C5D54E53456407BDF091344529BB"); if(!name_prop) { _lastError = "Couldn't find the name in the file."; return Containers::NullOpt; } return name_prop->value; } void Mass::refreshValues() { if(!Utility::Directory::exists(Utility::Directory::join(_folder, _filename))) { _state = State::Empty; return; } if(!_mass) { _mass.emplace(Utility::Directory::join(_folder, _filename)); if(!_mass->valid()) { _state = State::Invalid; return; } } else { if(!_mass->reloadData()) { _state = State::Invalid; return; } } auto unit_data = _mass->at("UnitData"); if(!unit_data) { _state = State::Invalid; return; } auto name_prop = unit_data->at("Name_45_A037C5D54E53456407BDF091344529BB"); if(!name_prop) { _name = Containers::NullOpt; _state = State::Invalid; return; } _name = name_prop->value; getJointSliders(); if(_state == State::Invalid) { return; } getFrameStyles(); if(_state == State::Invalid) { return; } getEyeFlareColour(); if(_state == State::Invalid) { return; } getFrameCustomStyles(); if(_state == State::Invalid) { return; } getArmourParts(); if(_state == State::Invalid) { return; } getArmourCustomStyles(); if(_state == State::Invalid) { return; } getMeleeWeapons(); if(_state == State::Invalid) { return; } getShields(); if(_state == State::Invalid) { return; } getBulletShooters(); if(_state == State::Invalid) { return; } getEnergyShooters(); if(_state == State::Invalid) { return; } getBulletLaunchers(); if(_state == State::Invalid) { return; } getEnergyLaunchers(); if(_state == State::Invalid) { return; } if(!_demo) { getGlobalStyles(); } // TODO: tuning auto account_prop = _mass->at("Account"); if(!account_prop) { _state = State::Invalid; return; } _steamId = account_prop->value; _state = State::Valid; } auto Mass::filename() -> std::string const&{ return _filename; } auto Mass::name() -> Containers::Optional const& { return _name; } auto Mass::setName(std::string new_name) -> bool { _name = new_name; auto unit_data = _mass->at("UnitData"); if(!unit_data) { _state = State::Invalid; return false; } auto name_prop = unit_data->at("Name_45_A037C5D54E53456407BDF091344529BB"); if(!name_prop) { _state = State::Invalid; return false; } name_prop->value = std::move(new_name); return _mass->saveToFile(); } auto Mass::state() -> State { return _state; } auto Mass::demo() const -> bool { return _demo; } auto Mass::dirty() const -> bool { return _dirty; } void Mass::setDirty(bool dirty) { _dirty = dirty; } auto Mass::jointSliders() -> Joints& { return _frame.joints; } void Mass::getJointSliders() { auto unit_data = _mass->at("UnitData"); if(!unit_data) { _state = State::Invalid; return; } auto frame_prop = unit_data->at("Frame_3_F92B0F6A44A15088AF7F41B9FF290653"); if(!frame_prop) { _state = State::Invalid; return; } auto length = frame_prop->at("NeckLength_6_ED6AF79849C27CD1A9D523A09E2BFE58"); _frame.joints.neck = (length ? length->value : 0.0f); length = frame_prop->at("BodyLength_7_C16287754CBA96C93BAE36A5C154996A"); _frame.joints.body = (length ? length->value : 0.0f); length = frame_prop->at("ShoulderLength_8_220EDF304F1C1226F0D8D39117FB3883"); _frame.joints.shoulders = (length ? length->value : 0.0f); length = frame_prop->at("HipLength_14_02AEEEAC4376087B9C51F0AA7CC92818"); _frame.joints.hips = (length ? length->value : 0.0f); length = frame_prop->at("ArmUpperLength_10_249FDA3E4F3B399E7B9E5C9B7C765EAE"); _frame.joints.upperArms = (length ? length->value : 0.0f); length = frame_prop->at("ArmLowerLength_12_ACD0F02745C28882619376926292FB36"); _frame.joints.lowerArms = (length ? length->value : 0.0f); length = frame_prop->at("LegUpperLength_16_A7C4C71249A3776F7A543D96819C0C61"); _frame.joints.upperLegs = (length ? length->value : 0.0f); length = frame_prop->at("LegLowerLength_18_D2DF39964EA0F2A2129D0491B08A032F"); _frame.joints.lowerLegs = (length ? length->value : 0.0f); } auto Mass::writeJointSliders() -> bool { auto unit_data = _mass->at("UnitData"); if(!unit_data) { _state = State::Invalid; _lastError = "No unit data in " + _filename; return false; } auto frame_prop = unit_data->at("Frame_3_F92B0F6A44A15088AF7F41B9FF290653"); if(!frame_prop) { _state = State::Invalid; _lastError = "No frame data in " + _filename; return false; } auto length = frame_prop->at("NeckLength_6_ED6AF79849C27CD1A9D523A09E2BFE58"); if(!length && _frame.joints.neck != 0.0f) { length = new FloatProperty; auto length_prop = FloatProperty::ptr{length}; length_prop->name.emplace("NeckLength_6_ED6AF79849C27CD1A9D523A09E2BFE58"); arrayAppend(frame_prop->properties, std::move(length_prop)); } if(length) { length->value = _frame.joints.neck; } length = frame_prop->at("BodyLength_7_C16287754CBA96C93BAE36A5C154996A"); if(!length && _frame.joints.body != 0.0f) { length = new FloatProperty; auto length_prop = FloatProperty::ptr{length}; length_prop->name.emplace("BodyLength_7_C16287754CBA96C93BAE36A5C154996A"); arrayAppend(frame_prop->properties, std::move(length_prop)); } if(length) { length->value = _frame.joints.body; } length = frame_prop->at("ShoulderLength_8_220EDF304F1C1226F0D8D39117FB3883"); if(!length && _frame.joints.shoulders != 0.0f) { length = new FloatProperty; auto length_prop = FloatProperty::ptr{length}; length_prop->name.emplace("ShoulderLength_8_220EDF304F1C1226F0D8D39117FB3883"); arrayAppend(frame_prop->properties, std::move(length_prop)); } if(length) { length->value = _frame.joints.shoulders; } length = frame_prop->at("HipLength_14_02AEEEAC4376087B9C51F0AA7CC92818"); if(!length && _frame.joints.hips != 0.0f) { length = new FloatProperty; auto length_prop = FloatProperty::ptr{length}; length_prop->name.emplace("HipLength_14_02AEEEAC4376087B9C51F0AA7CC92818"); arrayAppend(frame_prop->properties, std::move(length_prop)); } if(length) { length->value = _frame.joints.hips; } length = frame_prop->at("ArmUpperLength_10_249FDA3E4F3B399E7B9E5C9B7C765EAE"); if(!length && _frame.joints.upperArms != 0.0f) { length = new FloatProperty; auto length_prop = FloatProperty::ptr{length}; length_prop->name.emplace("ArmUpperLength_10_249FDA3E4F3B399E7B9E5C9B7C765EAE"); arrayAppend(frame_prop->properties, std::move(length_prop)); } if(length) { length->value = _frame.joints.upperArms; } length = frame_prop->at("ArmLowerLength_12_ACD0F02745C28882619376926292FB36"); if(!length && _frame.joints.lowerArms != 0.0f) { length = new FloatProperty; auto length_prop = FloatProperty::ptr{length}; length_prop->name.emplace("ArmLowerLength_12_ACD0F02745C28882619376926292FB36"); arrayAppend(frame_prop->properties, std::move(length_prop)); } if(length) { length->value = _frame.joints.lowerArms; } length = frame_prop->at("LegUpperLength_16_A7C4C71249A3776F7A543D96819C0C61"); if(!length && _frame.joints.upperLegs != 0.0f) { length = new FloatProperty; auto length_prop = FloatProperty::ptr{length}; length_prop->name.emplace("LegUpperLength_16_A7C4C71249A3776F7A543D96819C0C61"); arrayAppend(frame_prop->properties, std::move(length_prop)); } if(length) { length->value = _frame.joints.upperLegs; } length = frame_prop->at("LegLowerLength_18_D2DF39964EA0F2A2129D0491B08A032F"); if(!length && _frame.joints.lowerLegs != 0.0f) { length = new FloatProperty; auto length_prop = FloatProperty::ptr{length}; length_prop->name.emplace("LegLowerLength_18_D2DF39964EA0F2A2129D0491B08A032F"); arrayAppend(frame_prop->properties, std::move(length_prop)); } if(length) { length->value = _frame.joints.lowerLegs; } if(!_mass->saveToFile()) { _lastError = "Couldn't write data to " + _filename; return false; } return true; } auto Mass::frameStyles() -> Containers::StaticArrayView<4, Int> { return _frame.styles; } void Mass::getFrameStyles() { auto unit_data = _mass->at("UnitData"); if(!unit_data) { _state = State::Invalid; return; } auto frame_prop = unit_data->at("Frame_3_F92B0F6A44A15088AF7F41B9FF290653"); if(!frame_prop) { _state = State::Invalid; return; } auto frame_styles = frame_prop->at("Styles_32_00A3B3284B37F1E7819458844A20EB48"); if(!frame_styles) { _state = State::Invalid; return; } if(frame_styles->items.size() != 4) { _state = State::Invalid; return; } for(UnsignedInt i = 0; i < 4; i++) { _frame.styles[i] = frame_styles->at(i)->value; } } auto Mass::writeFrameStyles() -> bool { auto unit_data = _mass->at("UnitData"); if(!unit_data) { _state = State::Invalid; _lastError = "No unit data in " + _filename; return false; } auto frame = unit_data->at("Frame_3_F92B0F6A44A15088AF7F41B9FF290653"); if(!frame) { _state = State::Invalid; _lastError = "No frame data in " + _filename; return false; } auto frame_styles = frame->at("Styles_32_00A3B3284B37F1E7819458844A20EB48"); if(!frame_styles) { _state = State::Invalid; _lastError = "No frame styles in " + _filename; return false; } for(UnsignedInt i = 0; i < frame_styles->items.size(); i++) { frame_styles->at(i)->value = _frame.styles[i]; } if(!_mass->saveToFile()) { _lastError = "Couldn't write data to " + _filename; return false; } return true; } auto Mass::eyeFlareColour() -> Color4& { return _frame.eyeFlare; } void Mass::getEyeFlareColour() { auto unit_data = _mass->at("UnitData"); if(!unit_data) { _state = State::Invalid; return; } auto frame_prop = unit_data->at("Frame_3_F92B0F6A44A15088AF7F41B9FF290653"); if(!frame_prop) { _state = State::Invalid; return; } auto eye_flare_prop = frame_prop->at("EyeFlareColor_36_AF79999C40FCA0E88A2F9A84488A38CA"); if(!eye_flare_prop) { _state = State::Invalid; return; } _frame.eyeFlare = Color4{eye_flare_prop->r, eye_flare_prop->g, eye_flare_prop->b, eye_flare_prop->a}; } auto Mass::writeEyeFlareColour() -> bool { auto unit_data = _mass->at("UnitData"); if(!unit_data) { _state = State::Invalid; return false; } auto frame = unit_data->at("Frame_3_F92B0F6A44A15088AF7F41B9FF290653"); if(!frame) { _state = State::Invalid; return false; } auto eye_flare_prop = frame->at("EyeFlareColor_36_AF79999C40FCA0E88A2F9A84488A38CA"); if(!eye_flare_prop) { _state = State::Invalid; return false; } eye_flare_prop->r = _frame.eyeFlare.r(); eye_flare_prop->g = _frame.eyeFlare.g(); eye_flare_prop->b = _frame.eyeFlare.b(); eye_flare_prop->a = _frame.eyeFlare.a(); return _mass->saveToFile(); } auto Mass::frameCustomStyles() -> Containers::StaticArrayView<16, CustomStyle> { return _frame.customStyles; } void Mass::getFrameCustomStyles() { auto unit_data = _mass->at("UnitData"); if(!unit_data) { _state = State::Invalid; return; } auto frame_styles = unit_data->at("FrameStyle_44_04A44C9440363CCEC5443D98BFAF22AA"); if(!frame_styles) { _state = State::Invalid; return; } if(frame_styles->items.size() != 16) { _state = State::Invalid; return; } for(UnsignedInt i = 0; i < frame_styles->items.size(); i++) { auto style_prop = frame_styles->at(i); CustomStyle style; style.name = style_prop->at("Name_27_1532115A46EF2B2FA283908DF561A86B")->value; auto colour_prop = style_prop->at("Color_5_F0D383DF40474C9464AE48A0984A212E"); style.colour = Color4{colour_prop->r, colour_prop->g, colour_prop->b, colour_prop->a}; style.metallic = style_prop->at("Metallic_10_0A4CD1E4482CBF41CA61D0A856DE90B9")->value; style.gloss = style_prop->at("Gloss_11_9769599842CC275A401C4282A236E240")->value; style.glow = colour_prop->a == 0.0f ? false : true; style.patternId = style_prop->at("PatternID_14_516DB85641DAF8ECFD2920BE2BDF1311")->value; style.opacity = style_prop->at("Opacity_30_53BD060B4DFCA1C92302D6A0F7831131")->value; style.offset = Vector2{ style_prop->at("OffsetX_23_70FC2E814C64BBB82452748D2AF9CD48")->value, style_prop->at("OffsetY_24_5E1F866C4C054D9B2EE337ADC180C17F")->value }; style.rotation = style_prop->at("Rotation_25_EC2DFAD84AD0A6BD3FA841ACD52EDD6D")->value; style.scale = style_prop->at("Scale_26_19DF0708409262183E1247B317137671")->value; _frame.customStyles[i] = std::move(style); } } auto Mass::writeFrameCustomStyle(UnsignedLong index) -> bool { if(index > _frame.customStyles.size()) { return false; } return setCustomStyle(_frame.customStyles[index], index, "FrameStyle_44_04A44C9440363CCEC5443D98BFAF22AA"); } auto Mass::armourParts() -> Containers::StaticArrayView<38, ArmourPart> { return _armour.parts; } void Mass::getArmourParts() { auto unit_data = _mass->at("UnitData"); if(!unit_data) { _state = State::Invalid; return; } auto armour_array = unit_data->at("Armor_10_12E266C44116DDAF57E99ABB575A4B3C"); if(!armour_array) { _state = State::Invalid; return; } if(armour_array->items.size() != _armour.parts.size()) { _state = State::Invalid; return; } for(UnsignedInt i = 0; i < armour_array->items.size(); i++) { auto part_prop = armour_array->at(i); auto& part = _armour.parts[i]; part.slot = part_prop->at("Slot_3_408BA56F4C9605C7E805CF91B642249C")->enumValue; part.id = part_prop->at("ID_5_ACD101864D3481DE96EDACACC09BDD25")->value; auto part_styles = part_prop->at("Styles_47_3E31870441DFD7DB8BEE5C85C26B365B"); if(!part_styles) { _state = State::Invalid; return; } if(part_styles->items.size() != part.styles.size()) { _state = State::Invalid; return; } for(UnsignedInt j = 0; j < part_styles->items.size(); j++) { part.styles[j] = part_styles->at(j)->value; } auto decals_array = part_prop->at("Decals_42_F358794A4F18497970F56BA9627D3603"); if(!decals_array) { _state = State::Invalid; return; } if(decals_array->items.size() != part.decals.size()) { part.demoDecals = decals_array->items.size(); _demo = true; } for(UnsignedInt j = 0; j < decals_array->items.size(); j++) { auto decal_prop = decals_array->at(j); auto& decal = part.decals[j]; decal.id = decal_prop->at("ID_3_694C0B35404D8A3168AEC89026BC8CF9")->value; auto colour_prop = decal_prop->at("Color_8_1B0B9D2B43DA6AAB9FA549B374D3E606"); decal.colour = Color4{colour_prop->r, colour_prop->g, colour_prop->b, colour_prop->a}; auto pos_prop = decal_prop->at("Position_41_022C8FE84E1AAFE587261E88F2C72250"); decal.position = Vector3{pos_prop->x, pos_prop->y, pos_prop->z}; auto u_prop = decal_prop->at("UAxis_37_EBEB715F45491AECACCC07A1AE4646D1"); decal.uAxis = Vector3{u_prop->x, u_prop->y, u_prop->z}; auto v_prop = decal_prop->at("VAxis_39_C31EB2664EE202CAECFBBB84100B5E35"); decal.vAxis = Vector3{v_prop->x, v_prop->y, v_prop->z}; auto offset_prop = decal_prop->at("Offset_29_B02BBBB74FC60F5EDBEBAB8020738020"); decal.offset = Vector2{offset_prop->x, offset_prop->y}; decal.scale = decal_prop->at("Scale_32_959D1C2747AFD8D62808468235CBBA40")->value; decal.rotation = decal_prop->at("Rotation_27_12D7C314493D203D5C2326A03C5F910F")->value; decal.flip = decal_prop->at("Flip_35_CECCFB184CCD9412BD93FE9A8B656BE1")->value; decal.wrap = decal_prop->at("Wrap_43_A7C68CDF4A92AF2ECDA53F953EE7CA62")->value; } if(!_demo) { auto accs_array = part_prop->at("Accessories_52_D902DD4241FA0050C2529596255153F3"); if(!accs_array) { _demo = true; continue; } if(accs_array->items.size() != part.accessories.size()) { _state = State::Invalid; return; } for(UnsignedInt j = 0; j < accs_array->items.size(); j++) { auto acc_prop = accs_array->at(j); auto& accessory = part.accessories[j]; accessory.attachIndex = acc_prop->at("AttachIndex_2_4AFCF6024E4BA7426C6B9F80B8179D20")->value; accessory.id = acc_prop->at("ID_4_5757B32647BAE263266259B8A7DFFFC1")->value; auto acc_styles = acc_prop->at("Styles_7_91DEB0F24E24D13FC9472882C11D0DFD"); for(UnsignedInt k = 0; k < acc_styles->items.size(); k++) { accessory.styles[k] = acc_styles->at(k)->value; } auto rel_pos_prop = acc_prop->at("RelativePosition_14_BE8FB2A94074F34B3EDA6683B227D3A1"); accessory.relativePosition = Vector3{rel_pos_prop->x, rel_pos_prop->y, rel_pos_prop->z}; auto rel_pos_offset_prop = acc_prop->at("RelativePositionOffset_15_98FD0CE74E44BBAFC2D46FB4CA4E0ED6"); accessory.relativePositionOffset = Vector3{rel_pos_offset_prop->x, rel_pos_offset_prop->y, rel_pos_offset_prop->z}; auto rel_rot_prop = acc_prop->at("RelativeRotation_20_C78C73274E6E78E7878F8C98ECA342C0"); accessory.relativeRotation = Vector3{rel_rot_prop->x, rel_rot_prop->y, rel_rot_prop->z}; auto rel_rot_offset_prop = acc_prop->at("RelativeRotationOffset_21_E07FA0EC46728B7BA763C6861249ABAA"); accessory.relativeRotationOffset = Vector3{rel_rot_offset_prop->x, rel_rot_offset_prop->y, rel_rot_offset_prop->z}; auto local_scale_prop = acc_prop->at("LocalScale_24_DC2D93A742A41A46E7E61D988F15ED53"); accessory.localScale = Vector3{local_scale_prop->x, local_scale_prop->y, local_scale_prop->z}; } } } } auto Mass::writeArmourPart(UnsignedLong index) -> bool { if(index > _armour.parts.size()) { return false; } auto unit_data = _mass->at("UnitData"); auto armour_array = unit_data->at("Armor_10_12E266C44116DDAF57E99ABB575A4B3C"); auto part_prop = armour_array->at(index); auto& part = _armour.parts[index]; if(part_prop->at("Slot_3_408BA56F4C9605C7E805CF91B642249C")->enumValue != part.slot) { return false; } part_prop->at("ID_5_ACD101864D3481DE96EDACACC09BDD25")->value = part.id; auto part_styles = part_prop->at("Styles_47_3E31870441DFD7DB8BEE5C85C26B365B"); for(UnsignedInt i = 0; i < part.styles.size(); i++) { part_styles->at(i)->value = part.styles[i]; } auto decals_array = part_prop->at("Decals_42_F358794A4F18497970F56BA9627D3603"); for(UnsignedInt i = 0; i < decals_array->items.size(); i++) { auto decal_prop = decals_array->at(i); auto& decal = part.decals[i]; decal_prop->at("ID_3_694C0B35404D8A3168AEC89026BC8CF9")->value = decal.id; auto colour_prop = decal_prop->at("Color_8_1B0B9D2B43DA6AAB9FA549B374D3E606"); colour_prop->r = decal.colour.r(); colour_prop->g = decal.colour.g(); colour_prop->b = decal.colour.b(); colour_prop->a = decal.colour.a(); auto pos_prop = decal_prop->at("Position_41_022C8FE84E1AAFE587261E88F2C72250"); pos_prop->x = decal.position.x(); pos_prop->y = decal.position.y(); pos_prop->z = decal.position.z(); auto u_prop = decal_prop->at("UAxis_37_EBEB715F45491AECACCC07A1AE4646D1"); u_prop->x = decal.uAxis.x(); u_prop->y = decal.uAxis.y(); u_prop->z = decal.uAxis.z(); auto v_prop = decal_prop->at("VAxis_39_C31EB2664EE202CAECFBBB84100B5E35"); v_prop->x = decal.vAxis.x(); v_prop->y = decal.vAxis.y(); v_prop->z = decal.vAxis.z(); auto offset_prop = decal_prop->at("Offset_29_B02BBBB74FC60F5EDBEBAB8020738020"); offset_prop->x = decal.offset.x(); offset_prop->y = decal.offset.y(); decal_prop->at("Scale_32_959D1C2747AFD8D62808468235CBBA40")->value = decal.scale; decal_prop->at("Rotation_27_12D7C314493D203D5C2326A03C5F910F")->value = decal.rotation; decal_prop->at("Flip_35_CECCFB184CCD9412BD93FE9A8B656BE1")->value = decal.flip; decal_prop->at("Wrap_43_A7C68CDF4A92AF2ECDA53F953EE7CA62")->value = decal.wrap; } if(!_demo) { auto accs_array = part_prop->at("Accessories_52_D902DD4241FA0050C2529596255153F3"); for(UnsignedInt i = 0; i < accs_array->items.size(); i++) { auto acc_prop = accs_array->at(i); auto& accessory = part.accessories[i]; acc_prop->at("AttachIndex_2_4AFCF6024E4BA7426C6B9F80B8179D20")->value = accessory.attachIndex; acc_prop->at("ID_4_5757B32647BAE263266259B8A7DFFFC1")->value = accessory.id; auto acc_styles = acc_prop->at("Styles_7_91DEB0F24E24D13FC9472882C11D0DFD"); for(UnsignedInt j = 0; j < acc_styles->items.size(); j++) { acc_styles->at(j)->value = accessory.styles[j]; } auto rel_pos_prop = acc_prop->at("RelativePosition_14_BE8FB2A94074F34B3EDA6683B227D3A1"); rel_pos_prop->x = accessory.relativePosition.x(); rel_pos_prop->y = accessory.relativePosition.y(); rel_pos_prop->z = accessory.relativePosition.z(); auto rel_pos_offset_prop = acc_prop->at("RelativePositionOffset_15_98FD0CE74E44BBAFC2D46FB4CA4E0ED6"); rel_pos_offset_prop->x = accessory.relativePositionOffset.x(); rel_pos_offset_prop->y = accessory.relativePositionOffset.y(); rel_pos_offset_prop->z = accessory.relativePositionOffset.z(); auto rel_rot_prop = acc_prop->at("RelativeRotation_20_C78C73274E6E78E7878F8C98ECA342C0"); rel_rot_prop->x = accessory.relativeRotation.x(); rel_rot_prop->y = accessory.relativeRotation.y(); rel_rot_prop->z = accessory.relativeRotation.z(); auto rel_rot_offset_prop = acc_prop->at("RelativeRotationOffset_21_E07FA0EC46728B7BA763C6861249ABAA"); rel_rot_offset_prop->x = accessory.relativeRotationOffset.x(); rel_rot_offset_prop->y = accessory.relativeRotationOffset.y(); rel_rot_offset_prop->z = accessory.relativeRotationOffset.z(); auto local_scale_prop = acc_prop->at("LocalScale_24_DC2D93A742A41A46E7E61D988F15ED53"); local_scale_prop->x = accessory.localScale.x(); local_scale_prop->y = accessory.localScale.y(); local_scale_prop->z = accessory.localScale.z(); } } return _mass->saveToFile(); } auto Mass::armourCustomStyles() -> Containers::StaticArrayView<16, CustomStyle> { return _armour.customStyles; } void Mass::getArmourCustomStyles() { auto unit_data = _mass->at("UnitData"); if(!unit_data) { _state = State::Invalid; return; } auto armour_styles = unit_data->at("ArmorStyle_42_E2F6AC3647788CB366BD469B3B7E899E"); if(!armour_styles) { _state = State::Invalid; return; } if(armour_styles->items.size() != 16) { _state = State::Invalid; return; } for(UnsignedInt i = 0; i < armour_styles->items.size(); i++) { auto style_prop = armour_styles->at(i); CustomStyle style; style.name = style_prop->at("Name_27_1532115A46EF2B2FA283908DF561A86B")->value; auto colour_prop = style_prop->at("Color_5_F0D383DF40474C9464AE48A0984A212E"); style.colour = Color4{colour_prop->r, colour_prop->g, colour_prop->b, colour_prop->a}; style.metallic = style_prop->at("Metallic_10_0A4CD1E4482CBF41CA61D0A856DE90B9")->value; style.gloss = style_prop->at("Gloss_11_9769599842CC275A401C4282A236E240")->value; style.glow = colour_prop->a == 0.0f ? false : true; style.patternId = style_prop->at("PatternID_14_516DB85641DAF8ECFD2920BE2BDF1311")->value; style.opacity = style_prop->at("Opacity_30_53BD060B4DFCA1C92302D6A0F7831131")->value; style.offset = Vector2{ style_prop->at("OffsetX_23_70FC2E814C64BBB82452748D2AF9CD48")->value, style_prop->at("OffsetY_24_5E1F866C4C054D9B2EE337ADC180C17F")->value }; style.rotation = style_prop->at("Rotation_25_EC2DFAD84AD0A6BD3FA841ACD52EDD6D")->value; style.scale = style_prop->at("Scale_26_19DF0708409262183E1247B317137671")->value; _armour.customStyles[i] = std::move(style); } } auto Mass::writeArmourCustomStyle(UnsignedLong index) -> bool { if(index > _armour.customStyles.size()) { return false; } return setCustomStyle(_armour.customStyles[index], index, "ArmorStyle_42_E2F6AC3647788CB366BD469B3B7E899E"); } auto Mass::meleeWeapons() -> Containers::StaticArrayView<8, Weapon> { return _weapons.melee; } void Mass::getMeleeWeapons() { getWeaponType("WeaponCC_22_0BBEC58C4A0EA1DB9E037B9339EE26A7", _weapons.melee); } auto Mass::shields() -> Containers::StaticArrayView<1, Weapon> { return _weapons.shields; } void Mass::getShields() { getWeaponType("Shield_53_839BFD7945481BAEA3E43A9C5CA8E92E", _weapons.shields); } auto Mass::bulletShooters() -> Containers::StaticArrayView<4, Weapon> { return _weapons.bulletShooters; } void Mass::getBulletShooters() { getWeaponType("WeaponBS_35_6EF6E0104FD7A138DF47F88CB57A83ED", _weapons.bulletShooters); } auto Mass::energyShooters() -> Containers::StaticArrayView<4, Weapon> { return _weapons.energyShooters; } void Mass::getEnergyShooters() { getWeaponType("WeaponES_37_1A295D544528623880A0B1AC2C7DEE99", _weapons.energyShooters); } auto Mass::bulletLaunchers() -> Containers::StaticArrayView<4, Weapon> { return _weapons.bulletLaunchers; } void Mass::getBulletLaunchers() { getWeaponType("WeaponBL_36_5FD7C41E4613A75B44AB0E90B362846E", _weapons.bulletLaunchers); } auto Mass::energyLaunchers() -> Containers::StaticArrayView<4, Weapon> { return _weapons.energyLaunchers; } void Mass::getEnergyLaunchers() { getWeaponType("WeaponEL_38_9D23F3884ACA15902C9E6CA6E4995995", _weapons.energyLaunchers); } auto Mass::globalStyles() -> Containers::StaticArrayView<16, CustomStyle> { return _globalStyles; } void Mass::getGlobalStyles() { auto unit_data = _mass->at("UnitData"); if(!unit_data) { _state = State::Invalid; return; } auto global_styles = unit_data->at("GlobalStyles_57_6A681C114035241F7BDAAE9B43A8BF1B"); if(!global_styles) { _state = State::Invalid; return; } if(global_styles->items.size() != 16) { _state = State::Invalid; return; } for(UnsignedInt i = 0; i < global_styles->items.size(); i++) { auto style_prop = global_styles->at(i); CustomStyle style; style.name = style_prop->at("Name_27_1532115A46EF2B2FA283908DF561A86B")->value; auto colour_prop = style_prop->at("Color_5_F0D383DF40474C9464AE48A0984A212E"); style.colour = Color4{colour_prop->r, colour_prop->g, colour_prop->b, colour_prop->a}; style.metallic = style_prop->at("Metallic_10_0A4CD1E4482CBF41CA61D0A856DE90B9")->value; style.gloss = style_prop->at("Gloss_11_9769599842CC275A401C4282A236E240")->value; style.glow = colour_prop->a == 0.0f ? false : true; style.patternId = style_prop->at("PatternID_14_516DB85641DAF8ECFD2920BE2BDF1311")->value; style.opacity = style_prop->at("Opacity_30_53BD060B4DFCA1C92302D6A0F7831131")->value; style.offset = Vector2{ style_prop->at("OffsetX_23_70FC2E814C64BBB82452748D2AF9CD48")->value, style_prop->at("OffsetY_24_5E1F866C4C054D9B2EE337ADC180C17F")->value }; style.rotation = style_prop->at("Rotation_25_EC2DFAD84AD0A6BD3FA841ACD52EDD6D")->value; style.scale = style_prop->at("Scale_26_19DF0708409262183E1247B317137671")->value; _globalStyles[i] = std::move(style); } } auto Mass::writeGlobalStyle(UnsignedLong index) -> bool { if(index > _globalStyles.size()) { return false; } return setCustomStyle(_globalStyles[index], index, "GlobalStyles_57_6A681C114035241F7BDAAE9B43A8BF1B"); } auto Mass::updateSteamId(const std::string& steam_id) -> bool { _steamId = steam_id; auto account = _mass->at("Account"); if(!account) { _state = State::Invalid; return false; } account->value = steam_id; return _mass->saveToFile(); } auto Mass::setCustomStyle(const CustomStyle& style, UnsignedLong index, const char* prop_name) -> bool { auto unit_data = _mass->at("UnitData"); if(!unit_data) { _state = State::Invalid; return false; } auto frame_styles = unit_data->at(prop_name); if(!frame_styles) { _state = State::Invalid; return false; } auto style_prop = frame_styles->at(index); style_prop->at("Name_27_1532115A46EF2B2FA283908DF561A86B")->value = style.name; auto colour_prop = style_prop->at("Color_5_F0D383DF40474C9464AE48A0984A212E"); colour_prop->r = style.colour.r(); colour_prop->g = style.colour.g(); colour_prop->b = style.colour.b(); colour_prop->a = style.glow ? 1.0f : 0.0f; style_prop->at("Metallic_10_0A4CD1E4482CBF41CA61D0A856DE90B9")->value = style.metallic; style_prop->at("Gloss_11_9769599842CC275A401C4282A236E240")->value = style.gloss; style_prop->at("PatternID_14_516DB85641DAF8ECFD2920BE2BDF1311")->value = style.patternId; style_prop->at("Opacity_30_53BD060B4DFCA1C92302D6A0F7831131")->value = style.opacity; style_prop->at("OffsetX_23_70FC2E814C64BBB82452748D2AF9CD48")->value = style.offset.x(); style_prop->at("OffsetY_24_5E1F866C4C054D9B2EE337ADC180C17F")->value = style.offset.y(); style_prop->at("Rotation_25_EC2DFAD84AD0A6BD3FA841ACD52EDD6D")->value = style.rotation; style_prop->at("Scale_26_19DF0708409262183E1247B317137671")->value = style.scale; return _mass->saveToFile(); } void Mass::getWeaponType(const char* prop_name, Containers::ArrayView weapon_array) { auto unit_data = _mass->at("UnitData"); if(!unit_data) { _state = State::Invalid; return; } auto prop = unit_data->at(prop_name); if(!prop) { _state = State::Invalid; return; } if(prop->items.size() != weapon_array.size()) { _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")->value; weapon.type = weapon_prop->at("Type_2_35ABA8C3406F8D9BBF14A89CD6BCE976")->enumValue; auto parts_prop = weapon_prop->at("Element_6_8E4617CC4B2C1F1490435599784EC6E0"); 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")->value; auto part_styles = part_prop->at("Styles_17_994C97C34A90667BE5B716BFD0B97588"); 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"); if(part_decals->items.size() != 8) { _demo = true; part.demoDecals = part_decals->items.size(); } for(UnsignedInt k = 0; k < part_decals->items.size(); k++) { auto decal_prop = part_decals->at(k); auto& decal = part.decals[k]; decal.id = decal_prop->at("ID_3_694C0B35404D8A3168AEC89026BC8CF9")->value; auto colour_prop = decal_prop->at("Color_8_1B0B9D2B43DA6AAB9FA549B374D3E606"); decal.colour = Color4{colour_prop->r, colour_prop->g, colour_prop->b, colour_prop->a}; auto pos_prop = decal_prop->at("Position_41_022C8FE84E1AAFE587261E88F2C72250"); decal.position = Vector3{pos_prop->x, pos_prop->y, pos_prop->z}; auto u_prop = decal_prop->at("UAxis_37_EBEB715F45491AECACCC07A1AE4646D1"); decal.uAxis = Vector3{u_prop->x, u_prop->y, u_prop->z}; auto v_prop = decal_prop->at("VAxis_39_C31EB2664EE202CAECFBBB84100B5E35"); decal.vAxis = Vector3{v_prop->x, v_prop->y, v_prop->z}; auto offset_prop = decal_prop->at("Offset_29_B02BBBB74FC60F5EDBEBAB8020738020"); decal.offset = Vector2{offset_prop->x, offset_prop->y}; decal.scale = decal_prop->at("Scale_32_959D1C2747AFD8D62808468235CBBA40")->value; decal.rotation = decal_prop->at("Rotation_27_12D7C314493D203D5C2326A03C5F910F")->value; decal.flip = decal_prop->at("Flip_35_CECCFB184CCD9412BD93FE9A8B656BE1")->value; decal.wrap = decal_prop->at("Wrap_43_A7C68CDF4A92AF2ECDA53F953EE7CA62")->value; } if(!_demo) { auto part_accs = part_prop->at("Accessories_21_3878DE8B4ED0EA0DB725E98BCDC20E0C"); if(!part_accs) { _demo = true; continue; } if(part_accs->items.size() != 8) { _state = State::Invalid; return; } for(UnsignedInt k = 0; k < part_accs->items.size(); k++) { auto acc_prop = part_accs->at(k); auto& accessory = part.accessories[k]; accessory.attachIndex = acc_prop->at("AttachIndex_2_4AFCF6024E4BA7426C6B9F80B8179D20")->value; accessory.id = acc_prop->at("ID_4_5757B32647BAE263266259B8A7DFFFC1")->value; auto acc_styles = acc_prop->at("Styles_7_91DEB0F24E24D13FC9472882C11D0DFD"); for(UnsignedInt l = 0; l < acc_styles->items.size(); l++) { accessory.styles[l] = acc_styles->at(l)->value; } auto rel_pos_prop = acc_prop->at("RelativePosition_14_BE8FB2A94074F34B3EDA6683B227D3A1"); accessory.relativePosition = Vector3{rel_pos_prop->x, rel_pos_prop->y, rel_pos_prop->z}; auto rel_pos_offset_prop = acc_prop->at("RelativePositionOffset_15_98FD0CE74E44BBAFC2D46FB4CA4E0ED6"); accessory.relativePositionOffset = Vector3{rel_pos_offset_prop->x, rel_pos_offset_prop->y, rel_pos_offset_prop->z}; auto rel_rot_prop = acc_prop->at("RelativeRotation_20_C78C73274E6E78E7878F8C98ECA342C0"); accessory.relativeRotation = Vector3{rel_rot_prop->x, rel_rot_prop->y, rel_rot_prop->z}; auto rel_rot_offset_prop = acc_prop->at("RelativeRotationOffset_21_E07FA0EC46728B7BA763C6861249ABAA"); accessory.relativeRotationOffset = Vector3{rel_rot_offset_prop->x, rel_rot_offset_prop->y, rel_rot_offset_prop->z}; auto local_scale_prop = acc_prop->at("LocalScale_24_DC2D93A742A41A46E7E61D988F15ED53"); accessory.localScale = Vector3{local_scale_prop->x, local_scale_prop->y, local_scale_prop->z}; } } } } }