1 #include "FieldType.h"
2
3 #include <boost/algorithm/string/case_conv.hpp>
4 #include "ConditionSource.h"
5 #include "Effects.h"
6 #include "Enums.h"
7 #include "ValueRefs.h"
8 #include "UniverseObject.h"
9 #include "../util/CheckSums.h"
10
11
12 namespace {
13 std::shared_ptr<Effect::EffectsGroup>
IncreaseMeter(MeterType meter_type,double increase)14 IncreaseMeter(MeterType meter_type, double increase) {
15 typedef std::vector<std::unique_ptr<Effect::Effect>> Effects;
16 auto scope = std::make_unique<Condition::Source>();
17 std::unique_ptr<Condition::Source> activation = nullptr;
18 auto vr =
19 std::make_unique<ValueRef::Operation<double>>(
20 ValueRef::PLUS,
21 std::make_unique<ValueRef::Variable<double>>(
22 ValueRef::EFFECT_TARGET_VALUE_REFERENCE, std::vector<std::string>()),
23 std::make_unique<ValueRef::Constant<double>>(increase)
24 );
25 auto effects = Effects();
26 effects.push_back(std::make_unique<Effect::SetMeter>(meter_type, std::move(vr)));
27 return std::make_shared<Effect::EffectsGroup>(std::move(scope), std::move(activation), std::move(effects));
28 }
29 }
30
31
FieldType(const std::string & name,const std::string & description,float stealth,const std::set<std::string> & tags,std::vector<std::unique_ptr<Effect::EffectsGroup>> && effects,const std::string & graphic)32 FieldType::FieldType(const std::string& name, const std::string& description,
33 float stealth, const std::set<std::string>& tags,
34 std::vector<std::unique_ptr<Effect::EffectsGroup>>&& effects,
35 const std::string& graphic) :
36 m_name(name),
37 m_description(description),
38 m_stealth(stealth),
39 m_tags(),
40 m_effects(),
41 m_graphic(graphic)
42 {
43 for (const std::string& tag : tags)
44 m_tags.insert(boost::to_upper_copy<std::string>(tag));
45
46 for (auto&& effect : effects)
47 m_effects.emplace_back(std::move(effect));
48
49 if (m_stealth != 0.0f)
50 m_effects.push_back(IncreaseMeter(METER_STEALTH, m_stealth));
51
52 for (auto& effect : m_effects) {
53 effect->SetTopLevelContent(m_name);
54 }
55 }
56
Dump(unsigned short ntabs) const57 std::string FieldType::Dump(unsigned short ntabs) const {
58 std::string retval = DumpIndent(ntabs) + "FieldType\n";
59 retval += DumpIndent(ntabs+1) + "name = \"" + m_name + "\"\n";
60 retval += DumpIndent(ntabs+1) + "description = \"" + m_description + "\"\n";
61 retval += DumpIndent(ntabs+1) + "location = \n";
62 if (m_effects.size() == 1) {
63 retval += DumpIndent(ntabs+1) + "effectsgroups =\n";
64 retval += m_effects[0]->Dump(ntabs+2);
65 } else {
66 retval += DumpIndent(ntabs+1) + "effectsgroups = [\n";
67 for (auto& effect : m_effects) {
68 retval += effect->Dump(ntabs+2);
69 }
70 retval += DumpIndent(ntabs+1) + "]\n";
71 }
72 retval += DumpIndent(ntabs+1) + "graphic = \"" + m_graphic + "\"\n";
73 return retval;
74 }
75
GetCheckSum() const76 unsigned int FieldType::GetCheckSum() const {
77 unsigned int retval{0};
78
79 CheckSums::CheckSumCombine(retval, m_name);
80 CheckSums::CheckSumCombine(retval, m_description);
81 CheckSums::CheckSumCombine(retval, m_stealth);
82 CheckSums::CheckSumCombine(retval, m_tags);
83 CheckSums::CheckSumCombine(retval, m_effects);
84 CheckSums::CheckSumCombine(retval, m_graphic);
85
86 DebugLogger() << "FieldTypeManager checksum: " << retval;
87 return retval;
88 }
89
90
91 FieldTypeManager* FieldTypeManager::s_instance = nullptr;
92
FieldTypeManager()93 FieldTypeManager::FieldTypeManager() {
94 if (s_instance)
95 throw std::runtime_error("Attempted to create more than one FieldTypeManager.");
96
97 // Only update the global pointer on sucessful construction.
98 s_instance = this;
99 }
100
GetFieldType(const std::string & name) const101 const FieldType* FieldTypeManager::GetFieldType(const std::string& name) const {
102 CheckPendingFieldTypes();
103 auto it = m_field_types.find(name);
104 return it != m_field_types.end() ? it->second.get() : nullptr;
105 }
106
begin() const107 FieldTypeManager::iterator FieldTypeManager::begin() const {
108 CheckPendingFieldTypes();
109 return m_field_types.begin();
110 }
111
end() const112 FieldTypeManager::iterator FieldTypeManager::end() const {
113 CheckPendingFieldTypes();
114 return m_field_types.end();
115 }
116
GetFieldTypeManager()117 FieldTypeManager& FieldTypeManager::GetFieldTypeManager() {
118 static FieldTypeManager manager;
119 return manager;
120 }
121
GetCheckSum() const122 unsigned int FieldTypeManager::GetCheckSum() const {
123 CheckPendingFieldTypes();
124 unsigned int retval{0};
125 for (auto const& name_type_pair : m_field_types)
126 CheckSums::CheckSumCombine(retval, name_type_pair);
127 CheckSums::CheckSumCombine(retval, m_field_types.size());
128
129 return retval;
130 }
131
SetFieldTypes(Pending::Pending<container_type> && future)132 void FieldTypeManager::SetFieldTypes(Pending::Pending<container_type>&& future)
133 { m_pending_types = std::move(future); }
134
CheckPendingFieldTypes() const135 void FieldTypeManager::CheckPendingFieldTypes() const
136 { Pending::SwapPending(m_pending_types, m_field_types); }
137
138
GetFieldTypeManager()139 FieldTypeManager& GetFieldTypeManager()
140 { return FieldTypeManager::GetFieldTypeManager(); }
141
GetFieldType(const std::string & name)142 const FieldType* GetFieldType(const std::string& name)
143 { return FieldTypeManager::GetFieldTypeManager().GetFieldType(name); }
144