1 #ifndef _ShipPart_h_
2 #define _ShipPart_h_
3
4 #include <boost/serialization/nvp.hpp>
5
6 #include <GG/Enum.h>
7 #include "CommonParams.h"
8 #include "../util/Pending.h"
9
10
11 FO_COMMON_API extern const int INVALID_DESIGN_ID;
12
13
14 //! Classifies ShipParts by general function.
15 GG_ENUM(ShipPartClass,
16 INVALID_SHIP_PART_CLASS = -1,
17 PC_DIRECT_WEAPON, //!< direct-fire weapons
18 PC_FIGHTER_BAY, //!< launch aparatus for fighters, which are self-propelled platforms that function independently of ships in combat, but don't exist on the main game map
19 PC_FIGHTER_HANGAR, //!< storage for fighters, also determines their weapon strength stat
20 PC_SHIELD, //!< energy-based defense
21 PC_ARMOUR, //!< defensive material on hull of ship
22 PC_TROOPS, //!< ground troops, used to conquer planets
23 PC_DETECTION, //!< range of vision and seeing through stealth
24 PC_STEALTH, //!< hiding from enemies
25 PC_FUEL, //!< distance that can be traveled away from resupply
26 PC_COLONY, //!< transports colonists and allows ships to make new colonies
27 PC_SPEED, //!< affects ship speed on starlanes
28 PC_GENERAL, //!< special purpose parts that don't fall into another class
29 PC_BOMBARD, //!< permit orbital bombardment by ships against planets
30 PC_INDUSTRY, //!< generates production points for owner at its location
31 PC_RESEARCH, //!< generates research points for owner
32 PC_TRADE, //!< generates trade points for owner
33 PC_PRODUCTION_LOCATION, //!< allows production items to be produced at its location
34 NUM_SHIP_PART_CLASSES
35 )
36
37
38 //! Describes an equipable part for a ship.
39 class FO_COMMON_API ShipPart {
40 public:
41 ShipPart();
42
43 ShipPart(ShipPartClass part_class, double capacity, double stat2,
44 CommonParams& common_params, const MoreCommonParams& more_common_params,
45 std::vector<ShipSlotType> mountable_slot_types,
46 const std::string& icon, bool add_standard_capacity_effect = true,
47 std::unique_ptr<Condition::Condition>&& combat_targets = nullptr);
48
49 ~ShipPart();
50
51 //! Returns name of part
52 auto Name() const -> const std::string&
53 { return m_name; }
54
55 //! Returns description string, generally a UserString key.
56 auto Description() const -> const std::string&
57 { return m_description; }
58
59 //! Returns that class of part that this is.
60 auto Class() const -> ShipPartClass
61 { return m_class; }
62
63 auto Capacity() const -> float;
64
65 //! Returns a translated description of the part capacity, with numeric
66 //! value
67 auto CapacityDescription() const -> std::string;
68
69 auto SecondaryStat() const -> float;
70
71 //! Returns true if this part can be placed in a slot of the indicated type
72 auto CanMountInSlotType(ShipSlotType slot_type) const -> bool;
73
74 //! Returns the condition for possible targets. may be nullptr if no
75 //! condition was specified.
76 auto CombatTargets() const -> const Condition::Condition*
77 { return m_combat_targets.get(); }
78
79 auto MountableSlotTypes() const -> const std::vector<ShipSlotType>&
80 { return m_mountable_slot_types; }
81
82 //! Returns true if the production cost and time are invariant
83 //! (does not depend on) the location
84 auto ProductionCostTimeLocationInvariant() const -> bool;
85
86 //! Returns the number of production points required to produce this part
87 auto ProductionCost(int empire_id, int location_id, int in_design_id = INVALID_DESIGN_ID) const -> float;
88
89 //! Returns the number of turns required to produce this part
90 auto ProductionTime(int empire_id, int location_id, int in_design_id = INVALID_DESIGN_ID) const -> int;
91
92 //! Returns whether this part type is producible by players and appears on
93 //! the design screen
94 auto Producible() const -> bool
95 { return m_producible; }
96
97 auto ProductionMeterConsumption() const -> const ConsumptionMap<MeterType>&
98 { return m_production_meter_consumption; }
99
100 auto ProductionSpecialConsumption() const -> const ConsumptionMap<std::string>&
101 { return m_production_special_consumption; }
102
103 auto Tags() const -> const std::set<std::string>&
104 { return m_tags; }
105
106 //! Returns the condition that determines the locations where ShipDesign
107 //! containing part can be produced
108 auto Location() const -> const Condition::Condition*
109 { return m_location.get(); }
110
111 //! Returns the names of other content that cannot be used in the same
112 //! ship design as this part
113 auto Exclusions() const -> const std::set<std::string>&
114 { return m_exclusions; }
115
116 //! Returns the EffectsGroups that encapsulate the effects this part has.
117 auto Effects() const -> const std::vector<std::shared_ptr<Effect::EffectsGroup>>&
118 { return m_effects; }
119
120 //! Returns icon graphic that represents part in UI
121 auto Icon() const -> const std::string&
122 { return m_icon; }
123
124 //! Returns a number, calculated from the contained data, which should be
125 //! different for different contained data, and must be the same for
126 //! the same contained data, and must be the same on different platforms
127 //! and executions of the program and the function. Useful to verify that
128 //! the parsed content is consistent without sending it all between
129 //! clients and server.
130 unsigned int GetCheckSum() const;
131 //@}
132
133 private:
134 void Init(std::vector<std::unique_ptr<Effect::EffectsGroup>>&& effects);
135
136 std::string m_name;
137 std::string m_description;
138 ShipPartClass m_class;
139 float m_capacity = 0.0f;
140 //! Damage for a hangar bay, shots per turn for a weapon, etc.
141 float m_secondary_stat = 0.0f;
142 bool m_producible = false;
143
144 std::unique_ptr<ValueRef::ValueRef<double>> m_production_cost;
145 std::unique_ptr<ValueRef::ValueRef<int>> m_production_time;
146 std::vector<ShipSlotType> m_mountable_slot_types;
147 std::set<std::string> m_tags;
148 ConsumptionMap<MeterType> m_production_meter_consumption;
149 ConsumptionMap<std::string> m_production_special_consumption;
150 std::unique_ptr<Condition::Condition> m_location;
151 std::set<std::string> m_exclusions;
152 std::vector<std::shared_ptr<Effect::EffectsGroup>> m_effects;
153 std::string m_icon;
154 bool m_add_standard_capacity_effect = false;
155 std::unique_ptr<Condition::Condition> m_combat_targets;
156
157 friend class boost::serialization::access;
158 template <typename Archive>
159 void serialize(Archive& ar, const unsigned int version);
160 };
161
162
163 template <typename Archive>
serialize(Archive & ar,const unsigned int version)164 void ShipPart::serialize(Archive& ar, const unsigned int version)
165 {
166 ar & BOOST_SERIALIZATION_NVP(m_name)
167 & BOOST_SERIALIZATION_NVP(m_description)
168 & BOOST_SERIALIZATION_NVP(m_class)
169 & BOOST_SERIALIZATION_NVP(m_capacity)
170 & BOOST_SERIALIZATION_NVP(m_secondary_stat)
171 & BOOST_SERIALIZATION_NVP(m_production_cost)
172 & BOOST_SERIALIZATION_NVP(m_production_time)
173 & BOOST_SERIALIZATION_NVP(m_producible)
174 & BOOST_SERIALIZATION_NVP(m_mountable_slot_types)
175 & BOOST_SERIALIZATION_NVP(m_tags)
176 & BOOST_SERIALIZATION_NVP(m_production_meter_consumption)
177 & BOOST_SERIALIZATION_NVP(m_production_special_consumption)
178 & BOOST_SERIALIZATION_NVP(m_location)
179 & BOOST_SERIALIZATION_NVP(m_exclusions)
180 & BOOST_SERIALIZATION_NVP(m_effects)
181 & BOOST_SERIALIZATION_NVP(m_icon)
182 & BOOST_SERIALIZATION_NVP(m_add_standard_capacity_effect)
183 & BOOST_SERIALIZATION_NVP(m_combat_targets);
184 }
185
186
187 //! Holds FreeOrion available ShipParts
188 class FO_COMMON_API ShipPartManager {
189 public:
190 using ShipPartMap = std::map<std::string, std::unique_ptr<ShipPart>>;
191 using iterator = ShipPartMap::const_iterator;
192
193 //! Returns the ShipPart with the name @p name; you should use the free
194 //! function GetShipPart() instead
195 auto GetShipPart(const std::string& name) const -> const ShipPart*;
196
197 //! Iterator to the first ShipPart
198 auto begin() const -> iterator;
199
200 //! Iterator to one after the last ShipPart.
201 auto end() const -> iterator;
202
203 //! Returns the instance of this singleton class; you should use the free
204 //! function GetShipPartManager() instead.
205 static auto GetShipPartManager() -> ShipPartManager&;
206
207 //! Returns a number, calculated from the contained data, which should be
208 //! different for different contained data, and must be the same for
209 //! the same contained data, and must be the same on different platforms
210 //! and executions of the program and the function. Useful to verify that
211 //! the parsed content is consistent without sending it all between
212 //! clients and server.
213 auto GetCheckSum() const -> unsigned int;
214
215 //! Sets part types to the future value of @p pending_ship_parts.
216 FO_COMMON_API void SetShipParts(Pending::Pending<ShipPartMap>&& pending_ship_parts);
217
218 private:
219 ShipPartManager();
220
221 //! Assigns any m_pending_ship_parts to m_parts.
222 void CheckPendingShipParts() const;
223
224 //! Future that provides all ShipPart%s after loaded by the parser.
225 mutable boost::optional<Pending::Pending<ShipPartMap>> m_pending_ship_parts = boost::none;
226
227 //! Map of ShipPart::Name to ShipPart%s.
228 mutable ShipPartMap m_parts;
229
230 static ShipPartManager* s_instance;
231 };
232
233
234 //! Returns the singleton ShipPart manager
235 FO_COMMON_API ShipPartManager& GetShipPartManager();
236
237
238 //! Returns the ShipPart specification object with name @p name. If no
239 //! such ShipPart exists, nullptr is returned instead.
240 FO_COMMON_API const ShipPart* GetShipPart(const std::string& name);
241
242
243 #endif // _ShipPart_h_
244