1 #ifndef _BuildingType_h_
2 #define _BuildingType_h_
3 
4 
5 #include "CommonParams.h"
6 #include "../util/Export.h"
7 #include "../util/Pending.h"
8 
9 
10 namespace Effect {
11     class EffectsGroup;
12 }
13 namespace Condition {
14     struct Condition;
15 }
16 namespace ValueRef {
17     template <typename T>
18     struct ValueRef;
19 }
20 
21 
22 //! Class to specify a kind of building.
23 //!
24 //! Each building type must have a unique @a name string, by which it can be
25 //! looked up using GetBuildingType(...).
26 class FO_COMMON_API BuildingType {
27 public:
28     BuildingType(const std::string& name,
29                  const std::string& description,
30                  CommonParams& common_params,
31                  CaptureResult capture_result,
32                  const std::string& icon);
33 
34     ~BuildingType();
35 
36     //! Returns the unique name for this type of building
37     auto Name() const -> const std::string&
38     { return m_name; }
39 
40     //! Returns a text description of this type of building
41     auto Description() const -> const std::string&
42     { return m_description; }
43 
44     //! Returns a data file format representation of this object
45     auto Dump(unsigned short ntabs = 0) const -> std::string;
46 
47     //! Returns true if the production cost and time are invariant (does not
48     //! depend on) the location
49     auto ProductionCostTimeLocationInvariant() const -> bool;
50 
51     //! Returns the number of production points required to build this building
52     //! at this location by this empire
53     auto ProductionCost(int empire_id, int location_id) const -> float;
54 
55     //! Returns the maximum number of production points per turn that can be
56     //! spend on this building
57     auto PerTurnCost(int empire_id, int location_id) const -> float;
58 
59     //! Returns the number of turns required to build this building at this
60     //! location by this empire
61     auto ProductionTime(int empire_id, int location_id) const -> int;
62 
63     //! Returns the ValueRef that determines ProductionCost()
64     auto Cost() const -> const ValueRef::ValueRef<double>*
65     { return m_production_cost.get(); }
66 
67     //! Returns the ValueRef that determines ProductionTime()
68     auto Time() const -> const ValueRef::ValueRef<int>*
69     { return m_production_time.get(); }
70 
71     //! Returns whether this building type is producible by players and appears
72     //! on the production screen
73     auto Producible() const -> bool
74     { return m_producible; }
75 
76     auto ProductionMeterConsumption() const -> const ConsumptionMap<MeterType>&
77     { return m_production_meter_consumption; }
78 
79     auto ProductionSpecialConsumption() const -> const ConsumptionMap<std::string>&
80     { return m_production_special_consumption; }
81 
82     auto Tags() const -> const std::set<std::string>&
83     { return m_tags; }
84 
85     //! Returns the condition that determines the locations where this building
86     //! can be produced
87     auto Location() const -> const Condition::Condition*
88     { return m_location.get(); }
89 
90     //! Returns a condition that can be used by the UI to further filter (beyond
91     //! the Location() requirement) where this building will be presented for
92     //! enqueuing onto the production queue, to avoid clutter in the
93     //! BuildDesignatorWnd. Example usage: Buildings that are already enqueued
94     //! at a production location are hidden so they don't appear in the list of
95     //! available items that can be enqueued/produced (again) at that location.
96     auto EnqueueLocation() const -> const Condition::Condition*
97     { return m_enqueue_location.get(); }
98 
99     //! Returns the EffectsGroups that encapsulate the effects that buildings of
100     //! this type have when operational.
101     auto Effects() const -> const std::vector<std::shared_ptr<Effect::EffectsGroup>>&
102     { return m_effects; }
103 
104     //! Returns the name of the grapic file for this building type
105     auto Icon() const -> const std::string&
106     { return m_icon; }
107 
108     //! Returns true iff the empire with ID empire_id can produce this building
109     //! at the location with location_id
110     auto ProductionLocation(int empire_id, int location_id) const -> bool;
111 
112     //! Returns true iff the empire with ID empire_id meets the requirements of
113     //! the EnqueueLocation() UI filter method for this building at the
114     //! location with location_id
115     auto EnqueueLocation(int empire_id, int location_id) const -> bool;
116 
117     //! Returns CaptureResult for empire with ID @p to_empire_id capturing from
118     //! empire with IDs @p from_empire_id the planet (or other UniverseObject)
119     //! with id @p location_id on which this type of Building is located (if
120     //! @p as_production_item is false) or which is the location of a Production
121     //! Queue BuildItem for a building of this type (otherwise)
122     auto GetCaptureResult(int from_empire_id, int to_empire_id, int location_id, bool as_production_item) const -> CaptureResult
123     { return m_capture_result; }
124 
125     //! Returns a number, calculated from the contained data, which should be
126     //! different for different contained data, and must be the same for
127     //! the same contained data, and must be the same on different platforms
128     //! and executions of the program and the function. Useful to verify that
129     //! the parsed content is consistent without sending it all between
130     //! clients and server.
131     auto GetCheckSum() const -> unsigned int;
132 
133 private:
134     void Init();
135 
136     std::string                                         m_name;
137     std::string                                         m_description;
138     std::unique_ptr<ValueRef::ValueRef<double>>         m_production_cost;
139     std::unique_ptr<ValueRef::ValueRef<int>>            m_production_time;
140     bool                                                m_producible = true;
141     CaptureResult                                       m_capture_result;
142     std::set<std::string>                               m_tags;
143     ConsumptionMap<MeterType>                           m_production_meter_consumption;
144     ConsumptionMap<std::string>                         m_production_special_consumption;
145     std::unique_ptr<Condition::Condition>               m_location;
146     std::unique_ptr<Condition::Condition>               m_enqueue_location;
147     std::vector<std::shared_ptr<Effect::EffectsGroup>>  m_effects;
148     std::string                                         m_icon;
149 };
150 
151 //! Holds all FreeOrion BuildingType%s.  Types may be looked up by name.
152 class BuildingTypeManager {
153 public:
154     using container_type = std::map<std::string, std::unique_ptr<BuildingType>>;
155     using iterator = container_type::const_iterator;
156 
157     //! Returns the building type with the name @p name; you should use the
158     //! free function GetBuildingType(...) instead, mainly to save some typing.
159     auto GetBuildingType(const std::string& name) const -> const BuildingType*;
160 
161     auto NumBuildingTypes() const -> std::size_t { return m_building_types.size(); }
162 
163     //! iterator to the first building type
164     FO_COMMON_API auto begin() const -> iterator;
165 
166     //! iterator to the last + 1th building type
167     FO_COMMON_API auto end() const -> iterator;
168 
169     //! Returns the instance of this singleton class; you should use the free
170     //! function GetBuildingTypeManager() instead
171     static auto GetBuildingTypeManager() -> BuildingTypeManager&;
172 
173     //! Returns a number, calculated from the contained data, which should be
174     //! different for different contained data, and must be the same for
175     //! the same contained data, and must be the same on different platforms
176     //! and executions of the program and the function. Useful to verify that
177     //! the parsed content is consistent without sending it all between
178     //! clients and server.
179     auto GetCheckSum() const -> unsigned int;
180 
181     //! Sets building types to the future value of \p pending_building_types.
182     FO_COMMON_API void SetBuildingTypes(Pending::Pending<container_type>&& pending_building_types);
183 
184 private:
185     BuildingTypeManager();
186 
187     //! Assigns any m_pending_building_types to m_bulding_types.
188     void CheckPendingBuildingTypes() const;
189 
190     //! Future building type being parsed by parser.
191     //! Mutable so that it can be assigned to m_building_types when completed.
192     mutable boost::optional<Pending::Pending<container_type>> m_pending_building_types = boost::none;
193 
194     //! Map of building types identified by the BuildingType::Name.
195     //! mutable so that when the parse complete it can be updated.
196     mutable container_type m_building_types;
197 
198     static BuildingTypeManager* s_instance;
199 };
200 
201 //! Returns the singleton building type manager
202 FO_COMMON_API auto GetBuildingTypeManager() -> BuildingTypeManager&;
203 
204 //! Returns the BuildingType specification object for a building of type
205 //! @p name.  If no such BuildingType exists, nullptr is returned instead.
206 FO_COMMON_API auto GetBuildingType(const std::string& name) -> const BuildingType*;
207 
208 
209 #endif // _BuildingType_h_
210