// 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 #include #include #include #include #include #include "../UESaveFile/Types/ArrayProperty.h" #include "../UESaveFile/Types/ResourceItemValue.h" #include "../UESaveFile/Types/IntProperty.h" #include "../UESaveFile/Types/StringProperty.h" #include "Profile.h" using namespace Corrade; using namespace Containers::Literals; Profile::Profile(Containers::StringView path): _profile(path) { if(!_profile.valid()) { _lastError = _profile.lastError(); return; } _filename = Utility::Path::split(path).second(); if(_filename.hasPrefix("Demo"_s)) { _type = ProfileType::Demo; } else { _type = ProfileType::FullGame; } auto account_prop = _profile.at("Account"_s); if(!account_prop) { _lastError = "Couldn't find an account ID in "_s + _filename; _valid = false; return; } _account = account_prop->value; if(_account.hasPrefix("PMCSlot"_s)) { _version = ProfileVersion::Normal; } else { _version = ProfileVersion::Legacy; } refreshValues(); } auto Profile::valid() const -> bool { return _valid; } auto Profile::lastError() const -> Containers::StringView { return _lastError; } auto Profile::filename() const -> Containers::StringView { return _filename; } auto Profile::type() const -> ProfileType { return _type; } auto Profile::version() const -> ProfileVersion { return _version; } auto Profile::account() const -> Containers::StringView { return _account; } void Profile::refreshValues() { if(!_profile.reloadData()) { _lastError = _profile.lastError(); _valid = false; return; } auto name_prop = _profile.at("CompanyName"_s); if(!name_prop) { _lastError = "No company name in "_s + _filename; _valid = false; return; } _name = name_prop->value; auto prop = _profile.at("ActiveFrameSlot"_s); _activeFrameSlot = prop ? prop->value : 0; prop = _profile.at("Credit"_s); _credits = prop ? prop->value : 0; prop = _profile.at("StoryProgress"_s); _storyProgress = prop ? prop->value : 0; prop = _profile.at("LastMissionID"_s); _lastMissionId = prop ? prop->value : 0; _verseSteel = getResource("ResourceMaterial"_s, VerseSteel); _undinium = getResource("ResourceMaterial"_s, Undinium); _necriumAlloy = getResource("ResourceMaterial"_s, NecriumAlloy); _lunarite = getResource("ResourceMaterial"_s, Lunarite); _asterite = getResource("ResourceMaterial"_s, Asterite); _ednil = getResource("ResourceMaterial"_s, Ednil); _nuflalt = getResource("ResourceMaterial"_s, Nuflalt); _aurelene = getResource("ResourceMaterial"_s, Aurelene); _soldus = getResource("ResourceMaterial"_s, Soldus); _synthesisedN = getResource("ResourceMaterial"_s, SynthesisedN); _alcarbonite = getResource("ResourceMaterial"_s, Alcarbonite); _keriphene = getResource("ResourceMaterial"_s, Keriphene); _nitinolCM = getResource("ResourceMaterial"_s, NitinolCM); _quarkium = getResource("ResourceMaterial"_s, Quarkium); _alterene = getResource("ResourceMaterial"_s, Alterene); _mixedComposition = getResource("ResourceQuarkData"_s, MixedComposition); _voidResidue = getResource("ResourceQuarkData"_s, VoidResidue); _muscularConstruction = getResource("ResourceQuarkData"_s, MuscularConstruction); _mineralExoskeletology = getResource("ResourceQuarkData"_s, MineralExoskeletology); _carbonisedSkin = getResource("ResourceQuarkData"_s, CarbonisedSkin); _valid = true; } auto Profile::companyName() const -> Containers::StringView { return _name; } auto Profile::renameCompany(Containers::StringView new_name) -> bool { auto name_prop = _profile.at("CompanyName"_s); if(!name_prop) { _lastError = "No company name in "_s + _filename; _valid = false; return false; } name_prop->value = new_name; if(!_profile.saveToFile()) { _lastError = _profile.lastError(); return false; } return true; } auto Profile::activeFrameSlot() const -> Int { return _activeFrameSlot; } auto Profile::credits() const -> Int { return _credits; } auto Profile::setCredits(Int amount) -> bool { auto credits_prop = _profile.at("Credit"_s); if(!credits_prop) { credits_prop = new IntProperty; credits_prop->name.emplace("Credit"_s); _profile.appendProperty(IntProperty::ptr{credits_prop}); } credits_prop->value = amount; if(!_profile.saveToFile()) { _lastError = _profile.lastError(); return false; } return true; } auto Profile::storyProgress() const -> Int { return _storyProgress; } auto Profile::setStoryProgress(Int progress) -> bool { auto story_progress_prop = _profile.at("StoryProgress"_s); if(!story_progress_prop) { story_progress_prop = new IntProperty; story_progress_prop->name.emplace("StoryProgress"_s); _profile.appendProperty(IntProperty::ptr{story_progress_prop}); } story_progress_prop->value = progress; if(!_profile.saveToFile()) { _lastError = _profile.lastError(); return false; } return true; } auto Profile::lastMissionId() const -> Int { return _lastMissionId; } auto Profile::verseSteel() const -> Int { return _verseSteel; } auto Profile::setVerseSteel(Int amount) -> bool { return setResource("ResourceMaterial"_s, VerseSteel, amount); } auto Profile::undinium() const -> Int { return _undinium; } auto Profile::setUndinium(Int amount) -> bool { return setResource("ResourceMaterial"_s, Undinium, amount); } auto Profile::necriumAlloy() const -> Int { return _necriumAlloy; } auto Profile::setNecriumAlloy(Int amount) -> bool { return setResource("ResourceMaterial"_s, NecriumAlloy, amount); } auto Profile::lunarite() const -> Int { return _lunarite; } auto Profile::setLunarite(Int amount) -> bool { return setResource("ResourceMaterial"_s, Lunarite, amount); } auto Profile::asterite() const -> Int { return _asterite; } auto Profile::setAsterite(Int amount) -> bool { return setResource("ResourceMaterial"_s, Asterite, amount); } auto Profile::ednil() const -> Int { return _ednil; } auto Profile::setEdnil(Int amount) -> bool { return setResource("ResourceMaterial"_s, Ednil, amount); } auto Profile::nuflalt() const -> Int { return _nuflalt; } auto Profile::setNuflalt(Int amount) -> bool { return setResource("ResourceMaterial"_s, Nuflalt, amount); } auto Profile::aurelene() const -> Int { return _aurelene; } auto Profile::setAurelene(Int amount) -> bool { return setResource("ResourceMaterial"_s, Aurelene, amount); } auto Profile::soldus() const -> Int { return _soldus; } auto Profile::setSoldus(Int amount) -> bool { return setResource("ResourceMaterial"_s, Soldus, amount); } auto Profile::synthesisedN() const -> Int { return _synthesisedN; } auto Profile::setSynthesisedN(Int amount) -> bool { return setResource("ResourceMaterial"_s, SynthesisedN, amount); } auto Profile::alcarbonite() const -> Int { return _alcarbonite; } auto Profile::setAlcarbonite(Int amount) -> bool { return setResource("ResourceMaterial"_s, Alcarbonite, amount); } auto Profile::keriphene() const -> Int { return _keriphene; } auto Profile::setKeriphene(Int amount) -> bool { return setResource("ResourceMaterial"_s, Keriphene, amount); } auto Profile::nitinolCM() const -> Int { return _nitinolCM; } auto Profile::setNitinolCM(Int amount) -> bool { return setResource("ResourceMaterial"_s, NitinolCM, amount); } auto Profile::quarkium() const -> Int { return _quarkium; } auto Profile::setQuarkium(Int amount) -> bool { return setResource("ResourceMaterial"_s, Quarkium, amount); } auto Profile::alterene() const -> Int { return _alterene; } auto Profile::setAlterene(Int amount) -> bool { return setResource("ResourceMaterial"_s, Alterene, amount); } auto Profile::mixedComposition() const -> Int { return _mixedComposition; } auto Profile::setMixedComposition(Int amount) -> bool { return setResource("ResourceQuarkData"_s, MixedComposition, amount); } auto Profile::voidResidue() const -> Int { return _voidResidue; } auto Profile::setVoidResidue(Int amount) -> bool { return setResource("ResourceQuarkData"_s, VoidResidue, amount); } auto Profile::muscularConstruction() const -> Int { return _muscularConstruction; } auto Profile::setMuscularConstruction(Int amount) -> bool { return setResource("ResourceQuarkData"_s, MuscularConstruction, amount); } auto Profile::mineralExoskeletology() const -> Int { return _mineralExoskeletology; } auto Profile::setMineralExoskeletology(Int amount) -> bool { return setResource("ResourceQuarkData"_s, MineralExoskeletology, amount); } auto Profile::carbonisedSkin() const -> Int { return _carbonisedSkin; } auto Profile::setCarbonisedSkin(Int amount) -> bool { return setResource("ResourceQuarkData"_s, CarbonisedSkin, amount); } auto Profile::getResource(Containers::StringView container, MaterialID id) -> Int { auto mats_prop = _profile.at(container); if(!mats_prop) { return 0; } auto predicate = [&id](UnrealPropertyBase::ptr& prop){ auto res_prop = static_cast(prop.get()); return res_prop->id == id; }; auto it = std::find_if(mats_prop->items.begin(), mats_prop->items.end(), predicate); return it != mats_prop->items.end() ? static_cast(it->get())->quantity : 0; } auto Profile::setResource(Containers::StringView container, MaterialID id, Int amount) -> bool { auto mats_prop = _profile.at(container); if(!mats_prop) { _lastError = "Couldn't find "_s + container + " in "_s + _filename; _valid = false; return false; } auto predicate = [&id](UnrealPropertyBase::ptr& prop){ auto res_prop = static_cast(prop.get()); return res_prop->id == id; }; auto it = std::find_if(mats_prop->items.begin(), mats_prop->items.end(), predicate); ResourceItemValue* res_prop; if(it == mats_prop->items.end()) { res_prop = new ResourceItemValue; res_prop->id = id; ResourceItemValue::ptr prop{res_prop}; arrayAppend(mats_prop->items, std::move(prop)); } else { res_prop = static_cast(it->get()); } res_prop->quantity = amount; if(!_profile.saveToFile()) { _lastError = _profile.lastError(); return false; } return true; }