MassBuilderSaveTool/src/Profile/Profile.cpp

353 lines
9.4 KiB
C++

// 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 <https://www.gnu.org/licenses/>.
#include <algorithm>
#include <Corrade/Containers/Array.h>
#include <Corrade/Containers/StaticArray.h>
#include <Corrade/Utility/Directory.h>
#include <Corrade/Utility/FormatStl.h>
#include <Corrade/Utility/String.h>
#include "../UESaveFile/Types/ArrayProperty.h"
#include "../UESaveFile/Types/ResourceItemValue.h"
#include "../UESaveFile/Types/IntProperty.h"
#include "../UESaveFile/Types/StringProperty.h"
#include "Profile.h"
#include "Locators.h"
using namespace Corrade;
Profile::Profile(const std::string& path):
_profile(path)
{
_profileDirectory = Utility::Directory::path(path);
_filename = Utility::Directory::filename(path);
if(Utility::String::beginsWith(_filename, "Demo")) {
_type = ProfileType::Demo;
}
else {
_type = ProfileType::FullGame;
}
_steamId = Utility::String::ltrim(Utility::String::rtrim(_filename, ".sav"), (_type == ProfileType::Demo ? "Demo" : "") + std::string{"Profile"});
_valid = _profile.valid();
}
auto Profile::valid() const -> bool {
return _valid;
}
auto Profile::lastError() const -> std::string const& {
return _lastError;
}
auto Profile::filename() const -> std::string const& {
return _filename;
}
auto Profile::type() const -> ProfileType {
return _type;
}
auto Profile::steamId() const -> std::string const& {
return _steamId;
}
void Profile::refreshValues() {
_profile.reloadData();
}
auto Profile::companyName() -> std::string const& {
return _profile.at<StringProperty>("CompanyName")->value;
}
auto Profile::renameCompany(const std::string& new_name) -> bool {
auto name_prop = _profile.at<StringProperty>("CompanyName");
name_prop->value = new_name;
if(!_profile.saveToFile()) {
_lastError = "Couldn't save the profile.";
return false;
}
return true;
}
auto Profile::activeFrameSlot() -> Int {
auto active_frame_slot_prop = _profile.at<IntProperty>("ActiveFrameSlot");
return active_frame_slot_prop ? active_frame_slot_prop->value : 0;
}
auto Profile::credits() -> Int {
auto credits_prop = _profile.at<IntProperty>("Credit");
return credits_prop ? credits_prop->value : 0;
}
auto Profile::setCredits(Int amount) -> bool {
auto credits_prop = _profile.at<IntProperty>("Credit");
if(!credits_prop) {
credits_prop = new IntProperty;
_profile.appendProperty(IntProperty::ptr{credits_prop});
}
credits_prop->value = amount;
if(!_profile.saveToFile()) {
_lastError = "Couldn't save the profile.";
return false;
}
return true;
}
auto Profile::storyProgress() -> Int {
auto story_progress_prop = _profile.at<IntProperty>("StoryProgress");
return story_progress_prop ? story_progress_prop->value : 0;
}
auto Profile::setStoryProgress(Int progress) -> bool {
auto story_progress_prop = _profile.at<IntProperty>("StoryProgress");
if(!story_progress_prop) {
story_progress_prop = new IntProperty;
_profile.appendProperty(IntProperty::ptr{story_progress_prop});
}
story_progress_prop->value = progress;
if(!_profile.saveToFile()) {
_lastError = "Couldn't save the profile.";
return false;
}
return true;
}
auto Profile::lastMissionId() -> Int {
auto last_mission_id_prop = _profile.at<IntProperty>("LastMissionID");
return last_mission_id_prop ? last_mission_id_prop->value : 0;
}
auto Profile::verseSteel() -> Int {
return resource("ResourceMaterial", 0xC3500);
}
auto Profile::setVerseSteel(Int amount) -> bool {
return setResource("ResourceMaterial", 0xC3500, amount);
}
auto Profile::undinium() -> Int {
return resource("ResourceMaterial", 0xC3501);
}
auto Profile::setUndinium(Int amount) -> bool {
return setResource("ResourceMaterial", 0xC3501, amount);
}
auto Profile::necriumAlloy() -> Int {
return resource("ResourceMaterial", 0xC3502);
}
auto Profile::setNecriumAlloy(Int amount) -> bool {
return setResource("ResourceMaterial", 0xC3502, amount);
}
auto Profile::lunarite() -> Int {
return resource("ResourceMaterial", 0xC3503);
}
auto Profile::setLunarite(Int amount) -> bool {
return setResource("ResourceMaterial", 0xC3503, amount);
}
auto Profile::asterite() -> Int {
return resource("ResourceMaterial", 0xC3504);
}
auto Profile::setAsterite(Int amount) -> bool {
return setResource("ResourceMaterial", 0xC3504, amount);
}
auto Profile::ednil() -> Int {
return resource("ResourceMaterial", 0xC350A);
}
auto Profile::setEdnil(Int amount) -> bool {
return setResource("ResourceMaterial", 0xC350A, amount);
}
auto Profile::nuflalt() -> Int {
return resource("ResourceMaterial", 0xC350B);
}
auto Profile::setNuflalt(Int amount) -> bool {
return setResource("ResourceMaterial", 0xC350B, amount);
}
auto Profile::aurelene() -> Int {
return resource("ResourceMaterial", 0xC350C);
}
auto Profile::setAurelene(Int amount) -> bool {
return setResource("ResourceMaterial", 0xC350C, amount);
}
auto Profile::soldus() -> Int {
return resource("ResourceMaterial", 0xC350D);
}
auto Profile::setSoldus(Int amount) -> bool {
return setResource("ResourceMaterial", 0xC350D, amount);
}
auto Profile::synthesizedN() -> Int {
return resource("ResourceMaterial", 0xC350E);
}
auto Profile::setSynthesizedN(Int amount) -> bool {
return setResource("ResourceMaterial", 0xC350E, amount);
}
auto Profile::alcarbonite() -> Int {
return resource("ResourceMaterial", 0xC3514);
}
auto Profile::setAlcarbonite(Int amount) -> bool {
return setResource("ResourceMaterial", 0xC3514, amount);
}
auto Profile::keriphene() -> Int {
return resource("ResourceMaterial", 0xC3515);
}
auto Profile::setKeriphene(Int amount) -> bool {
return setResource("ResourceMaterial", 0xC3515, amount);
}
auto Profile::nitinolCM() -> Int {
return resource("ResourceMaterial", 0xC3516);
}
auto Profile::setNitinolCM(Int amount) -> bool {
return setResource("ResourceMaterial", 0xC3516, amount);
}
auto Profile::quarkium() -> Int {
return resource("ResourceMaterial", 0xC3517);
}
auto Profile::setQuarkium(Int amount) -> bool {
return setResource("ResourceMaterial", 0xC3517, amount);
}
auto Profile::alterene() -> Int {
return resource("ResourceMaterial", 0xC3518);
}
auto Profile::setAlterene(Int amount) -> bool {
return setResource("ResourceMaterial", 0xC3518, amount);
}
auto Profile::mixedComposition() -> Int {
return resource("ResourceQuarkData", 0xDBBA0);
}
auto Profile::setMixedComposition(Int amount) -> bool {
return setResource("ResourceQuarkData", 0xDBBA0, amount);
}
auto Profile::voidResidue() -> Int {
return resource("ResourceQuarkData", 0xDBBA1);
}
auto Profile::setVoidResidue(Int amount) -> bool {
return setResource("ResourceQuarkData", 0xDBBA1, amount);
}
auto Profile::muscularConstruction() -> Int {
return resource("ResourceQuarkData", 0xDBBA2);
}
auto Profile::setMuscularConstruction(Int amount) -> bool {
return setResource("ResourceQuarkData", 0xDBBA2, amount);
}
auto Profile::mineralExoskeletology() -> Int {
return resource("ResourceQuarkData", 0xDBBA3);
}
auto Profile::setMineralExoskeletology(Int amount) -> bool {
return setResource("ResourceQuarkData", 0xDBBA3, amount);
}
auto Profile::carbonizedSkin() -> Int {
return resource("ResourceQuarkData", 0xDBBA4);
}
auto Profile::setCarbonizedSkin(Int amount) -> bool {
return setResource("ResourceQuarkData", 0xDBBA4, amount);
}
auto Profile::resource(const char* container, Int id) -> Int {
auto mats_prop = _profile.at<ArrayProperty>(container);
static auto predicate = [&id](UnrealPropertyBase::ptr& prop){
auto res_prop = static_cast<ResourceItemValue*>(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<ResourceItemValue*>(it->get())->quantity : 0;
}
auto Profile::setResource(const char* container, Int id, Int amount) -> bool {
auto mats_prop = _profile.at<ArrayProperty>(container);
static auto predicate = [&id](UnrealPropertyBase::ptr& prop){
auto res_prop = static_cast<ResourceItemValue*>(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<ResourceItemValue*>(it->get());
}
res_prop->quantity = amount;
if(!_profile.saveToFile()) {
_lastError = _profile.lastError();
return false;
}
return _profile.saveToFile();
}