MassBuilderSaveTool/src/ResearchTree/ResearchTree.cpp

461 lines
27 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 "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<Node*> {
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;
}
// 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",
"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", ""});
// 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.",
"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 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.",
"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", ""});
// 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));
_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));
_engineNodes.at(VerseEngine).setState(Node::State::Unlocked);
}
void ResearchTree::generateOSTree() {
if(!_osNodes.empty()) {
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);
}
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<Int> engines, Containers::ArrayView<Int> gears) {
if(engines == nullptr || engines.size() == 0) {
Utility::Error{} << "Engines can't be empty";
return;
}
for(Int engine : engines) {
if(_engineNodes.find(engine) != _engineNodes.end()) {
_engineNodes.at(engine).setState(Node::State::Unlocked);
}
}
if(gears == nullptr || gears.size() == 0) {
return;
}
for(Int gear : gears) {
if(_engineNodes.find(gear) != _engineNodes.end()) {
_engineNodes.at(gear).setState(Node::State::Unlocked);
}
}
}
void ResearchTree::readOSUnlocks(Containers::ArrayView<Int> os, Containers::ArrayView<Int> 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<Int> archs, Containers::ArrayView<Int> 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);
}
auto ResearchTree::getOSRootNode() -> Node& {
return _osNodes.at(NeuralOS);
}
auto ResearchTree::getArchRootNode() -> Node& {
return _archNodes.at(StandardFrame);
}