From bb6de66b0c3fae45f0bd090131e036325cc8bdbe Mon Sep 17 00:00:00 2001 From: William JCM Date: Wed, 21 Jul 2021 11:30:41 +0200 Subject: [PATCH 01/22] ResearchTree: add basic functionality and some nodes. --- src/CMakeLists.txt | 3 + src/Profile/Profile.cpp | 53 +++++ src/Profile/Profile.h | 15 ++ src/ResearchTree/NodeIDs.h | 94 +++++++++ src/ResearchTree/ResearchTree.cpp | 277 ++++++++++++++++++++++++++ src/ResearchTree/ResearchTree.h | 112 +++++++++++ src/SaveTool/SaveTool.cpp | 3 + src/SaveTool/SaveTool.h | 7 + src/SaveTool/SaveTool_MainManager.cpp | 123 ++++++++++++ 9 files changed, 687 insertions(+) create mode 100644 src/ResearchTree/NodeIDs.h create mode 100644 src/ResearchTree/ResearchTree.cpp create mode 100644 src/ResearchTree/ResearchTree.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 6e206a9..b796823 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -48,6 +48,9 @@ add_executable(MassBuilderSaveTool WIN32 Maps/StoryProgress.h ToastQueue/ToastQueue.h ToastQueue/ToastQueue.cpp + ResearchTree/NodeIDs.h + ResearchTree/ResearchTree.h + ResearchTree/ResearchTree.cpp FontAwesome/IconsFontAwesome5.h FontAwesome/IconsFontAwesome5Brands.h resource.rc diff --git a/src/Profile/Profile.cpp b/src/Profile/Profile.cpp index 46a1819..045d19b 100644 --- a/src/Profile/Profile.cpp +++ b/src/Profile/Profile.cpp @@ -109,6 +109,8 @@ void Profile::refreshValues() { getMuscularConstruction(); getMineralExoskeletology(); getCarbonizedSkin(); + + getEngineUnlocks(); } auto Profile::companyName() const -> std::string const& { @@ -1001,3 +1003,54 @@ auto Profile::setCarbonizedSkin(Int amount) -> bool { return false; } } + +auto Profile::engineInventory() -> Containers::ArrayView { + return _engineInventory; +} + +auto Profile::gearInventory() -> Containers::ArrayView { + return _gearInventory; +} + +void Profile::getEngineUnlocks() { + auto mmap = Utility::Directory::map(Utility::Directory::join(_profileDirectory, _filename)); + + auto iter = std::search(mmap.begin(), mmap.end(), &engine_inventory_locator[0], &engine_inventory_locator[33]); + + if(iter != mmap.end()) { + Int* int_iter = reinterpret_cast(iter + 0x3B); + Int size = *(int_iter++); + + if(size > 0) { + _engineInventory = Containers::Array{DefaultInit, std::size_t(size)}; + std::copy_n(int_iter, size, _engineInventory.data()); + + Utility::Debug{} << "_engineInventory:" << _engineInventory; + + iter = std::search(mmap.begin(), mmap.end(), &gear_inventory_locator[0], &gear_inventory_locator[31]); + + if(iter == mmap.end()) { + return; + } + + int_iter = reinterpret_cast(iter + 0x39); + size = *(int_iter++); + + if(size <= 0) { + return; + } + + _gearInventory = Containers::Array{DefaultInit, std::size_t(size)}; + std::copy_n(int_iter, size, _gearInventory.data()); + + Utility::Debug{} << "_gearInventory:" << _gearInventory; + } + else { + _lastError = "An array can't have a null or negative size."; + Utility::Fatal{EXIT_FAILURE} << _lastError.c_str(); + } + } + else { + _lastError = "The profile save seems to be corrupted or the game didn't release the handle on the file."; + } +} diff --git a/src/Profile/Profile.h b/src/Profile/Profile.h index 63cf5bc..b2c4cff 100644 --- a/src/Profile/Profile.h +++ b/src/Profile/Profile.h @@ -18,6 +18,8 @@ #include +#include + #include using namespace Magnum; @@ -141,6 +143,10 @@ class Profile { auto getCarbonizedSkin() -> Int; auto setCarbonizedSkin(Int amount) -> bool; + auto engineInventory() -> Containers::ArrayView; + auto gearInventory() -> Containers::ArrayView; + void getEngineUnlocks(); + private: std::string _profileDirectory; std::string _filename; @@ -183,4 +189,13 @@ class Profile { Int _muscularConstruction; Int _mineralExoskeletology; Int _carbonizedSkin; + + Containers::Array _engineInventory; + Containers::Array _gearInventory; + + Containers::Array _osInventory; + Containers::Array _moduleInventory; + + Containers::Array _archInventory; + Containers::Array _techInventory; }; diff --git a/src/ResearchTree/NodeIDs.h b/src/ResearchTree/NodeIDs.h new file mode 100644 index 0000000..551f5c7 --- /dev/null +++ b/src/ResearchTree/NodeIDs.h @@ -0,0 +1,94 @@ +#pragma once + +// 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 . + +enum EngineIDs: Int { + // Tier 1 + VerseEngine = 100000, + LoadedEngine = 100020, + MetalPlatings1 = 200000, + HeatTurbines1 = 200040, + Microcontroller1 = 200060, + CombustionController1 = 200020, + + // Tier 2 + ModAlloyEngine = 110000, + ChargedEngine = 110040, + ReinforcedLoadedEngine = 110020, + HeavyImpactsEnabler = 110100, + MetalPlatings2 = 210000, + HeatTurbines2 = 210040, + Microcontroller2 = 210060, + WeaponsCargo1 = 210061, + CombustionController2 = 210020, + PoweredRewiring1 = 210021, + + // Tier 3 + ModSteelEngine, + SuperchargedEngine, + NecriumAlloyEngine, + MetalPlatings3, + HeatTurbines3, + Microcontroller3, + WeaponsCargo2, + CombustionController3, + PoweredRewiring2, + + // Tier 4 + ModLunariteEngine, + ChargedLunariteEngine, + LunariteEngine, + InfusedEngine, + MetalPlatings4, + HeatTurbines4, + Microcontroller4, + WeaponsCargo3, + CombustionController4, + PoweredRewiring3, + ArmouredCargo1, + ArmouredFuelTank1, + ExtraCapacity1, + HighmetalEngine, + PowerRedirector1, + + // Tier 5 + AsteriteCarbonEngine, + ChargedAsteriteEngine, + AsteriteSteelEngine, + MeldedEngine, + MetalPlatings5, + HeatTurbines5, + Microcontroller5, + WeaponsCargo4, + CombustionController5, + PoweredRewiring4, + ArmouredCargo2, + ArmouredFuelTank2, + ExtraCapacity2, + CastHighmetalEngine, + PowerRedirector2, +}; + +enum OSIDs: Int { + // Tier 1 + NeuralOS = 300010, +}; + +enum ArchIDs: Int { + // Tier 1 + StandardFrame = 500099, +}; diff --git a/src/ResearchTree/ResearchTree.cpp b/src/ResearchTree/ResearchTree.cpp new file mode 100644 index 0000000..b23b4e4 --- /dev/null +++ b/src/ResearchTree/ResearchTree.cpp @@ -0,0 +1,277 @@ +// 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 "ResearchTree.h" + +#include "NodeIDs.h" + +//region Node +Node::Node(Node::Type type, const char* name, UnsignedByte tier, UnsignedByte slots, + const char* description, const char* active_effect, const char* passive_effect): + _type{type}, _state{State::Unavailable}, _name{name}, _tier{tier}, _slots{slots}, + _description{description}, _activeEffect{active_effect}, _passiveEffect{passive_effect} +{ + //ctor +} + +auto Node::type() const -> Node::Type { + return _type; +} + +auto Node::state() const -> Node::State { + return _state; +} + +void Node::setState(Node::State state) { + if(_state == state) { + return; + } + + _state = state; + + if(_state == State::Available) { + for(Node* n : _children) { + n->setState(State::Unavailable, NotClicked); + } + } + else if(_state == State::Unlocked) { + for(Node* n : _children) { + n->setState(State::Available, NotClicked); + } + } +} + +auto Node::name() const -> const char* { + return _name; +} + +auto Node::tier() const -> UnsignedByte { + return _tier; +} + +auto Node::slots() const -> UnsignedByte { + return _slots; +} + +auto Node::description() const -> const char* { + return _description; +} + +auto Node::activeEffect() const -> const char* { + return _activeEffect; +} + +auto Node::passiveEffect() const -> const char* { + return _passiveEffect; +} + +auto Node::children() -> Containers::ArrayView { + return _children; +} + +void Node::addChild(Node& child) { + arrayAppend(_children, &child); + child.addParent(*this); +} + +void Node::addParent(Node& parent) { + arrayAppend(_parents, &parent); +} + +void Node::setState(State state, NotClickedT) { + if(_state == state) { + return; + } + + if(state == State::Unavailable) { + for(Node* node : _parents) { + if(node->state() == State::Unlocked) { + return; + } + } + } + else if(state == State::Available && _state == State::Unlocked) { + return; + } + + _state = state; + + if(_state != State::Unlocked) { + for(Node* node : _children) { + node->setState(State::Unavailable, NotClicked); + } + } + else { + for(Node* node : _children) { + node->setState(State::Available, NotClicked); + } + } +} +//endregion + +void ResearchTree::generateEngineTree() { + if(!_engineNodes.empty()) { + return; + } + + _engineNodes.emplace(VerseEngine, Node{Node::Type::Engine, "Verse Engine", 1, 3, + "A basic low-speed engine with great durability.", + "Durability +346, Power +60, Armour +22, Acceleration +75, Magazine load +35, Energy capacity +35", + "Durability +3%"}); + + _engineNodes.emplace(LoadedEngine, Node{Node::Type::Engine, "Loaded Engine", 1, 3, + "An alternate heavier model of engine used to operate a M.A.S.S.", + "Durability +288, Power +84, Armour +14, Acceleration +75, Magazine load +35, Energy capacity +35", + "Power +3%"}); + + _engineNodes.emplace(MetalPlatings1, Node{Node::Type::Gear, "Metal Platings 1", 1, 0, + "Level 1 metal plating that adds durability and armour to your engine.", + "Durability +60, Armour +5, Acceleration -15", ""}); + + _engineNodes.emplace(HeatTurbines1, Node{Node::Type::Gear, "Heat Turbines 1", 1, 0, + "Modified heat turbines to increase speed for a M.A.S.S.", + "Acceleration +75, Fuel capacity +5", ""}); + + _engineNodes.emplace(Microcontroller1, Node{Node::Type::Gear, "Microcontroller 1", 1, 0, + "A microchip that enhances various aspects of a M.A.S.S.", + "Durability +36, Power +1, Armour +11, Magazine load +5, Energy capacity +5, Fuel capacity +3", ""}); + + _engineNodes.emplace(CombustionController1, Node{Node::Type::Gear, "Combustion Controller 1", 1, 0, + "Controlled combustion allows increased power generation through specific ignition.", + "Power +2, Magazine load +10, Energy capacity +10, Acceleration -25", ""}); + + _engineNodes.emplace(ModAlloyEngine, Node{Node::Type::Engine, "Mod. Alloy Engine", 2, 3, + "Built with a modified alloy and able to sustain greater attacks from any enemy.", + "Durability +1152, Power +75, Armour +194, Acceleration +75, Magazine load +40, Energy capacity +40", + "Durability +3%"}); + + _engineNodes.emplace(ChargedEngine, Node{Node::Type::Engine, "Charged Engine", 2, 3, + "Remove most armours to attain more speed and power, and fuel.", + "Durability +960, Power +75, Acceleration +300, Magazine load +40, Energy capacity +40, Fuel capacity +52", + "Acceleration +5"}); + + _engineNodes.emplace(ReinforcedLoadedEngine, Node{Node::Type::Engine, "Reinforced Loaded Engine", 2, 3, + "An upgraded build of the basic model, with reinforced Verse Steel for more strength.", + "Durability +960, Power +105, Armour +130, Acceleration +75, Magazine load +40, Energy capacity +40", + "Power +3%"}); + + _engineNodes.emplace(HeavyImpactsEnabler, Node{Node::Type::Engine, "Heavy Impacts Enabler", 2, 0, + "Enable the usage of Heavy Combos in close combat attacks.", "", ""}); + + _engineNodes.emplace(MetalPlatings2, Node{Node::Type::Gear, "Metal Platings 2", 2, 0, + "Level 2 Metal plating that adds durability and armour to your engine.", + "Durability +180, Armour +41, Acceleration -15", ""}); + + _engineNodes.emplace(HeatTurbines2, Node{Node::Type::Gear, "Heat Turbines 2", 2, 0, + "Level 2 Modified heat turbines to increase speed for a M.A.S.S.", + "Acceleration +75, Fuel capacity +16", ""}); + + _engineNodes.emplace(Microcontroller2, Node{Node::Type::Gear, "Microcontroller 2", 2, 0, + "Level 2 Microchip that enhances various aspects of a M.A.S.S.", + "Durability +108, Power +3, Armour +17, Magazine load +6, Energy capacity +6, Fuel capacity +8", ""}); + + _engineNodes.emplace(WeaponsCargo1, Node{Node::Type::Gear, "Weapons Cargo 1", 2, 0, + "Added another cargo hold for ammo and energy recharger", + "Magazine load +24, Energy capacity +24, Acceleration -40", ""}); + + _engineNodes.emplace(CombustionController2, Node{Node::Type::Gear, "Combustion Controller 2", 2, 0, + "Level 2 Controlled combustion allows increased power generation through specific ignition.", + "Power +5, Magazine load +12, Energy capacity +12, Acceleration -25", ""}); + + _engineNodes.emplace(PoweredRewiring1, Node{Node::Type::Gear, "Powered Rewiring 1", 2, 0, + "Rewiring that efficiently improves power and engine durability.", + "Durability +180, Power +5", ""}); + + _engineNodes.at(VerseEngine).addChild(_engineNodes.at(MetalPlatings1)); + _engineNodes.at(VerseEngine).addChild(_engineNodes.at(HeatTurbines1)); + _engineNodes.at(VerseEngine).addChild(_engineNodes.at(LoadedEngine)); + _engineNodes.at(LoadedEngine).addChild(_engineNodes.at(Microcontroller1)); + _engineNodes.at(LoadedEngine).addChild(_engineNodes.at(CombustionController1)); + _engineNodes.at(MetalPlatings1).addChild(_engineNodes.at(ModAlloyEngine)); + _engineNodes.at(HeatTurbines1).addChild(_engineNodes.at(ChargedEngine)); + _engineNodes.at(Microcontroller1).addChild(_engineNodes.at(ChargedEngine)); + _engineNodes.at(CombustionController1).addChild(_engineNodes.at(ReinforcedLoadedEngine)); + _engineNodes.at(ModAlloyEngine).addChild(_engineNodes.at(MetalPlatings2)); + _engineNodes.at(ModAlloyEngine).addChild(_engineNodes.at(HeatTurbines2)); + _engineNodes.at(ChargedEngine).addChild(_engineNodes.at(HeatTurbines2)); + _engineNodes.at(ChargedEngine).addChild(_engineNodes.at(Microcontroller2)); + _engineNodes.at(ChargedEngine).addChild(_engineNodes.at(WeaponsCargo1)); + _engineNodes.at(ReinforcedLoadedEngine).addChild(_engineNodes.at(CombustionController2)); + _engineNodes.at(ReinforcedLoadedEngine).addChild(_engineNodes.at(PoweredRewiring1)); + _engineNodes.at(ReinforcedLoadedEngine).addChild(_engineNodes.at(HeavyImpactsEnabler)); + + _engineNodes.at(VerseEngine).setState(Node::State::Unlocked); +} + +void ResearchTree::generateOSTree() { + if(!_osNodes.empty()) { + return; + } + + _osNodes.emplace(NeuralOS, Node{Node::Type::OS, "Neural OS", 1, 3, + "Synchronise the links between your nervous system and the M.A.S.S. perfectly.", + "Accuracy +24, Shield +624, Fuel burn rate +200, Magazine reload +24, Energy recharge +66, Shield recover +1620", + "Shield +3%"}); + + _osNodes.at(NeuralOS).setState(Node::State::Unlocked); +} + +void ResearchTree::generateArchTree() { + if(!_archNodes.empty()) { + return; + } + + _archNodes.emplace(StandardFrame, Node{Node::Type::Architect, "Standard Frame", 1, 2, + "The standard frame architecture for mass-produced humanoid robots. It uses the most common technologies and materials.", + "Durability +300, Shield +200, Physical damage +600, Piercing damage +300, Plasma damage +300", + ""}); + + _archNodes.at(StandardFrame).setState(Node::State::Unlocked); +} + +void ResearchTree::readEngineUnlocks(Containers::ArrayView engines, Containers::ArrayView gears) { + if(engines == nullptr || engines.size() == 0) { + Utility::Error{} << "Engines can't be empty"; + } + + for(Int& engine : engines) { + if(_engineNodes.find(engine) != _engineNodes.end()) { + _engineNodes.at(engine).setState(Node::State::Unlocked); + } + } + + if(gears == nullptr || engines.size() == 0) { + return; + } + + for(Int& gear : gears) { + if(_engineNodes.find(gear) != _engineNodes.end()) { + _engineNodes.at(gear).setState(Node::State::Unlocked); + } + } +} + +auto ResearchTree::getEngineRootNode() -> Node& { + return _engineNodes.at(VerseEngine); +} + +auto ResearchTree::getOSRootNode() -> Node& { + return _osNodes.at(NeuralOS); +} + +auto ResearchTree::getArchRootNode() -> Node& { + return _archNodes.at(StandardFrame); +} diff --git a/src/ResearchTree/ResearchTree.h b/src/ResearchTree/ResearchTree.h new file mode 100644 index 0000000..6f488af --- /dev/null +++ b/src/ResearchTree/ResearchTree.h @@ -0,0 +1,112 @@ +#pragma once + +// 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 + +using namespace Corrade; +using namespace Magnum; + +class Node { + public: + enum class Type { + Engine, + Gear, + OS, + Module, + Architect, + Tech + }; + + enum class State { + Unavailable, + Available, + Unlocked + }; + + Node(Type type, const char* name, UnsignedByte tier, UnsignedByte slots, + const char* description, const char* active_effect, const char* passive_effect); + + Node(const Node& other) = delete; + Node& operator=(const Node& other) = delete; + + Node(Node&& other) = default; + Node& operator=(Node&& other) = default; + + auto type() const -> Type; + + auto state() const -> State; + void setState(State state); + + auto name() const -> const char*; + + auto tier() const -> UnsignedByte; + + auto slots() const -> UnsignedByte; + + auto description() const -> const char*; + + auto activeEffect() const -> const char*; + + auto passiveEffect() const -> const char*; + + auto children() -> Containers::ArrayView; + void addChild(Node& child); + + private: + void addParent(Node& parent); + + struct NotClickedT {} NotClicked; + void setState(State state, NotClickedT); + + Type _type; + State _state; + + const char* _name; + UnsignedByte _tier; + UnsignedByte _slots; + const char* _description; + const char* _activeEffect; + const char* _passiveEffect; + + Containers::Array _parents; + Containers::Array _children; +}; + +class ResearchTree { + public: + void generateEngineTree(); + void generateOSTree(); + void generateArchTree(); + + void readEngineUnlocks(Containers::ArrayView engines, Containers::ArrayView gears = nullptr); + + auto getEngineRootNode() -> Node&; + auto getOSRootNode() -> Node&; + auto getArchRootNode() -> Node&; + + private: + using Tree = std::unordered_map; + Tree _engineNodes; + Tree _osNodes; + Tree _archNodes; +}; diff --git a/src/SaveTool/SaveTool.cpp b/src/SaveTool/SaveTool.cpp index e95aff6..69f7eb1 100644 --- a/src/SaveTool/SaveTool.cpp +++ b/src/SaveTool/SaveTool.cpp @@ -188,6 +188,9 @@ void SaveTool::handleFileAction(efsw::WatchID watch_id, case efsw::Actions::Modified: if(filename == _currentProfile->filename()) { _currentProfile->refreshValues(); + if(_tree) { + _tree->readEngineUnlocks(_currentProfile->engineInventory(), _currentProfile->gearInventory()); + } } else if(Utility::String::endsWith(filename, _currentProfile->steamId() + ".sav")) { if(Utility::String::beginsWith(filename, Utility::formatString("{}Unit", _currentProfile->type() == ProfileType::Demo ? "Demo" : ""))) { diff --git a/src/SaveTool/SaveTool.h b/src/SaveTool/SaveTool.h index 7577848..9b9e483 100644 --- a/src/SaveTool/SaveTool.h +++ b/src/SaveTool/SaveTool.h @@ -35,6 +35,9 @@ #include "../ProfileManager/ProfileManager.h" #include "../MassManager/MassManager.h" #include "../ToastQueue/ToastQueue.h" +#include "../ResearchTree/ResearchTree.h" + +class Node; using namespace Corrade; using namespace Magnum; @@ -97,6 +100,8 @@ class SaveTool: public Platform::Sdl2Application, public efsw::FileWatchListener auto drawRenamePopup(Containers::ArrayView name_view) -> bool; void drawGeneralInfo(); void drawResearchInventory(); + void drawResearchTree(); + void drawNode(Node& node); void drawMassManager(); auto drawDeleteMassPopup(int mass_index) -> ImGuiID; auto drawDeleteStagedMassPopup(const std::string& filename) -> ImGuiID; @@ -197,6 +202,8 @@ class SaveTool: public Platform::Sdl2Application, public efsw::FileWatchListener }; Containers::StaticArray<2, efsw::WatchID> _watchIDs; + Containers::Pointer _tree; + bool _checkUpdatesOnStartup{true}; bool _unsafeMode{false}; diff --git a/src/SaveTool/SaveTool_MainManager.cpp b/src/SaveTool/SaveTool_MainManager.cpp index 0e5ee5b..cf1ae18 100644 --- a/src/SaveTool/SaveTool_MainManager.cpp +++ b/src/SaveTool/SaveTool_MainManager.cpp @@ -74,6 +74,11 @@ void SaveTool::drawManager() { ImGui::EndTabItem(); } + if(ImGui::BeginTabItem("Research tree")) { + drawResearchTree(); + ImGui::EndTabItem(); + } + ImGui::EndTabBar(); } @@ -389,6 +394,124 @@ void SaveTool::drawResearchInventory() { #undef matRow } +void SaveTool::drawResearchTree() { + if(!_tree) { + _tree.emplace(); + + _tree->generateEngineTree(); + _tree->readEngineUnlocks(_currentProfile->engineInventory(), _currentProfile->gearInventory()); + + _tree->generateOSTree(); + + _tree->generateArchTree(); + } + + if(ImGui::BeginTabBar("##TreeTabBar")) { + if(ImGui::BeginTabItem("Engine")) { + if(ImGui::BeginTable("##EngineTable", 1, ImGuiTableFlags_RowBg)) { + ImGui::TableSetupColumn("##Column", ImGuiTableColumnFlags_WidthStretch); + + drawNode(_tree->getEngineRootNode()); + + ImGui::EndTable(); + } + + ImGui::EndTabItem(); + } + + if(ImGui::BeginTabItem("OS")) { + if(ImGui::BeginTable("##OSTable", 1, ImGuiTableFlags_RowBg)) { + ImGui::TableSetupColumn("##Column", ImGuiTableColumnFlags_WidthStretch); + + drawNode(_tree->getOSRootNode()); + + ImGui::EndTable(); + } + + ImGui::EndTabItem(); + } + + if(ImGui::BeginTabItem("Architect")) { + if(ImGui::BeginTable("##ArchTable", 1, ImGuiTableFlags_RowBg)) { + ImGui::TableSetupColumn("##Column", ImGuiTableColumnFlags_WidthStretch); + + drawNode(_tree->getArchRootNode()); + + ImGui::EndTable(); + } + + ImGui::EndTabItem(); + } + + ImGui::EndTabBar(); + } +} + +void SaveTool::drawNode(Node& node) { + auto nodeTooltip = [this, &node]{ + if(ImGui::IsItemHovered()) { + ImGui::BeginTooltip(); + ImGui::Text("Tier %u", node.tier()); + + if(node.type() == Node::Type::Engine || + node.type() == Node::Type::OS || + node.type() == Node::Type::Architect) + { + ImGui::SameLine(); + ImGui::SeparatorEx(ImGuiSeparatorFlags_Vertical); + ImGui::SameLine(); + switch(node.type()) { + case Node::Type::Engine: + ImGui::Text("%u gear slots", node.slots()); + break; + case Node::Type::OS: + ImGui::Text("%u module slots", node.slots()); + break; + case Node::Type::Architect: + ImGui::Text("%u tech slots", node.slots()); + break; + default: + break; + } + } + + ImGui::Separator(); + ImGui::PushTextWrapPos(windowSize().x() * 0.40f); + ImGui::TextUnformatted(node.description()); + if(std::strncmp("", node.activeEffect(), 3) != 0) { + ImGui::Separator(); + ImGui::Text("Active effect: %s", node.activeEffect()); + } + if(std::strncmp("", node.passiveEffect(), 3) != 0) { + ImGui::Separator(); + ImGui::Text("Passive effect: %s", node.passiveEffect()); + } + ImGui::PopTextWrapPos(); + ImGui::EndTooltip(); + } + }; + + ImGui::TableNextRow(); + ImGui::TableNextColumn(); + + bool has_children = (node.children().size() > 0); + if(has_children) { + bool open = ImGui::TreeNodeEx(node.name(), ImGuiTreeNodeFlags_SpanAvailWidth|(node.state() == Node::State::Unlocked ? ImGuiTreeNodeFlags_Selected : 0)); + nodeTooltip(); + if(open) { + for(Node* child : node.children()) { + drawNode(*child); + } + ImGui::TreePop(); + } + } + else { + ImGui::TreeNodeEx(node.name(), ImGuiTreeNodeFlags_SpanAvailWidth|ImGuiTreeNodeFlags_Leaf|ImGuiTreeNodeFlags_NoTreePushOnOpen| + ImGuiTreeNodeFlags_Bullet|(node.state() == Node::State::Unlocked ? ImGuiTreeNodeFlags_Selected : 0)); + nodeTooltip(); + } +} + void SaveTool::drawMassManager() { if(!_massManager) { return; -- 2.39.2 From 44ee2f2c3509c387e21e45d70908c9c1efcb15d0 Mon Sep 17 00:00:00 2001 From: William JCM Date: Fri, 30 Jul 2021 15:23:19 +0200 Subject: [PATCH 02/22] Profile: add support for reading OS unlocks. --- src/Profile/Profile.cpp | 52 +++++++++++++++++++++++++++++++++++++++++ src/Profile/Profile.h | 4 ++++ 2 files changed, 56 insertions(+) diff --git a/src/Profile/Profile.cpp b/src/Profile/Profile.cpp index 045d19b..b1e562b 100644 --- a/src/Profile/Profile.cpp +++ b/src/Profile/Profile.cpp @@ -111,6 +111,7 @@ void Profile::refreshValues() { getCarbonizedSkin(); getEngineUnlocks(); + getOsUnlocks(); } auto Profile::companyName() const -> std::string const& { @@ -1054,3 +1055,54 @@ void Profile::getEngineUnlocks() { _lastError = "The profile save seems to be corrupted or the game didn't release the handle on the file."; } } + +auto Profile::osInventory() -> Containers::ArrayView { + return _osInventory; +} + +auto Profile::moduleInventory() -> Containers::ArrayView { + return _moduleInventory; +} + +void Profile::getOsUnlocks() { + auto mmap = Utility::Directory::map(Utility::Directory::join(_profileDirectory, _filename)); + + auto iter = std::search(mmap.begin(), mmap.end(), &os_inventory_locator[0], &os_inventory_locator[29]); + + if(iter != mmap.end()) { + Int* int_iter = reinterpret_cast(iter + 0x37); + Int size = *(int_iter++); + + if(size > 0) { + _osInventory = Containers::Array{DefaultInit, std::size_t(size)}; + std::copy_n(int_iter, size, _osInventory.data()); + + Utility::Debug{} << "_osInventory:" << _osInventory; + + iter = std::search(mmap.begin(), mmap.end(), &module_inventory_locator[0], &module_inventory_locator[33]); + + if(iter == mmap.end()) { + return; + } + + int_iter = reinterpret_cast(iter + 0x3B); + size = *(int_iter++); + + if(size <= 0) { + return; + } + + _moduleInventory = Containers::Array{DefaultInit, std::size_t(size)}; + std::copy_n(int_iter, size, _moduleInventory.data()); + + Utility::Debug{} << "_moduleInventory:" << _moduleInventory; + } + else { + _lastError = "An array can't have a null or negative size."; + Utility::Fatal{EXIT_FAILURE} << _lastError.c_str(); + } + } + else { + _lastError = "The profile save seems to be corrupted or the game didn't release the handle on the file."; + } +} diff --git a/src/Profile/Profile.h b/src/Profile/Profile.h index b2c4cff..6f16116 100644 --- a/src/Profile/Profile.h +++ b/src/Profile/Profile.h @@ -147,6 +147,10 @@ class Profile { auto gearInventory() -> Containers::ArrayView; void getEngineUnlocks(); + auto osInventory() -> Containers::ArrayView; + auto moduleInventory() -> Containers::ArrayView; + void getOsUnlocks(); + private: std::string _profileDirectory; std::string _filename; -- 2.39.2 From fee5c2aefd02f86e8d0f5cffb0bbe5f8a1894fdc Mon Sep 17 00:00:00 2001 From: William JCM Date: Fri, 30 Jul 2021 15:39:11 +0200 Subject: [PATCH 03/22] Profile: add support for reading arch unlocks. --- src/Profile/Profile.cpp | 52 +++++++++++++++++++++++++++++++++++++++++ src/Profile/Profile.h | 4 ++++ 2 files changed, 56 insertions(+) diff --git a/src/Profile/Profile.cpp b/src/Profile/Profile.cpp index b1e562b..9c11c8b 100644 --- a/src/Profile/Profile.cpp +++ b/src/Profile/Profile.cpp @@ -112,6 +112,7 @@ void Profile::refreshValues() { getEngineUnlocks(); getOsUnlocks(); + getArchUnlocks(); } auto Profile::companyName() const -> std::string const& { @@ -1106,3 +1107,54 @@ void Profile::getOsUnlocks() { _lastError = "The profile save seems to be corrupted or the game didn't release the handle on the file."; } } + +auto Profile::archInventory() -> Containers::ArrayView { + return _archInventory; +} + +auto Profile::techInventory() -> Containers::ArrayView { + return _techInventory; +} + +void Profile::getArchUnlocks() { + auto mmap = Utility::Directory::map(Utility::Directory::join(_profileDirectory, _filename)); + + auto iter = std::search(mmap.begin(), mmap.end(), &arch_inventory_locator[0], &arch_inventory_locator[36]); + + if(iter != mmap.end()) { + Int* int_iter = reinterpret_cast(iter + 0x3E); + Int size = *(int_iter++); + + if(size > 0) { + _archInventory = Containers::Array{DefaultInit, std::size_t(size)}; + std::copy_n(int_iter, size, _archInventory.data()); + + Utility::Debug{} << "_archInventory:" << _archInventory; + + iter = std::search(mmap.begin(), mmap.end(), &tech_inventory_locator[0], &tech_inventory_locator[31]); + + if(iter == mmap.end()) { + return; + } + + int_iter = reinterpret_cast(iter + 0x39); + size = *(int_iter++); + + if(size <= 0) { + return; + } + + _techInventory = Containers::Array{DefaultInit, std::size_t(size)}; + std::copy_n(int_iter, size, _techInventory.data()); + + Utility::Debug{} << "_techInventory:" << _techInventory; + } + else { + _lastError = "An array can't have a null or negative size."; + Utility::Fatal{EXIT_FAILURE} << _lastError.c_str(); + } + } + else { + _lastError = "The profile save seems to be corrupted or the game didn't release the handle on the file."; + } +} diff --git a/src/Profile/Profile.h b/src/Profile/Profile.h index 6f16116..947aab7 100644 --- a/src/Profile/Profile.h +++ b/src/Profile/Profile.h @@ -151,6 +151,10 @@ class Profile { auto moduleInventory() -> Containers::ArrayView; void getOsUnlocks(); + auto archInventory() -> Containers::ArrayView; + auto techInventory() -> Containers::ArrayView; + void getArchUnlocks(); + private: std::string _profileDirectory; std::string _filename; -- 2.39.2 From f8b51791a1040870206c8aa03d90f671cd0488c1 Mon Sep 17 00:00:00 2001 From: William JCM Date: Sat, 31 Jul 2021 11:30:15 +0200 Subject: [PATCH 04/22] NodeIDs: add OS enumerators. --- src/ResearchTree/NodeIDs.h | 65 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) diff --git a/src/ResearchTree/NodeIDs.h b/src/ResearchTree/NodeIDs.h index 551f5c7..80490d9 100644 --- a/src/ResearchTree/NodeIDs.h +++ b/src/ResearchTree/NodeIDs.h @@ -86,6 +86,71 @@ enum EngineIDs: Int { enum OSIDs: Int { // Tier 1 NeuralOS = 300010, + ExoSkelOS, + Shields1, + Enhancements1, + FuelSave1, + LongRange1, + + // Tier 2 + SparkOS, + ImprovedNeuralOS, + EnhancedSkeletonOS, + ExtendedArtsLibrary, + SustainableShield1, + Shields2, + SustainableRecharger1, + Enhancements2, + FuelSave2, + LongRange2, + EmpoweredArtsLibrary, + + //Tier 3 + BlazeOS, + NeurolinkOS, + PoweredGuardianOS, + SustainableShields2, + Shields3, + SustainableRecharger2, + Enhancements3, + FuelSave3, + LongRange3, + + // Tier 4 + IgnitionOS, + AlteredFuelOS, + MindlinkOS, + FramelinkOS, + SlayerOS, + SustainableShields3, + Shields4, + SustainableRecharger3, + Enhancements4, + FuelSave4, + LongRange4, + CellburnOS, + StorageShielder1, + Realignment1, + AlphaAssault1, + BetaAssault1, + + // Tier 5 + BrightburnOS, + OmniaOS, + FullConnectOS, + FullDiveOS, + SpartoiOS, + SustainableShields4, + Shields5, + SustainableRecharger5, + Enhancements5, + FuelSave5, + LongRange5, + FirestormOS, + StorageShielder2, + Realignment2, + AlphaAssault2, + BetaAssault2, }; enum ArchIDs: Int { -- 2.39.2 From 7f710f5db3d6911984751cd14e5d7a21274ba965 Mon Sep 17 00:00:00 2001 From: William JCM Date: Sun, 1 Aug 2021 11:55:35 +0200 Subject: [PATCH 05/22] NodeIDs: add arch enumerators. --- src/ResearchTree/NodeIDs.h | 205 ++++++++++++++++++++++++++++++++++++- 1 file changed, 203 insertions(+), 2 deletions(-) diff --git a/src/ResearchTree/NodeIDs.h b/src/ResearchTree/NodeIDs.h index 80490d9..fdec6e8 100644 --- a/src/ResearchTree/NodeIDs.h +++ b/src/ResearchTree/NodeIDs.h @@ -153,7 +153,208 @@ enum OSIDs: Int { BetaAssault2, }; -enum ArchIDs: Int { - // Tier 1 +enum ArchIDs: Int { // That tree is a **fucking mess**, so this enum will be too. + // Left side T1 StandardFrame = 500099, + StrengthFrame, + BoostFrame, + SupportFrame, + CombatFrame, + DurableFibre1, + EfficientThrusters1, + MaterialsCollector1, + TempoPreserver, + + // Left side T2 + StopperFrame, + ReinforcedFrame, + Overtaker, + GeneratorFrame, + HeavyLoadFrame, + SiegeMechFrame, + SentryFrame, + MetalsReplacement, + ReactiveArmour1, + FrameBoostingSystemSType, + EnemyScanner1, + MaterialsCollector2, + CompositeNanorobotics, + PinpointReticle1, + + // Left side T3 + BlockerUnit, + Hillgard, + Atmosformer, + Revitaliser, + SupplyCarrier, + TheEnforcer, + Precelsior, + ForcefulTinkeringDType, + ReactiveArmour2, + EfficienttThrusters2, + EnemyScanner2, + MaterialsCollector3, + PressurisedGears1, + PinpointReticle2, + + // Left side T4 + Aurochs, + Pantheris, + Vulture, + Vitalcycler, + Amberjack, + Bloodhounds, + ManOWar, + Steelwall, + DurableFibre2, + Streamliner, + FortressConfigurations1, + Afterburners1, + PerpetualGenerator1, + DataAnalyser1, + VoidDestabiliser1, + Ragelock, + BinaryMonarchEType, + Stingray, + ShieldsformerSystem1, + ShieldsEnhancer1, + AcceleratedWalkers1, + BulletRecollector1, + EnemyScanner3, + ArmsSBattery1, + BinaryMonarchAType, + + // Left side T5 + Longhorn, + Lionel, + Stormbyrd, + Hydra, + Orca, + Felcaninus, + Anglerwasp, + Ramsgate, + DoomsdayCargo, + Ghostech, + ReactiveArmour3, + FrameBoostingSystemDType, + PerpetualGenerator2, + DataAnalyser2, + PoweredNanorobotics, + Styxgear, + FullMetalJacketAType, + Thornwhip, + ShieldsformerSystem2, + ShieldsRerouter, + AdditionalThrusters1, + BulletRecollector2, + EnemyInspector1, + ArmsSBattery2, + FullMetalJacketIType, + + // Elemental T1/2 (there's a lone T1 node, so I won't make a separate group just for it) + EnemyObserverUnit, + BladeBlazeCanister, + BladeCryoCore, + BladeVoltAmplifier, + BlazeBulletsTech, + CryoBulletsTech, + VoltBulletsTech, + BlazePodsTech, + CryoPodsTech, + VoltPodsTech, + + // Elemental T3 + PowerTransferenceUnit1, + Adaptive, + BlazeArmsEnhancer, + CryoArmsEnhancer, + VoltArmsEnhancer, + + // Elemental T4 + PowerTransferenceUnit2, + Elemental, + BlazeTransferenceUnit, + CryoTransferenceUnit, + VoltTransferenceUnit, + QuickBurningChemicals, + CryoCoatedMetals, + VoltageOverclock, + + // Elemental T5 + PowerTransferenceUnit3, + Revenant, + ArmsConductionController, + TrinityCore1, + PodsConductionController, + MeltingChemicals, + LongLastingCryoChems, + VoltSplitters, + + WeaponStanceControls, // This node is common to both the DW and shield sub-trees. + + // Shield T2 + ProtectiveCoating1, + MeteorShielder1, + + // Shield T3 + Retaliator, + Flagbearer1, + AegisReinforcements1, + + // Shield T4 + Flashspike, + ProtectiveCoating2, + MeteorShielder2, + IntegrityStrengthening1, + + // Shield T5 + Faithbinder, + SaintessBulwark, + MeteorShielder3, + BlizzardCore1, + + // DW T2 + GatheringStorm1, + WildfireStarter1, + + // DW T3 + MasterOfArms, + Stormwielder, + Suncaller, + + // DW T4 + Evoker, + GatheringStorm2, + WildfireStarter2, + GravitationDefier1, + + // DW T5 + Bladedancer, + Type3ArmsSBattery1, + ShieldsBatteryRegulator1, + GravitationDefier2, + + // QB T2/3 + // Okay, time to rant. The first node of the QB sub-tree is a tier 2 node. By itself, it's not that bad, + // except that... it's the child of Master of Arms, the first T3 node in the DW sub-tree. :DeadInside: + QuantumMechanicsResearch, + QuantumAccelerationResearch, + QuantumControlResearch, + QuantumCoatingResearch, + + // QB T4 + EnergyCollector1, + ParticleAccelerator1, + AmplificationModule1, + QAugmentedThrusters, + EssenceRedistributor1, + MomentumSpiker1, + + // QB T5 + EnergyCollector2, + ParticleAccelerator2, + AmplificationModule2, + QAugmentedShields, + EssenceRedistributor2, + MomentumSpiker2, }; -- 2.39.2 From f321a06a0e35a10b8fa1e28780ccd16d447b7436 Mon Sep 17 00:00:00 2001 From: William JCM Date: Sun, 1 Aug 2021 13:26:11 +0200 Subject: [PATCH 06/22] ResearchTree: added T3 engine nodes. --- src/ResearchTree/ResearchTree.cpp | 61 +++++++++++++++++++++++++------ 1 file changed, 49 insertions(+), 12 deletions(-) diff --git a/src/ResearchTree/ResearchTree.cpp b/src/ResearchTree/ResearchTree.cpp index b23b4e4..a63f5c9 100644 --- a/src/ResearchTree/ResearchTree.cpp +++ b/src/ResearchTree/ResearchTree.cpp @@ -127,6 +127,7 @@ void ResearchTree::generateEngineTree() { return; } + // T1 _engineNodes.emplace(VerseEngine, Node{Node::Type::Engine, "Verse Engine", 1, 3, "A basic low-speed engine with great durability.", "Durability +346, Power +60, Armour +22, Acceleration +75, Magazine load +35, Energy capacity +35", @@ -140,61 +141,83 @@ void ResearchTree::generateEngineTree() { _engineNodes.emplace(MetalPlatings1, Node{Node::Type::Gear, "Metal Platings 1", 1, 0, "Level 1 metal plating that adds durability and armour to your engine.", "Durability +60, Armour +5, Acceleration -15", ""}); - _engineNodes.emplace(HeatTurbines1, Node{Node::Type::Gear, "Heat Turbines 1", 1, 0, "Modified heat turbines to increase speed for a M.A.S.S.", "Acceleration +75, Fuel capacity +5", ""}); - _engineNodes.emplace(Microcontroller1, Node{Node::Type::Gear, "Microcontroller 1", 1, 0, "A microchip that enhances various aspects of a M.A.S.S.", "Durability +36, Power +1, Armour +11, Magazine load +5, Energy capacity +5, Fuel capacity +3", ""}); - _engineNodes.emplace(CombustionController1, Node{Node::Type::Gear, "Combustion Controller 1", 1, 0, "Controlled combustion allows increased power generation through specific ignition.", "Power +2, Magazine load +10, Energy capacity +10, Acceleration -25", ""}); + // T2 _engineNodes.emplace(ModAlloyEngine, Node{Node::Type::Engine, "Mod. Alloy Engine", 2, 3, "Built with a modified alloy and able to sustain greater attacks from any enemy.", "Durability +1152, Power +75, Armour +194, Acceleration +75, Magazine load +40, Energy capacity +40", "Durability +3%"}); - _engineNodes.emplace(ChargedEngine, Node{Node::Type::Engine, "Charged Engine", 2, 3, "Remove most armours to attain more speed and power, and fuel.", "Durability +960, Power +75, Acceleration +300, Magazine load +40, Energy capacity +40, Fuel capacity +52", "Acceleration +5"}); - _engineNodes.emplace(ReinforcedLoadedEngine, Node{Node::Type::Engine, "Reinforced Loaded Engine", 2, 3, "An upgraded build of the basic model, with reinforced Verse Steel for more strength.", "Durability +960, Power +105, Armour +130, Acceleration +75, Magazine load +40, Energy capacity +40", "Power +3%"}); - _engineNodes.emplace(HeavyImpactsEnabler, Node{Node::Type::Engine, "Heavy Impacts Enabler", 2, 0, "Enable the usage of Heavy Combos in close combat attacks.", "", ""}); _engineNodes.emplace(MetalPlatings2, Node{Node::Type::Gear, "Metal Platings 2", 2, 0, "Level 2 Metal plating that adds durability and armour to your engine.", "Durability +180, Armour +41, Acceleration -15", ""}); - _engineNodes.emplace(HeatTurbines2, Node{Node::Type::Gear, "Heat Turbines 2", 2, 0, "Level 2 Modified heat turbines to increase speed for a M.A.S.S.", "Acceleration +75, Fuel capacity +16", ""}); - _engineNodes.emplace(Microcontroller2, Node{Node::Type::Gear, "Microcontroller 2", 2, 0, "Level 2 Microchip that enhances various aspects of a M.A.S.S.", "Durability +108, Power +3, Armour +17, Magazine load +6, Energy capacity +6, Fuel capacity +8", ""}); - _engineNodes.emplace(WeaponsCargo1, Node{Node::Type::Gear, "Weapons Cargo 1", 2, 0, - "Added another cargo hold for ammo and energy recharger", + "Added another cargo hold for ammo and energy recharger.", "Magazine load +24, Energy capacity +24, Acceleration -40", ""}); - _engineNodes.emplace(CombustionController2, Node{Node::Type::Gear, "Combustion Controller 2", 2, 0, "Level 2 Controlled combustion allows increased power generation through specific ignition.", "Power +5, Magazine load +12, Energy capacity +12, Acceleration -25", ""}); - _engineNodes.emplace(PoweredRewiring1, Node{Node::Type::Gear, "Powered Rewiring 1", 2, 0, "Rewiring that efficiently improves power and engine durability.", "Durability +180, Power +5", ""}); + // T3 + _engineNodes.emplace(ModSteelEngine, Node{Node::Type::Engine, "Mod. Steel Engine", 3, 3, + "Low-speed engine that uses heavy materials for high durability.", + "Durability +2352, Power +90, Armour +311, Acceleration +75, Magazine load +47, Energy capacity +47", + "Durability +3%"}); + _engineNodes.emplace(SuperchargedEngine, Node{Node::Type::Engine, "Supercharged Engine", 3, 3, + "An engine with more thermal efficiency that does not sacrifice much performance for speed.", + "Durability +1960, Power +90, Acceleration +300, Magazine load +47, Energy capacity +47, Fuel capacity +104", + "Acceleration +5"}); + _engineNodes.emplace(NecriumAlloyEngine, Node{Node::Type::Engine, "Necrium Alloy Engine", 3, 3, + "Engine constructed of Necrium Alloy. Costly but with better performance.", + "Durability +1960, Power +126, Armour +207, Acceleration +75, Magazine load +47, Energy capacity +47", + "Power +3%"}); + _engineNodes.emplace(MetalPlatings3, Node{Node::Type::Gear, "Metal Platings 3", 3, 0, + "Level 2 Metal plating that adds durability and armour to your engine.", + "Durability +360, Armour +57, Acceleration -15", ""}); + _engineNodes.emplace(HeatTurbines3, Node{Node::Type::Gear, "Heat Turbines 3", 3, 0, + "Level 3 Modified heat turbines to increase speed for a M.A.S.S.", + "Acceleration +75, Fuel capacity +32", ""}); + _engineNodes.emplace(Microcontroller3, Node{Node::Type::Gear, "Microcontroller 3", 3, 0, + "Level 3 Microchip that enhances various aspects of a M.A.S.S.", + "Durability +216, Power +5, Armour +24, Magazine load +7, Energy capacity +7, Fuel capacity +16", ""}); + _engineNodes.emplace(WeaponsCargo2, Node{Node::Type::Gear, "Weapons Cargo 2", 3, 0, + "Level 2 Added another cargo hold for ammo and energy recharger.", + "Magazine load +28, Energy capacity +28, Acceleration -40", ""}); + _engineNodes.emplace(CombustionController3, Node{Node::Type::Gear, "Combustion Controller 3", 3, 0, + "Level 3 Controlled combustion allows increased power generation through specific ignition.", + "Power +11, Magazine load +14, Energy capacity +14, Acceleration -25", ""}); + _engineNodes.emplace(PoweredRewiring2, Node{Node::Type::Gear, "Powered Rewiring 2", 3, 0, + "Level 2 Rewiring that efficiently improves power and engine durability.", + "Durability +360, Power +11", ""}); + _engineNodes.at(VerseEngine).addChild(_engineNodes.at(MetalPlatings1)); _engineNodes.at(VerseEngine).addChild(_engineNodes.at(HeatTurbines1)); _engineNodes.at(VerseEngine).addChild(_engineNodes.at(LoadedEngine)); @@ -212,6 +235,20 @@ void ResearchTree::generateEngineTree() { _engineNodes.at(ReinforcedLoadedEngine).addChild(_engineNodes.at(CombustionController2)); _engineNodes.at(ReinforcedLoadedEngine).addChild(_engineNodes.at(PoweredRewiring1)); _engineNodes.at(ReinforcedLoadedEngine).addChild(_engineNodes.at(HeavyImpactsEnabler)); + _engineNodes.at(MetalPlatings2).addChild(_engineNodes.at(ModSteelEngine)); + _engineNodes.at(HeatTurbines2).addChild(_engineNodes.at(SuperchargedEngine)); + _engineNodes.at(Microcontroller2).addChild(_engineNodes.at(SuperchargedEngine)); + _engineNodes.at(WeaponsCargo1).addChild(_engineNodes.at(SuperchargedEngine)); + _engineNodes.at(CombustionController2).addChild(_engineNodes.at(NecriumAlloyEngine)); + _engineNodes.at(PoweredRewiring1).addChild(_engineNodes.at(NecriumAlloyEngine)); + _engineNodes.at(ModSteelEngine).addChild(_engineNodes.at(MetalPlatings3)); + _engineNodes.at(ModSteelEngine).addChild(_engineNodes.at(HeatTurbines3)); + _engineNodes.at(SuperchargedEngine).addChild(_engineNodes.at(HeatTurbines3)); + _engineNodes.at(SuperchargedEngine).addChild(_engineNodes.at(Microcontroller3)); + _engineNodes.at(SuperchargedEngine).addChild(_engineNodes.at(WeaponsCargo2)); + _engineNodes.at(NecriumAlloyEngine).addChild(_engineNodes.at(WeaponsCargo2)); + _engineNodes.at(NecriumAlloyEngine).addChild(_engineNodes.at(CombustionController3)); + _engineNodes.at(NecriumAlloyEngine).addChild(_engineNodes.at(PoweredRewiring2)); _engineNodes.at(VerseEngine).setState(Node::State::Unlocked); } -- 2.39.2 From 562758109c2c258cb8d354a6d898ac1f8831f3f7 Mon Sep 17 00:00:00 2001 From: William JCM Date: Sun, 1 Aug 2021 13:26:44 +0200 Subject: [PATCH 07/22] SaveTool: improve the looks of nodes. --- src/SaveTool/SaveTool_MainManager.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/SaveTool/SaveTool_MainManager.cpp b/src/SaveTool/SaveTool_MainManager.cpp index cf1ae18..ec1fc1d 100644 --- a/src/SaveTool/SaveTool_MainManager.cpp +++ b/src/SaveTool/SaveTool_MainManager.cpp @@ -495,6 +495,9 @@ void SaveTool::drawNode(Node& node) { ImGui::TableNextColumn(); bool has_children = (node.children().size() > 0); + if(node.state() == Node::State::Unavailable) { + ImGui::PushStyleColor(ImGuiCol_Text, ImGui::GetStyleColorVec4(ImGuiCol_TextDisabled)); + } if(has_children) { bool open = ImGui::TreeNodeEx(node.name(), ImGuiTreeNodeFlags_SpanAvailWidth|(node.state() == Node::State::Unlocked ? ImGuiTreeNodeFlags_Selected : 0)); nodeTooltip(); @@ -510,6 +513,9 @@ void SaveTool::drawNode(Node& node) { ImGuiTreeNodeFlags_Bullet|(node.state() == Node::State::Unlocked ? ImGuiTreeNodeFlags_Selected : 0)); nodeTooltip(); } + if(node.state() == Node::State::Unavailable) { + ImGui::PopStyleColor(); + } } void SaveTool::drawMassManager() { -- 2.39.2 From 7a9cb3d9a1c515db5dafbd5c514ab1d6a98ed0f5 Mon Sep 17 00:00:00 2001 From: William JCM Date: Sun, 1 Aug 2021 20:15:21 +0200 Subject: [PATCH 08/22] ResearchTree: fix a typo. --- src/ResearchTree/ResearchTree.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ResearchTree/ResearchTree.cpp b/src/ResearchTree/ResearchTree.cpp index a63f5c9..18b5adf 100644 --- a/src/ResearchTree/ResearchTree.cpp +++ b/src/ResearchTree/ResearchTree.cpp @@ -200,7 +200,7 @@ void ResearchTree::generateEngineTree() { "Durability +1960, Power +126, Armour +207, Acceleration +75, Magazine load +47, Energy capacity +47", "Power +3%"}); _engineNodes.emplace(MetalPlatings3, Node{Node::Type::Gear, "Metal Platings 3", 3, 0, - "Level 2 Metal plating that adds durability and armour to your engine.", + "Level 3 Metal plating that adds durability and armour to your engine.", "Durability +360, Armour +57, Acceleration -15", ""}); _engineNodes.emplace(HeatTurbines3, Node{Node::Type::Gear, "Heat Turbines 3", 3, 0, "Level 3 Modified heat turbines to increase speed for a M.A.S.S.", -- 2.39.2 From 8ede484b0e5761dcc6da0b9d75a71a395ebcc365 Mon Sep 17 00:00:00 2001 From: William JCM Date: Tue, 3 Aug 2021 20:07:16 +0200 Subject: [PATCH 09/22] ResearchTree: added T4 engine nodes. --- src/ResearchTree/ResearchTree.cpp | 76 +++++++++++++++++++++++++++++++ 1 file changed, 76 insertions(+) diff --git a/src/ResearchTree/ResearchTree.cpp b/src/ResearchTree/ResearchTree.cpp index 18b5adf..22653ca 100644 --- a/src/ResearchTree/ResearchTree.cpp +++ b/src/ResearchTree/ResearchTree.cpp @@ -218,6 +218,58 @@ void ResearchTree::generateEngineTree() { "Level 2 Rewiring that efficiently improves power and engine durability.", "Durability +360, Power +11", ""}); + // T4 + _engineNodes.emplace(ModLunariteEngine, Node{Node::Type::Engine, "Mod. Lunarite Engine", 4, 4, + "Modified Durasteel that is heavier than normal durasteel, but even more durable", + "Durability +3744, Power +105, Armour +428, Acceleration +75, Magazine load +54, Energy capacity +54", + "Durability +3%"}); + _engineNodes.emplace(ChargedLunariteEngine, Node{Node::Type::Engine, "Charged Lunarite Engine", 4, 4, + "Charged up Lunarite engine that compromises durability for more speed, then added with armour platings.", + "Durability +3120, Power +105, Acceleration +300, Magazine load +54, Energy capacity +54, Fuel capacity +157", + "Acceleration +5"}); + _engineNodes.emplace(LunariteEngine, Node{Node::Type::Engine, "Lunarite Engine", 4, 4, + "Engine made of an alloy composed of Lunarite and various other metals.", + "Durability +3120, Power +147, Armour +285, Acceleration +75, Magazine load +54, Energy capacity +54", + "Power +3%"}); + _engineNodes.emplace(InfusedEngine, Node{Node::Type::Engine, "Infused Engine", 4, 4, + "An engine with infused plating. Highly resistant to heat, allowing fuel to be burned at higher temperatures.", + "Durability +5460, Power +84, Armour +499, Acceleration -50, Magazine load +43, Energy capacity +43", + "Durability +3%"}); + _engineNodes.emplace(MetalPlatings4, Node{Node::Type::Gear, "Metal Platings 4", 4, 0, + "Level 4 Metal plating that adds durability and armour to your engine.", + "Durability +540, Armour +73, Acceleration -15", ""}); + _engineNodes.emplace(HeatTurbines4, Node{Node::Type::Gear, "Heat Turbines 4", 4, 0, + "Level 4 Modified heat turbines to increase speed for a M.A.S.S.", + "Acceleration +75, Fuel capacity +47", ""}); + _engineNodes.emplace(Microcontroller4, Node{Node::Type::Gear, "Microcontroller 4", 4, 0, + "Level 4 Microchip that enhances various aspects of a M.A.S.S.", + "Durability +324, Power +8, Armour +30, Magazine load +8, Energy capacity +8, Fuel capacity +24", ""}); + _engineNodes.emplace(WeaponsCargo3, Node{Node::Type::Gear, "Weapons Cargo 3", 4, 0, + "Level 3 Added another cargo hold for ammo and energy recharger.", + "Magazine load +32, Energy capacity +32, Acceleration -40", ""}); + _engineNodes.emplace(CombustionController4, Node{Node::Type::Gear, "Combustion Controller 4", 4, 0, + "Level 4 Controlled combustion allows increased power generation through specific ignition.", + "Power +16, Magazine load +16, Energy capacity +16, Acceleration -25", ""}); + _engineNodes.emplace(PoweredRewiring3, Node{Node::Type::Gear, "Powered Rewiring 3", 4, 0, + "Level 3 Rewiring that efficiently improves power and engine durability.", + "Durability +540, Power +16", ""}); + _engineNodes.emplace(ArmouredCargo1, Node{Node::Type::Gear, "Armoured Cargo 1", 4, 0, + "Added armoured platings for large cargo holds.", + "Armour +61, Magazine load +16, Energy capacity +16, Acceleration -40", ""}); + _engineNodes.emplace(ArmouredFuelTank1, Node{Node::Type::Gear, "Armoured Fuel Tank 1", 4, 0, + "Added armoured platings for a large fuel tank.", + "Armour +61, Fuel capacity +24, Acceleration -15", ""}); + _engineNodes.emplace(ExtraCapacity1, Node{Node::Type::Gear, "Extra Capacity 1", 4, 0, + "Space management with added capacity for more cargo holds and fuel.", + "Magazine load +16, Energy capacity +16, Fuel capacity +47, Acceleration -40", ""}); + _engineNodes.emplace(HighmetalEngine, Node{Node::Type::Engine, "Highmetal Engine", 4, 4, + "Made of highmetal, an alloy composed of Lunarite and other metals. Difficult to work into complex shapes, but high heat resistance.", + "Durability +2730, Power +189, Armour +249, Acceleration -50", + "Power +3%"}); + _engineNodes.emplace(PowerRedirector1, Node{Node::Type::Gear, "Power Redirector 1", 4, 0, + "Redirection of power into fuel management for more power and acceleration.", + "Power +16, Acceleration +50", ""}); + _engineNodes.at(VerseEngine).addChild(_engineNodes.at(MetalPlatings1)); _engineNodes.at(VerseEngine).addChild(_engineNodes.at(HeatTurbines1)); _engineNodes.at(VerseEngine).addChild(_engineNodes.at(LoadedEngine)); @@ -249,6 +301,30 @@ void ResearchTree::generateEngineTree() { _engineNodes.at(NecriumAlloyEngine).addChild(_engineNodes.at(WeaponsCargo2)); _engineNodes.at(NecriumAlloyEngine).addChild(_engineNodes.at(CombustionController3)); _engineNodes.at(NecriumAlloyEngine).addChild(_engineNodes.at(PoweredRewiring2)); + _engineNodes.at(MetalPlatings3).addChild(_engineNodes.at(ModLunariteEngine)); + _engineNodes.at(HeatTurbines3).addChild(_engineNodes.at(ChargedLunariteEngine)); + _engineNodes.at(Microcontroller3).addChild(_engineNodes.at(ChargedLunariteEngine)); + _engineNodes.at(WeaponsCargo2).addChild(_engineNodes.at(ChargedLunariteEngine)); + _engineNodes.at(CombustionController3).addChild(_engineNodes.at(LunariteEngine)); + _engineNodes.at(PoweredRewiring2).addChild(_engineNodes.at(LunariteEngine)); + _engineNodes.at(ModLunariteEngine).addChild(_engineNodes.at(InfusedEngine)); + _engineNodes.at(ModLunariteEngine).addChild(_engineNodes.at(MetalPlatings4)); + _engineNodes.at(ChargedLunariteEngine).addChild(_engineNodes.at(HeatTurbines4)); + _engineNodes.at(ChargedLunariteEngine).addChild(_engineNodes.at(Microcontroller4)); + _engineNodes.at(ChargedLunariteEngine).addChild(_engineNodes.at(WeaponsCargo3)); + _engineNodes.at(LunariteEngine).addChild(_engineNodes.at(CombustionController4)); + _engineNodes.at(LunariteEngine).addChild(_engineNodes.at(PoweredRewiring3)); + _engineNodes.at(InfusedEngine).addChild(_engineNodes.at(ArmouredCargo1)); + _engineNodes.at(InfusedEngine).addChild(_engineNodes.at(ArmouredFuelTank1)); + _engineNodes.at(MetalPlatings4).addChild(_engineNodes.at(ArmouredCargo1)); + _engineNodes.at(MetalPlatings4).addChild(_engineNodes.at(ArmouredFuelTank1)); + _engineNodes.at(HeatTurbines4).addChild(_engineNodes.at(ExtraCapacity1)); + _engineNodes.at(Microcontroller4).addChild(_engineNodes.at(ExtraCapacity1)); + _engineNodes.at(WeaponsCargo3).addChild(_engineNodes.at(ExtraCapacity1)); + _engineNodes.at(CombustionController4).addChild(_engineNodes.at(HighmetalEngine)); + _engineNodes.at(CombustionController4).addChild(_engineNodes.at(PowerRedirector1)); + _engineNodes.at(PoweredRewiring3).addChild(_engineNodes.at(HighmetalEngine)); + _engineNodes.at(PoweredRewiring3).addChild(_engineNodes.at(PowerRedirector1)); _engineNodes.at(VerseEngine).setState(Node::State::Unlocked); } -- 2.39.2 From f2243f086f241a49f47fe13e341c35a1fb5fe4c8 Mon Sep 17 00:00:00 2001 From: William JCM Date: Tue, 3 Aug 2021 20:23:44 +0200 Subject: [PATCH 10/22] ResearchTree: add T1 OS nodes and IDs. --- src/ResearchTree/NodeIDs.h | 12 ++++++------ src/ResearchTree/ResearchTree.cpp | 23 +++++++++++++++++++++++ 2 files changed, 29 insertions(+), 6 deletions(-) diff --git a/src/ResearchTree/NodeIDs.h b/src/ResearchTree/NodeIDs.h index fdec6e8..b99eeb9 100644 --- a/src/ResearchTree/NodeIDs.h +++ b/src/ResearchTree/NodeIDs.h @@ -85,12 +85,12 @@ enum EngineIDs: Int { enum OSIDs: Int { // Tier 1 - NeuralOS = 300010, - ExoSkelOS, - Shields1, - Enhancements1, - FuelSave1, - LongRange1, + NeuralOS = 300010, + ExoSkelOS = 300030, + Shields1 = 400010, + Enhancements1 = 400050, + FuelSave1 = 400051, + LongRange1 = 400030, // Tier 2 SparkOS, diff --git a/src/ResearchTree/ResearchTree.cpp b/src/ResearchTree/ResearchTree.cpp index 22653ca..db2dbba 100644 --- a/src/ResearchTree/ResearchTree.cpp +++ b/src/ResearchTree/ResearchTree.cpp @@ -334,10 +334,33 @@ void ResearchTree::generateOSTree() { return; } + // T1 _osNodes.emplace(NeuralOS, Node{Node::Type::OS, "Neural OS", 1, 3, "Synchronise the links between your nervous system and the M.A.S.S. perfectly.", "Accuracy +24, Shield +624, Fuel burn rate +200, Magazine reload +24, Energy recharge +66, Shield recover +1620", "Shield +3%"}); + _osNodes.emplace(ExoSkelOS, Node{Node::Type::OS, "ExoSkel OS", 1, 3, + "An OS that simulates the M.A.S.S. as your exoskeleton.", + "Accuracy +45, Shield +360, Fuel burn rate +300, Magazine reload +30, Energy recharge +83, Shield recover +608", + "Accuracy +3%"}); + _osNodes.emplace(Shields1, Node{Node::Type::Module, "Shields 1", 1, 0, + "Module that helps in optimising shield usage.", + "Shield +60, Fuel burn rate +25, Shield recover +506", ""}); + _osNodes.emplace(Enhancements1, Node{Node::Type::Module, "Enhancements 1", 1, 0, + "An overall enhancement module.", + "Accuracy +1, Shield +36, Magazine reload +13, Energy recharge +16, Fuel burn rate -3, Shield recover +169", ""}); + _osNodes.emplace(FuelSave1, Node{Node::Type::Module, "Fuel Save 1", 1, 0, + "Optimisation module for energy usage of the M.A.S.S. frame.", + "Fuel burn rate -5, Fuel recharge +2", ""}); + _osNodes.emplace(LongRange1, Node{Node::Type::Module, "Long Range 1", 1, 0, + "Controlling module that helps in stabilisation for higher accuracy and reload speed.", + "Accuracy +2, Fuel burn rate +50, Magazine reload +25, Energy recharge +33", ""}); + + _osNodes.at(NeuralOS).addChild(_osNodes.at(Shields1)); + _osNodes.at(NeuralOS).addChild(_osNodes.at(Enhancements1)); + _osNodes.at(NeuralOS).addChild(_osNodes.at(ExoSkelOS)); + _osNodes.at(ExoSkelOS).addChild(_osNodes.at(FuelSave1)); + _osNodes.at(ExoSkelOS).addChild(_osNodes.at(LongRange1)); _osNodes.at(NeuralOS).setState(Node::State::Unlocked); } -- 2.39.2 From 4baca47f728b6136b80e0d01b71507ef75d3474b Mon Sep 17 00:00:00 2001 From: William JCM Date: Tue, 3 Aug 2021 20:29:35 +0200 Subject: [PATCH 11/22] ResearchTree: fix a typo. --- src/ResearchTree/ResearchTree.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ResearchTree/ResearchTree.cpp b/src/ResearchTree/ResearchTree.cpp index db2dbba..b6ddb3e 100644 --- a/src/ResearchTree/ResearchTree.cpp +++ b/src/ResearchTree/ResearchTree.cpp @@ -389,7 +389,7 @@ void ResearchTree::readEngineUnlocks(Containers::ArrayView engines, Contain } } - if(gears == nullptr || engines.size() == 0) { + if(gears == nullptr || gears.size() == 0) { return; } -- 2.39.2 From be4d1029c56a3613db693db010e897e6eed879e4 Mon Sep 17 00:00:00 2001 From: William JCM Date: Tue, 3 Aug 2021 20:38:19 +0200 Subject: [PATCH 12/22] ResearchTree: add a missing early return. --- src/ResearchTree/ResearchTree.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/ResearchTree/ResearchTree.cpp b/src/ResearchTree/ResearchTree.cpp index b6ddb3e..d5b2f64 100644 --- a/src/ResearchTree/ResearchTree.cpp +++ b/src/ResearchTree/ResearchTree.cpp @@ -381,6 +381,7 @@ void ResearchTree::generateArchTree() { void ResearchTree::readEngineUnlocks(Containers::ArrayView engines, Containers::ArrayView gears) { if(engines == nullptr || engines.size() == 0) { Utility::Error{} << "Engines can't be empty"; + return; } for(Int& engine : engines) { -- 2.39.2 From 1cd91e1aaa4dfcf1f5245cb789d62d555c0f41a4 Mon Sep 17 00:00:00 2001 From: William JCM Date: Tue, 3 Aug 2021 20:39:40 +0200 Subject: [PATCH 13/22] ResearchTree: use normal ints in range-based for. They're smaller than references, and they're trivially-copiable. They shouldn't be passed by reference. :facepalm: --- src/ResearchTree/ResearchTree.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ResearchTree/ResearchTree.cpp b/src/ResearchTree/ResearchTree.cpp index d5b2f64..bda6279 100644 --- a/src/ResearchTree/ResearchTree.cpp +++ b/src/ResearchTree/ResearchTree.cpp @@ -384,7 +384,7 @@ void ResearchTree::readEngineUnlocks(Containers::ArrayView engines, Contain return; } - for(Int& engine : engines) { + for(Int engine : engines) { if(_engineNodes.find(engine) != _engineNodes.end()) { _engineNodes.at(engine).setState(Node::State::Unlocked); } @@ -394,7 +394,7 @@ void ResearchTree::readEngineUnlocks(Containers::ArrayView engines, Contain return; } - for(Int& gear : gears) { + for(Int gear : gears) { if(_engineNodes.find(gear) != _engineNodes.end()) { _engineNodes.at(gear).setState(Node::State::Unlocked); } -- 2.39.2 From e786cf2d7a04b200b00095f871813a8ada96b65a Mon Sep 17 00:00:00 2001 From: William JCM Date: Tue, 3 Aug 2021 20:40:42 +0200 Subject: [PATCH 14/22] ResearchTree: add functions to read OS and arch unlocks. Now the set is complete. --- src/ResearchTree/ResearchTree.cpp | 46 +++++++++++++++++++++++++++++++ src/ResearchTree/ResearchTree.h | 2 ++ 2 files changed, 48 insertions(+) diff --git a/src/ResearchTree/ResearchTree.cpp b/src/ResearchTree/ResearchTree.cpp index bda6279..ed7093f 100644 --- a/src/ResearchTree/ResearchTree.cpp +++ b/src/ResearchTree/ResearchTree.cpp @@ -401,6 +401,52 @@ void ResearchTree::readEngineUnlocks(Containers::ArrayView engines, Contain } } +void ResearchTree::readOSUnlocks(Containers::ArrayView os, Containers::ArrayView modules) { + if(os == nullptr || os.size() == 0) { + Utility::Error{} << "OSes can't be empty"; + return; + } + + for(Int os_id : os) { + if(_osNodes.find(os_id) != _osNodes.end()) { + _osNodes.at(os_id).setState(Node::State::Unlocked); + } + } + + if(modules == nullptr || modules.size() == 0) { + return; + } + + for(Int module : modules) { + if(_osNodes.find(module) != _osNodes.end()) { + _osNodes.at(module).setState(Node::State::Unlocked); + } + } +} + +void ResearchTree::readArchUnlocks(Containers::ArrayView archs, Containers::ArrayView techs) { + if(archs == nullptr || archs.size() == 0) { + Utility::Error{} << "Archs can't be empty"; + return; + } + + for(Int arch : archs) { + if(_archNodes.find(arch) != _archNodes.end()) { + _archNodes.at(arch).setState(Node::State::Unlocked); + } + } + + if(techs == nullptr || techs.size() == 0) { + return; + } + + for(Int tech : techs) { + if(_archNodes.find(tech) != _archNodes.end()) { + _archNodes.at(tech).setState(Node::State::Unlocked); + } + } +} + auto ResearchTree::getEngineRootNode() -> Node& { return _engineNodes.at(VerseEngine); } diff --git a/src/ResearchTree/ResearchTree.h b/src/ResearchTree/ResearchTree.h index 6f488af..2989453 100644 --- a/src/ResearchTree/ResearchTree.h +++ b/src/ResearchTree/ResearchTree.h @@ -99,6 +99,8 @@ class ResearchTree { void generateArchTree(); void readEngineUnlocks(Containers::ArrayView engines, Containers::ArrayView gears = nullptr); + void readOSUnlocks(Containers::ArrayView os, Containers::ArrayView modules = nullptr); + void readArchUnlocks(Containers::ArrayView archs, Containers::ArrayView techs = nullptr); auto getEngineRootNode() -> Node&; auto getOSRootNode() -> Node&; -- 2.39.2 From 55b15381c6c04e99d9b81de80019a6268afb93c7 Mon Sep 17 00:00:00 2001 From: William JCM Date: Tue, 3 Aug 2021 23:00:53 +0200 Subject: [PATCH 15/22] ResearchTree: use a macro to add nodes. This will look better, IMO. --- src/ResearchTree/ResearchTree.cpp | 127 ++++++++++++++++-------------- 1 file changed, 67 insertions(+), 60 deletions(-) diff --git a/src/ResearchTree/ResearchTree.cpp b/src/ResearchTree/ResearchTree.cpp index ed7093f..2ec4166 100644 --- a/src/ResearchTree/ResearchTree.cpp +++ b/src/ResearchTree/ResearchTree.cpp @@ -270,61 +270,63 @@ void ResearchTree::generateEngineTree() { "Redirection of power into fuel management for more power and acceleration.", "Power +16, Acceleration +50", ""}); - _engineNodes.at(VerseEngine).addChild(_engineNodes.at(MetalPlatings1)); - _engineNodes.at(VerseEngine).addChild(_engineNodes.at(HeatTurbines1)); - _engineNodes.at(VerseEngine).addChild(_engineNodes.at(LoadedEngine)); - _engineNodes.at(LoadedEngine).addChild(_engineNodes.at(Microcontroller1)); - _engineNodes.at(LoadedEngine).addChild(_engineNodes.at(CombustionController1)); - _engineNodes.at(MetalPlatings1).addChild(_engineNodes.at(ModAlloyEngine)); - _engineNodes.at(HeatTurbines1).addChild(_engineNodes.at(ChargedEngine)); - _engineNodes.at(Microcontroller1).addChild(_engineNodes.at(ChargedEngine)); - _engineNodes.at(CombustionController1).addChild(_engineNodes.at(ReinforcedLoadedEngine)); - _engineNodes.at(ModAlloyEngine).addChild(_engineNodes.at(MetalPlatings2)); - _engineNodes.at(ModAlloyEngine).addChild(_engineNodes.at(HeatTurbines2)); - _engineNodes.at(ChargedEngine).addChild(_engineNodes.at(HeatTurbines2)); - _engineNodes.at(ChargedEngine).addChild(_engineNodes.at(Microcontroller2)); - _engineNodes.at(ChargedEngine).addChild(_engineNodes.at(WeaponsCargo1)); - _engineNodes.at(ReinforcedLoadedEngine).addChild(_engineNodes.at(CombustionController2)); - _engineNodes.at(ReinforcedLoadedEngine).addChild(_engineNodes.at(PoweredRewiring1)); - _engineNodes.at(ReinforcedLoadedEngine).addChild(_engineNodes.at(HeavyImpactsEnabler)); - _engineNodes.at(MetalPlatings2).addChild(_engineNodes.at(ModSteelEngine)); - _engineNodes.at(HeatTurbines2).addChild(_engineNodes.at(SuperchargedEngine)); - _engineNodes.at(Microcontroller2).addChild(_engineNodes.at(SuperchargedEngine)); - _engineNodes.at(WeaponsCargo1).addChild(_engineNodes.at(SuperchargedEngine)); - _engineNodes.at(CombustionController2).addChild(_engineNodes.at(NecriumAlloyEngine)); - _engineNodes.at(PoweredRewiring1).addChild(_engineNodes.at(NecriumAlloyEngine)); - _engineNodes.at(ModSteelEngine).addChild(_engineNodes.at(MetalPlatings3)); - _engineNodes.at(ModSteelEngine).addChild(_engineNodes.at(HeatTurbines3)); - _engineNodes.at(SuperchargedEngine).addChild(_engineNodes.at(HeatTurbines3)); - _engineNodes.at(SuperchargedEngine).addChild(_engineNodes.at(Microcontroller3)); - _engineNodes.at(SuperchargedEngine).addChild(_engineNodes.at(WeaponsCargo2)); - _engineNodes.at(NecriumAlloyEngine).addChild(_engineNodes.at(WeaponsCargo2)); - _engineNodes.at(NecriumAlloyEngine).addChild(_engineNodes.at(CombustionController3)); - _engineNodes.at(NecriumAlloyEngine).addChild(_engineNodes.at(PoweredRewiring2)); - _engineNodes.at(MetalPlatings3).addChild(_engineNodes.at(ModLunariteEngine)); - _engineNodes.at(HeatTurbines3).addChild(_engineNodes.at(ChargedLunariteEngine)); - _engineNodes.at(Microcontroller3).addChild(_engineNodes.at(ChargedLunariteEngine)); - _engineNodes.at(WeaponsCargo2).addChild(_engineNodes.at(ChargedLunariteEngine)); - _engineNodes.at(CombustionController3).addChild(_engineNodes.at(LunariteEngine)); - _engineNodes.at(PoweredRewiring2).addChild(_engineNodes.at(LunariteEngine)); - _engineNodes.at(ModLunariteEngine).addChild(_engineNodes.at(InfusedEngine)); - _engineNodes.at(ModLunariteEngine).addChild(_engineNodes.at(MetalPlatings4)); - _engineNodes.at(ChargedLunariteEngine).addChild(_engineNodes.at(HeatTurbines4)); - _engineNodes.at(ChargedLunariteEngine).addChild(_engineNodes.at(Microcontroller4)); - _engineNodes.at(ChargedLunariteEngine).addChild(_engineNodes.at(WeaponsCargo3)); - _engineNodes.at(LunariteEngine).addChild(_engineNodes.at(CombustionController4)); - _engineNodes.at(LunariteEngine).addChild(_engineNodes.at(PoweredRewiring3)); - _engineNodes.at(InfusedEngine).addChild(_engineNodes.at(ArmouredCargo1)); - _engineNodes.at(InfusedEngine).addChild(_engineNodes.at(ArmouredFuelTank1)); - _engineNodes.at(MetalPlatings4).addChild(_engineNodes.at(ArmouredCargo1)); - _engineNodes.at(MetalPlatings4).addChild(_engineNodes.at(ArmouredFuelTank1)); - _engineNodes.at(HeatTurbines4).addChild(_engineNodes.at(ExtraCapacity1)); - _engineNodes.at(Microcontroller4).addChild(_engineNodes.at(ExtraCapacity1)); - _engineNodes.at(WeaponsCargo3).addChild(_engineNodes.at(ExtraCapacity1)); - _engineNodes.at(CombustionController4).addChild(_engineNodes.at(HighmetalEngine)); - _engineNodes.at(CombustionController4).addChild(_engineNodes.at(PowerRedirector1)); - _engineNodes.at(PoweredRewiring3).addChild(_engineNodes.at(HighmetalEngine)); - _engineNodes.at(PoweredRewiring3).addChild(_engineNodes.at(PowerRedirector1)); + #define engineAddChild(parent, child) _engineNodes.at(parent).addChild(_engineNodes.at(child)); + engineAddChild(VerseEngine, MetalPlatings1) + engineAddChild(VerseEngine, HeatTurbines1) + engineAddChild(VerseEngine, LoadedEngine) + engineAddChild(LoadedEngine, Microcontroller1) + engineAddChild(LoadedEngine, CombustionController1) + engineAddChild(MetalPlatings1, ModAlloyEngine) + engineAddChild(HeatTurbines1, ChargedEngine) + engineAddChild(Microcontroller1, ChargedEngine) + engineAddChild(CombustionController1, ReinforcedLoadedEngine) + engineAddChild(ModAlloyEngine, MetalPlatings2) + engineAddChild(ModAlloyEngine, HeatTurbines2) + engineAddChild(ChargedEngine, HeatTurbines2) + engineAddChild(ChargedEngine, Microcontroller2) + engineAddChild(ChargedEngine, WeaponsCargo1) + engineAddChild(ReinforcedLoadedEngine, CombustionController2) + engineAddChild(ReinforcedLoadedEngine, PoweredRewiring1) + engineAddChild(ReinforcedLoadedEngine, HeavyImpactsEnabler) + engineAddChild(MetalPlatings2, ModSteelEngine) + engineAddChild(HeatTurbines2, SuperchargedEngine) + engineAddChild(Microcontroller2, SuperchargedEngine) + engineAddChild(WeaponsCargo1, SuperchargedEngine) + engineAddChild(CombustionController2, NecriumAlloyEngine) + engineAddChild(PoweredRewiring1, NecriumAlloyEngine) + engineAddChild(ModSteelEngine, MetalPlatings3) + engineAddChild(ModSteelEngine, HeatTurbines3) + engineAddChild(SuperchargedEngine, HeatTurbines3) + engineAddChild(SuperchargedEngine, Microcontroller3) + engineAddChild(SuperchargedEngine, WeaponsCargo2) + engineAddChild(NecriumAlloyEngine, WeaponsCargo2) + engineAddChild(NecriumAlloyEngine, CombustionController3) + engineAddChild(NecriumAlloyEngine, PoweredRewiring2) + engineAddChild(MetalPlatings3, ModLunariteEngine) + engineAddChild(HeatTurbines3, ChargedLunariteEngine) + engineAddChild(Microcontroller3, ChargedLunariteEngine) + engineAddChild(WeaponsCargo2, ChargedLunariteEngine) + engineAddChild(CombustionController3, LunariteEngine) + engineAddChild(PoweredRewiring2, LunariteEngine) + engineAddChild(ModLunariteEngine, InfusedEngine) + engineAddChild(ModLunariteEngine, MetalPlatings4) + engineAddChild(ChargedLunariteEngine, HeatTurbines4) + engineAddChild(ChargedLunariteEngine, Microcontroller4) + engineAddChild(ChargedLunariteEngine, WeaponsCargo3) + engineAddChild(LunariteEngine, CombustionController4) + engineAddChild(LunariteEngine, PoweredRewiring3) + engineAddChild(InfusedEngine, ArmouredCargo1) + engineAddChild(InfusedEngine, ArmouredFuelTank1) + engineAddChild(MetalPlatings4, ArmouredCargo1) + engineAddChild(MetalPlatings4, ArmouredFuelTank1) + engineAddChild(HeatTurbines4, ExtraCapacity1) + engineAddChild(Microcontroller4, ExtraCapacity1) + engineAddChild(WeaponsCargo3, ExtraCapacity1) + engineAddChild(CombustionController4, HighmetalEngine) + engineAddChild(CombustionController4, PowerRedirector1) + engineAddChild(PoweredRewiring3, HighmetalEngine) + engineAddChild(PoweredRewiring3, PowerRedirector1) + #undef engineAddChild _engineNodes.at(VerseEngine).setState(Node::State::Unlocked); } @@ -356,11 +358,13 @@ void ResearchTree::generateOSTree() { "Controlling module that helps in stabilisation for higher accuracy and reload speed.", "Accuracy +2, Fuel burn rate +50, Magazine reload +25, Energy recharge +33", ""}); - _osNodes.at(NeuralOS).addChild(_osNodes.at(Shields1)); - _osNodes.at(NeuralOS).addChild(_osNodes.at(Enhancements1)); - _osNodes.at(NeuralOS).addChild(_osNodes.at(ExoSkelOS)); - _osNodes.at(ExoSkelOS).addChild(_osNodes.at(FuelSave1)); - _osNodes.at(ExoSkelOS).addChild(_osNodes.at(LongRange1)); + #define osAddChild(parent, child) _osNodes.at(parent).addChild(_osNodes.at(child)); + osAddChild(NeuralOS, Shields1) + osAddChild(NeuralOS, Enhancements1) + osAddChild(NeuralOS, ExoSkelOS) + osAddChild(ExoSkelOS, FuelSave1) + osAddChild(ExoSkelOS, LongRange1) + #undef osAddChild _osNodes.at(NeuralOS).setState(Node::State::Unlocked); } @@ -375,6 +379,9 @@ void ResearchTree::generateArchTree() { "Durability +300, Shield +200, Physical damage +600, Piercing damage +300, Plasma damage +300", ""}); + #define archAddChild(parent, child) _archNodes.at(parent).addChild(_archNodes.at(child)); + #undef archAddChild + _archNodes.at(StandardFrame).setState(Node::State::Unlocked); } -- 2.39.2 From d9ca0f3c8345c0b05c19674bfb4440013531506c Mon Sep 17 00:00:00 2001 From: William JCM Date: Sat, 7 Aug 2021 14:48:18 +0200 Subject: [PATCH 16/22] SaveTool: fix a node styling issue. Unlocked children of locked nodes, as well as tooltips for locked nodes, used the "disabled text" colour when they shouldn't. --- src/SaveTool/SaveTool_MainManager.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/SaveTool/SaveTool_MainManager.cpp b/src/SaveTool/SaveTool_MainManager.cpp index ec1fc1d..78eda67 100644 --- a/src/SaveTool/SaveTool_MainManager.cpp +++ b/src/SaveTool/SaveTool_MainManager.cpp @@ -500,6 +500,9 @@ void SaveTool::drawNode(Node& node) { } if(has_children) { bool open = ImGui::TreeNodeEx(node.name(), ImGuiTreeNodeFlags_SpanAvailWidth|(node.state() == Node::State::Unlocked ? ImGuiTreeNodeFlags_Selected : 0)); + if(node.state() == Node::State::Unavailable) { + ImGui::PopStyleColor(); + } nodeTooltip(); if(open) { for(Node* child : node.children()) { @@ -511,11 +514,11 @@ void SaveTool::drawNode(Node& node) { else { ImGui::TreeNodeEx(node.name(), ImGuiTreeNodeFlags_SpanAvailWidth|ImGuiTreeNodeFlags_Leaf|ImGuiTreeNodeFlags_NoTreePushOnOpen| ImGuiTreeNodeFlags_Bullet|(node.state() == Node::State::Unlocked ? ImGuiTreeNodeFlags_Selected : 0)); + if(node.state() == Node::State::Unavailable) { + ImGui::PopStyleColor(); + } nodeTooltip(); } - if(node.state() == Node::State::Unavailable) { - ImGui::PopStyleColor(); - } } void SaveTool::drawMassManager() { -- 2.39.2 From 59c6f2d51f28866fdf8aea459ee4f89e469129be Mon Sep 17 00:00:00 2001 From: William JCM Date: Sat, 7 Aug 2021 14:52:50 +0200 Subject: [PATCH 17/22] NodeIDs: fixed an enumerator's name. --- src/ResearchTree/NodeIDs.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ResearchTree/NodeIDs.h b/src/ResearchTree/NodeIDs.h index b99eeb9..fd0ca96 100644 --- a/src/ResearchTree/NodeIDs.h +++ b/src/ResearchTree/NodeIDs.h @@ -142,7 +142,7 @@ enum OSIDs: Int { SpartoiOS, SustainableShields4, Shields5, - SustainableRecharger5, + SustainableRecharger4, Enhancements5, FuelSave5, LongRange5, -- 2.39.2 From 609404d181eee05eea5f506838a0ad9a50adb5a5 Mon Sep 17 00:00:00 2001 From: William JCM Date: Sat, 7 Aug 2021 14:54:09 +0200 Subject: [PATCH 18/22] NodeIDs: fix an enumerator's name. --- src/ResearchTree/NodeIDs.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ResearchTree/NodeIDs.h b/src/ResearchTree/NodeIDs.h index fd0ca96..7846704 100644 --- a/src/ResearchTree/NodeIDs.h +++ b/src/ResearchTree/NodeIDs.h @@ -97,7 +97,7 @@ enum OSIDs: Int { ImprovedNeuralOS, EnhancedSkeletonOS, ExtendedArtsLibrary, - SustainableShield1, + SustainableShields1, Shields2, SustainableRecharger1, Enhancements2, -- 2.39.2 From 7cfb8bbbcbaeabd017c72bfc97b2c1e45178df97 Mon Sep 17 00:00:00 2001 From: William JCM Date: Sat, 7 Aug 2021 15:13:51 +0200 Subject: [PATCH 19/22] SaveTool: read OS and arch unlocks on tree initialisation. --- src/SaveTool/SaveTool_MainManager.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/SaveTool/SaveTool_MainManager.cpp b/src/SaveTool/SaveTool_MainManager.cpp index 78eda67..97018fa 100644 --- a/src/SaveTool/SaveTool_MainManager.cpp +++ b/src/SaveTool/SaveTool_MainManager.cpp @@ -402,8 +402,10 @@ void SaveTool::drawResearchTree() { _tree->readEngineUnlocks(_currentProfile->engineInventory(), _currentProfile->gearInventory()); _tree->generateOSTree(); + _tree->readOSUnlocks(_currentProfile->osInventory(), _currentProfile->moduleInventory()); _tree->generateArchTree(); + _tree->readArchUnlocks(_currentProfile->archInventory(), _currentProfile->techInventory()); } if(ImGui::BeginTabBar("##TreeTabBar")) { -- 2.39.2 From 08c1aa105055526f6084ac980c493f9b83893773 Mon Sep 17 00:00:00 2001 From: William JCM Date: Sat, 7 Aug 2021 15:29:00 +0200 Subject: [PATCH 20/22] SaveTool: refresh unlocks when profile is updated. --- src/SaveTool/SaveTool.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/SaveTool/SaveTool.cpp b/src/SaveTool/SaveTool.cpp index 69f7eb1..b79251f 100644 --- a/src/SaveTool/SaveTool.cpp +++ b/src/SaveTool/SaveTool.cpp @@ -190,6 +190,8 @@ void SaveTool::handleFileAction(efsw::WatchID watch_id, _currentProfile->refreshValues(); if(_tree) { _tree->readEngineUnlocks(_currentProfile->engineInventory(), _currentProfile->gearInventory()); + _tree->readOSUnlocks(_currentProfile->osInventory(), _currentProfile->moduleInventory()); + _tree->readArchUnlocks(_currentProfile->archInventory(), _currentProfile->techInventory()); } } else if(Utility::String::endsWith(filename, _currentProfile->steamId() + ".sav")) { -- 2.39.2 From af3e32d9dee5c1e4e88b34319976a960a1970e47 Mon Sep 17 00:00:00 2001 From: William JCM Date: Sat, 7 Aug 2021 15:29:24 +0200 Subject: [PATCH 21/22] ResearchTree: add OS T2 nodes and IDs. --- src/ResearchTree/NodeIDs.h | 22 +++++------ src/ResearchTree/ResearchTree.cpp | 62 ++++++++++++++++++++++++++++--- 2 files changed, 68 insertions(+), 16 deletions(-) diff --git a/src/ResearchTree/NodeIDs.h b/src/ResearchTree/NodeIDs.h index 7846704..2e0bd2b 100644 --- a/src/ResearchTree/NodeIDs.h +++ b/src/ResearchTree/NodeIDs.h @@ -93,17 +93,17 @@ enum OSIDs: Int { LongRange1 = 400030, // Tier 2 - SparkOS, - ImprovedNeuralOS, - EnhancedSkeletonOS, - ExtendedArtsLibrary, - SustainableShields1, - Shields2, - SustainableRecharger1, - Enhancements2, - FuelSave2, - LongRange2, - EmpoweredArtsLibrary, + SparkOS = 310010, + ImprovedNeuralOS = 310050, + EnhancedSkeletonOS = 310030, + ExtendedArtsLibrary = 310100, + SustainableShields1 = 410011, + Shields2 = 410010, + SustainableRecharger1 = 410052, + Enhancements2 = 410050, + FuelSave2 = 410051, + LongRange2 = 410030, + EmpoweredArtsLibrary = 310101, //Tier 3 BlazeOS, diff --git a/src/ResearchTree/ResearchTree.cpp b/src/ResearchTree/ResearchTree.cpp index 2ec4166..14e1dbe 100644 --- a/src/ResearchTree/ResearchTree.cpp +++ b/src/ResearchTree/ResearchTree.cpp @@ -358,12 +358,64 @@ void ResearchTree::generateOSTree() { "Controlling module that helps in stabilisation for higher accuracy and reload speed.", "Accuracy +2, Fuel burn rate +50, Magazine reload +25, Energy recharge +33", ""}); + // T2 + _osNodes.emplace(SparkOS, Node{Node::Type::OS, "Spark OS", 2, 3, + "An OS equipped with an enhanced AI for M.A.S.S. control called \"Spark\".", + "Accuracy +31, Shield +1872, Fuel burn rate +200, Magazine reload +54, Energy recharge +93, Shield recover +2040", + "Shield +3%"}); + _osNodes.emplace(ImprovedNeuralOS, Node{Node::Type::OS, "Improved Neural OS", 2, 3, + "An improved version of the Neural OS that improves synchronisation.", + "Accuracy +14, Shield +1296, Fuel burn rate +50, Magazine reload +68, Energy recharge +117, Shield recover +3230", + "Magazine reload +3%, Energy recharge +3%"}); + _osNodes.emplace(EnhancedSkeletonOS, Node{Node::Type::OS, "Enhanced Skeleton OS", 2, 3, + "An updated version of the ExoSkel OS that improves weight simulation.", + "Accuracy +59, Shield +1080, Fuel burn rate +300, Magazine reload +68, Energy recharge +117, Shield recover +765", + "Accuracy +3%"}); + _osNodes.emplace(ExtendedArtsLibrary, Node{Node::Type::OS, "Extended Arts Library", 2, 0, + "Enable the usage of Extended Combos in close combat attacks.", + "", ""}); + _osNodes.emplace(SustainableShields1, Node{Node::Type::Module, "Sustainable Shields 1", 2, 0, + "A module that efficiently converts energy into shields.", + "Shields +216", ""}); + _osNodes.emplace(Shields2, Node{Node::Type::Module, "Shields 2", 2, 0, + "Level 2 Module that helps in optimising shield usage.", + "Shield +180, Fuel burn rate +25, Shield recover +675", ""}); + _osNodes.emplace(SustainableRecharger1, Node{Node::Type::Module, "Sustainable Recharger 1", 2, 0, + "Energy-saving shield recharging module.", + "Shield recover +1350", ""}); + _osNodes.emplace(Enhancements2, Node{Node::Type::Module, "Enhancements 2", 2, 0, + "Level 2 Overall enhancement module.", + "Accuracy +3, Shield +108, Magazine reload +15, Energy recharge +19, Fuel burn rate -6, Shield recover +225", ""}); + _osNodes.emplace(FuelSave2, Node{Node::Type::Module, "Fuel Save 2", 2, 0, + "Level 2 Optimisation module for energy usage of the M.A.S.S. frame.", + "Fuel burn rate -12, Fuel recharge +7", ""}); + _osNodes.emplace(LongRange2, Node{Node::Type::Module, "Long Range 2", 2, 0, + "Level 2 Controlling module that helps in stabilisation for higher accuracy and reload speed.", + "Accuracy +5, Fuel burn rate +50, Magazine reload +31, Energy recharge +38", ""}); + _osNodes.emplace(EmpoweredArtsLibrary, Node{Node::Type::OS, "Empowered Arts Library", 2, 0, + "Enable the usage of Empowered Combos in close combat attacks.", + "", ""}); + #define osAddChild(parent, child) _osNodes.at(parent).addChild(_osNodes.at(child)); - osAddChild(NeuralOS, Shields1) - osAddChild(NeuralOS, Enhancements1) - osAddChild(NeuralOS, ExoSkelOS) - osAddChild(ExoSkelOS, FuelSave1) - osAddChild(ExoSkelOS, LongRange1) + osAddChild(NeuralOS, Shields1) + osAddChild(NeuralOS, Enhancements1) + osAddChild(NeuralOS, ExoSkelOS) + osAddChild(ExoSkelOS, FuelSave1) + osAddChild(ExoSkelOS, LongRange1) + osAddChild(Shields1, SparkOS) + osAddChild(Enhancements1, ImprovedNeuralOS) + osAddChild(FuelSave1, ImprovedNeuralOS) + osAddChild(LongRange1, EnhancedSkeletonOS) + osAddChild(SparkOS, SustainableShields1) + osAddChild(SparkOS, Shields2) + osAddChild(SparkOS, SustainableRecharger1) + osAddChild(ImprovedNeuralOS, SustainableRecharger1) + osAddChild(ImprovedNeuralOS, Enhancements2) + osAddChild(ImprovedNeuralOS, FuelSave2) + osAddChild(EnhancedSkeletonOS, FuelSave2) + osAddChild(EnhancedSkeletonOS, LongRange2) + osAddChild(EnhancedSkeletonOS, ExtendedArtsLibrary) + osAddChild(ExtendedArtsLibrary, EmpoweredArtsLibrary) #undef osAddChild _osNodes.at(NeuralOS).setState(Node::State::Unlocked); -- 2.39.2 From b765dcbea43b5dea8f3e96ca2bf33a5e53f6b3b4 Mon Sep 17 00:00:00 2001 From: William JCM Date: Sat, 7 Aug 2021 16:38:51 +0200 Subject: [PATCH 22/22] ResearchTree: add engine T5 nodes. --- src/ResearchTree/ResearchTree.cpp | 75 +++++++++++++++++++++++++++++++ 1 file changed, 75 insertions(+) diff --git a/src/ResearchTree/ResearchTree.cpp b/src/ResearchTree/ResearchTree.cpp index 14e1dbe..1fcc80a 100644 --- a/src/ResearchTree/ResearchTree.cpp +++ b/src/ResearchTree/ResearchTree.cpp @@ -270,6 +270,58 @@ void ResearchTree::generateEngineTree() { "Redirection of power into fuel management for more power and acceleration.", "Power +16, Acceleration +50", ""}); + // T5 + _engineNodes.emplace(AsteriteCarbonEngine, Node{Node::Type::Engine, "Asterite Carbon Engine", 5, 4, + "A modified version of carbon steel with additional metals alloyed into it. Surprisingly harder, but heavier.", + "Durability +5952, Power +130, Armour +544, Acceleration +75, Magazine load +62, Energy capacity +62", + "Durability +3%"}); + _engineNodes.emplace(ChargedAsteriteEngine, Node{Node::Type::Engine, "Charged Asterite Engine", 5, 4, + "Charged-up Asterite steel. Extremely high resistance for better acceleration.", + "Durability +4960, Power +130, Acceleration +300, Magazine load +62, Energy capacity +62, Fuel capacity +244", + "Acceleration +5"}); + _engineNodes.emplace(AsteriteSteelEngine, Node{Node::Type::Engine, "Asterite Steel Engine", 5, 4, + "Engine made of Asterite steel, a technology learnt from researching interstellar metals.", + "Durability +4960, Power +182, Armour +363, Acceleration +75, Magazine load +62, Energy capacity +62", + "Power +3%"}); + _engineNodes.emplace(MeldedEngine, Node{Node::Type::Engine, "Melded Engine", 5, 4, + "Instead of infusing armour platings, they are melded to the engine itself for greater performance.", + "Durability +8680, Power +104, Armour +435, Acceleration -50, Magazine load +50, Energy capacity +50", + "Durability +3%"}); + _engineNodes.emplace(MetalPlatings5, Node{Node::Type::Gear, "Metal Platings 5", 5, 0, + "Level 5 Metal plating that adds durability and armour to your engine.", + "Durability +840, Armour +91, Acceleration -15", ""}); + _engineNodes.emplace(HeatTurbines5, Node{Node::Type::Gear, "Heat Turbines 5", 5, 0, + "Level 5 Modified heat turbines to increase speed for a M.A.S.S.", + "Acceleration +75, Fuel capacity +74", ""}); + _engineNodes.emplace(Microcontroller5, Node{Node::Type::Gear, "Microcontroller 5", 5, 0, + "Level 5 Microchip that enhances various aspects of a M.A.S.S.", + "Durability +504, Power +13, Armour +38, Magazine load +9, Energy capacity +9, Fuel capacity +37", ""}); + _engineNodes.emplace(WeaponsCargo4, Node{Node::Type::Gear, "Weapons Cargo 4", 5, 0, + "Level 4 Added another cargo hold for ammo and energy recharger.", + "Magazine load +36, Energy capacity +36, Acceleration -40", ""}); + _engineNodes.emplace(CombustionController5, Node{Node::Type::Gear, "Combustion Controller 5", 5, 0, + "Level 5 Controlled combustion allows increased power generation through specific ignition.", + "Power +25, Magazine load +18, Energy capacity +18, Acceleration -25", ""}); + _engineNodes.emplace(PoweredRewiring4, Node{Node::Type::Gear, "Powered Rewiring 4", 5, 0, + "Level 4 Rewiring that efficiently improves power and engine durability.", + "Durability +840, Power +25", ""}); + _engineNodes.emplace(ArmouredCargo2, Node{Node::Type::Gear, "Armoured Cargo 2", 5, 0, + "Level 2 Added armoured platings for large cargo holds.", + "Armour +76, Magazine load +18, Energy capacity +18, Acceleration -40", ""}); + _engineNodes.emplace(ArmouredFuelTank2, Node{Node::Type::Gear, "Armoured Fuel Tank 2", 5, 0, + "Level 2 Added armoured platings for a large fuel tank.", + "Armour +76, Fuel capacity +37, Acceleration -15", ""}); + _engineNodes.emplace(ExtraCapacity2, Node{Node::Type::Gear, "Extra Capacity 2", 5, 0, + "Level 2 Space management with added capacity for more cargo holds and fuel.", + "Magazine load +18, Energy capacity +18, Fuel capacity +74, Acceleration -40", ""}); + _engineNodes.emplace(CastHighmetalEngine, Node{Node::Type::Engine, "Cast Highmetal Engine", 5, 4, + "An upgraded version of the highmetal material, casted into a complex mold for better performance.", + "Durability +4340, Power +234, Armour +318, Acceleration -50", + "Power +3%"}); + _engineNodes.emplace(PowerRedirector2, Node{Node::Type::Gear, "Power Redirector 2", 5, 0, + "Level 2 Redirection of power into fuel management for more power and acceleration.", + "Power +25, Acceleration +50", ""}); + #define engineAddChild(parent, child) _engineNodes.at(parent).addChild(_engineNodes.at(child)); engineAddChild(VerseEngine, MetalPlatings1) engineAddChild(VerseEngine, HeatTurbines1) @@ -326,6 +378,29 @@ void ResearchTree::generateEngineTree() { engineAddChild(CombustionController4, PowerRedirector1) engineAddChild(PoweredRewiring3, HighmetalEngine) engineAddChild(PoweredRewiring3, PowerRedirector1) + engineAddChild(ArmouredCargo1, AsteriteCarbonEngine) + engineAddChild(ArmouredFuelTank1, AsteriteCarbonEngine) + engineAddChild(ExtraCapacity1, ChargedAsteriteEngine) + engineAddChild(HighmetalEngine, AsteriteSteelEngine) + engineAddChild(PowerRedirector1, AsteriteSteelEngine) + engineAddChild(AsteriteCarbonEngine, MeldedEngine) + engineAddChild(AsteriteCarbonEngine, MetalPlatings5) + engineAddChild(ChargedAsteriteEngine, HeatTurbines5) + engineAddChild(ChargedAsteriteEngine, Microcontroller5) + engineAddChild(ChargedAsteriteEngine, WeaponsCargo4) + engineAddChild(AsteriteSteelEngine, CombustionController5) + engineAddChild(AsteriteSteelEngine, PoweredRewiring4) + engineAddChild(MeldedEngine, ArmouredCargo2) + engineAddChild(MeldedEngine, ArmouredFuelTank2) + engineAddChild(MetalPlatings5, ArmouredCargo2) + engineAddChild(MetalPlatings5, ArmouredFuelTank2) + engineAddChild(HeatTurbines5, ExtraCapacity2) + engineAddChild(Microcontroller5, ExtraCapacity2) + engineAddChild(WeaponsCargo4, ExtraCapacity2) + engineAddChild(CombustionController5, CastHighmetalEngine) + engineAddChild(CombustionController5, PowerRedirector2) + engineAddChild(PoweredRewiring4, CastHighmetalEngine) + engineAddChild(PoweredRewiring4, PowerRedirector2) #undef engineAddChild _engineNodes.at(VerseEngine).setState(Node::State::Unlocked); -- 2.39.2