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