1 #include "Special.h"
2 
3 #include "Condition.h"
4 #include "Effect.h"
5 #include "UniverseObject.h"
6 #include "ValueRef.h"
7 #include "../util/OptionsDB.h"
8 #include "../util/Logger.h"
9 #include "../util/AppInterface.h"
10 #include "../util/CheckSums.h"
11 #include "../util/ScopedTimer.h"
12 #include "../util/i18n.h"
13 
14 #include <boost/filesystem/fstream.hpp>
15 
SpecialsManager()16 SpecialsManager::SpecialsManager()
17 {}
18 
~SpecialsManager()19 SpecialsManager::~SpecialsManager()
20 {}
21 
SpecialNames() const22 std::vector<std::string> SpecialsManager::SpecialNames() const {
23     CheckPendingSpecialsTypes();
24     std::vector<std::string> retval;
25     for (const auto& entry : m_specials) {
26         retval.push_back(entry.first);
27     }
28     return retval;
29 }
30 
GetSpecial(const std::string & name) const31 const Special* SpecialsManager::GetSpecial(const std::string& name) const {
32     CheckPendingSpecialsTypes();
33     auto it = m_specials.find(name);
34     return it != m_specials.end() ? it->second.get() : nullptr;
35 }
36 
GetCheckSum() const37 unsigned int SpecialsManager::GetCheckSum() const {
38     CheckPendingSpecialsTypes();
39     unsigned int retval{0};
40     for (auto const& name_type_pair : m_specials)
41         CheckSums::CheckSumCombine(retval, name_type_pair);
42     CheckSums::CheckSumCombine(retval, m_specials.size());
43     DebugLogger() << "SpecialsManager checksum: " << retval;
44     return retval;
45 }
46 
SetSpecialsTypes(Pending::Pending<SpecialsTypeMap> && future)47 void SpecialsManager::SetSpecialsTypes(Pending::Pending<SpecialsTypeMap>&& future)
48 { m_pending_types = std::move(future); }
49 
CheckPendingSpecialsTypes() const50 void SpecialsManager::CheckPendingSpecialsTypes() const {
51     if (!m_pending_types)
52         return;
53 
54     Pending::SwapPending(m_pending_types, m_specials);
55 }
56 
GetSpecialsManager()57 SpecialsManager& GetSpecialsManager() {
58     static SpecialsManager special_manager;
59     return special_manager;
60 }
61 
62 /////////////////////////////////////////////////
63 // Special                                     //
64 /////////////////////////////////////////////////
Special(const std::string & name,const std::string & description,std::unique_ptr<ValueRef::ValueRef<double>> && stealth,std::vector<std::unique_ptr<Effect::EffectsGroup>> && effects,double spawn_rate,int spawn_limit,std::unique_ptr<ValueRef::ValueRef<double>> && initial_capaicty,std::unique_ptr<Condition::Condition> && location,const std::string & graphic)65 Special::Special(const std::string& name, const std::string& description,
66                  std::unique_ptr<ValueRef::ValueRef<double>>&& stealth,
67                  std::vector<std::unique_ptr<Effect::EffectsGroup>>&& effects,
68                  double spawn_rate /*= 1.0*/, int spawn_limit /*= 99999*/,
69                  std::unique_ptr<ValueRef::ValueRef<double>>&& initial_capaicty /*= nullptr*/,
70                  std::unique_ptr<Condition::Condition>&& location /*= nullptr*/,
71                  const std::string& graphic /*= ""*/) :
72     m_name(name),
73     m_description(description),
74     m_stealth(std::move(stealth)),
75     m_effects(),
76     m_spawn_rate(spawn_rate),
77     m_spawn_limit(spawn_limit),
78     m_initial_capacity(std::move(initial_capaicty)),
79     m_location(std::move(location)),
80     m_graphic(graphic)
81 {
82     for (auto&& effect : effects)
83         m_effects.emplace_back(std::move(effect));
84 
85     Init();
86 }
87 
~Special()88 Special::~Special()
89 {}
90 
Description() const91 std::string Special::Description() const {
92     std::stringstream result;
93 
94     result << UserString(m_description) << "\n";
95 
96     for (auto& effect : m_effects) {
97         const std::string& description = effect->GetDescription();
98 
99         if (!description.empty()) {
100             result << "\n" << UserString(description) << "\n";
101         }
102     }
103 
104     return result.str();
105 }
106 
Init()107 void Special::Init() {
108     if (m_stealth)
109         m_stealth->SetTopLevelContent(m_name);
110     for (auto& effect : m_effects) {
111         effect->SetTopLevelContent(m_name);
112     }
113     if (m_initial_capacity)
114         m_initial_capacity->SetTopLevelContent(m_name);
115     if (m_location)
116         m_location->SetTopLevelContent(m_name);
117 }
118 
Dump(unsigned short ntabs) const119 std::string Special::Dump(unsigned short ntabs) const {
120     std::string retval = DumpIndent(ntabs) + "Special\n";
121     retval += DumpIndent(ntabs+1) + "name = \"" + m_name + "\"\n";
122     retval += DumpIndent(ntabs+1) + "description = \"" + m_description + "\"\n";
123 
124     if (m_stealth)
125         retval += DumpIndent(ntabs+1) + "stealth = " + m_stealth->Dump(ntabs+1) + "\n";
126 
127     retval += DumpIndent(ntabs+1) + "spawnrate = " + std::to_string(m_spawn_rate) + "\n"
128            +  DumpIndent(ntabs+1) + "spawnlimit = " + std::to_string(m_spawn_limit) + "\n";
129 
130     if (m_initial_capacity) {
131         retval += DumpIndent(ntabs+1) + "initialcapacity = ";
132         retval += m_initial_capacity->Dump(ntabs+2);
133     }
134 
135     if (m_location) {
136         retval += DumpIndent(ntabs+1) + "location =\n";
137         retval += m_location->Dump(ntabs+2);
138     }
139 
140     if (m_effects.size() == 1) {
141         retval += DumpIndent(ntabs+1) + "effectsgroups =\n";
142         retval += m_effects[0]->Dump(ntabs+2);
143     } else {
144         retval += DumpIndent(ntabs+1) + "effectsgroups = [\n";
145         for (auto& effect : m_effects)
146             retval += effect->Dump(ntabs+2);
147         retval += DumpIndent(ntabs+1) + "]\n";
148     }
149     retval += DumpIndent(ntabs+1) + "graphic = \"" + m_graphic + "\"\n";
150     return retval;
151 }
152 
InitialCapacity(int object_id) const153 float Special::InitialCapacity(int object_id) const {
154     if (!m_initial_capacity)
155         return 0.0f;
156 
157     auto obj = Objects().get(object_id);
158     if (!obj)
159         return 0.0f;
160 
161     return m_initial_capacity->Eval(ScriptingContext(obj));
162 }
163 
GetCheckSum() const164 unsigned int Special::GetCheckSum() const {
165     unsigned int retval{0};
166 
167     CheckSums::CheckSumCombine(retval, m_name);
168     CheckSums::CheckSumCombine(retval, m_description);
169     CheckSums::CheckSumCombine(retval, m_stealth);
170     CheckSums::CheckSumCombine(retval, m_effects);
171     CheckSums::CheckSumCombine(retval, m_initial_capacity);
172     CheckSums::CheckSumCombine(retval, m_location);
173     CheckSums::CheckSumCombine(retval, m_graphic);
174 
175     return retval;
176 }
177 
GetSpecial(const std::string & name)178 const Special* GetSpecial(const std::string& name)
179 { return GetSpecialsManager().GetSpecial(name); }
180 
SpecialNames()181 std::vector<std::string> SpecialNames()
182 { return GetSpecialsManager().SpecialNames(); }
183