278 lines
12 KiB
C++
278 lines
12 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;
|
|
}
|
|
|
|
_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<Int> engines, Containers::ArrayView<Int> 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);
|
|
}
|