1 /*
2  * Copyright (C) 2002-2020 by the Widelands Development Team
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
17  *
18  */
19 
20 #ifndef WL_LOGIC_MAP_OBJECTS_TRIBES_BUILDING_H
21 #define WL_LOGIC_MAP_OBJECTS_TRIBES_BUILDING_H
22 
23 #include "ai/ai_hints.h"
24 #include "base/macros.h"
25 #include "logic/map_objects/buildcost.h"
26 #include "logic/map_objects/immovable.h"
27 #include "logic/map_objects/tribes/attack_target.h"
28 #include "logic/map_objects/tribes/building_settings.h"
29 #include "logic/map_objects/tribes/soldiercontrol.h"
30 #include "logic/map_objects/tribes/wareworker.h"
31 #include "logic/map_objects/tribes/workarea_info.h"
32 #include "logic/message.h"
33 #include "scripting/lua_table.h"
34 
35 namespace Widelands {
36 
37 class InputQueue;
38 
39 constexpr int32_t kPriorityLow = 2;
40 constexpr int32_t kPriorityNormal = 4;
41 constexpr int32_t kPriorityHigh = 8;
42 
43 /* The value "" means that the DescriptionIndex is a normal building, as happens e.g. when enhancing
44  * a building. The value "tribe"/"world" means that the DescriptionIndex refers to an immovable of
45  * OwnerType kTribe/kWorld, as happens e.g. with amazon treetop sentry. This immovable
46  * should therefore always be painted below the building image.
47  */
48 using FormerBuildings = std::vector<std::pair<DescriptionIndex, std::string>>;
49 
50 /*
51  * Common to all buildings!
52  */
53 class BuildingDescr : public MapObjectDescr {
54 public:
55 	BuildingDescr(const std::string& init_descname,
56 	              MapObjectType type,
57 	              const LuaTable& t,
58 	              const Tribes& tribes);
~BuildingDescr()59 	~BuildingDescr() override {
60 	}
61 
is_buildable()62 	bool is_buildable() const {
63 		return buildable_;
64 	}
can_be_dismantled()65 	bool can_be_dismantled() const {
66 		return can_be_dismantled_;
67 	}
is_destructible()68 	bool is_destructible() const {
69 		return destructible_;
70 	}
is_enhanced()71 	bool is_enhanced() const {
72 		return enhanced_building_;
73 	}
74 
75 	/**
76 	 * The build cost for direct construction
77 	 */
buildcost()78 	const Buildcost& buildcost() const {
79 		return buildcost_;
80 	}
81 
82 	/**
83 	 * Returned wares for dismantling
84 	 */
returned_wares()85 	const Buildcost& returned_wares() const {
86 		return return_dismantle_;
87 	}
88 
89 	/**
90 	 * The build cost for enhancing a previous building
91 	 */
enhancement_cost()92 	const Buildcost& enhancement_cost() const {
93 		return enhance_cost_;
94 	}
95 
96 	/**
97 	 * The returned wares for a enhaced building
98 	 */
returned_wares_enhanced()99 	const Buildcost& returned_wares_enhanced() const {
100 		return return_enhanced_;
101 	}
102 
get_size()103 	int32_t get_size() const {
104 		return size_;
105 	}
get_ismine()106 	bool get_ismine() const {
107 		return mine_;
108 	}
get_isport()109 	bool get_isport() const {
110 		return port_;
111 	}
needs_seafaring()112 	bool needs_seafaring() const {
113 		return needs_seafaring_;
114 	}
needs_waterways()115 	bool needs_waterways() const {
116 		return needs_waterways_;
117 	}
118 
119 	bool is_useful_on_map(bool seafaring_allowed, bool waterways_allowed) const;
120 
121 	// Returns the enhancement this building can become or
122 	// INVALID_INDEX if it cannot be enhanced.
enhancement()123 	const DescriptionIndex& enhancement() const {
124 		return enhancement_;
125 	}
126 	// Returns the building from which this building can be enhanced or
127 	// INVALID_INDEX if it cannot be built as an enhanced building.
enhanced_from()128 	const DescriptionIndex& enhanced_from() const {
129 		return enhanced_from_;
130 	}
set_enhanced_from(const DescriptionIndex & index)131 	void set_enhanced_from(const DescriptionIndex& index) {
132 		enhanced_from_ = index;
133 	}
134 
135 	/// Create a building of this type in the game. Calls init, which does
136 	/// different things for different types of buildings (such as conquering
137 	/// land and requesting things). Therefore this must not be used to allocate
138 	/// a building during savegame loading. (It would cause many bugs.)
139 	///
140 	/// Does not perform any sanity checks.
141 	/// If former_buildings is not empty this is an enhancing.
142 	Building& create(EditorGameBase&,
143 	                 Player*,
144 	                 Coords,
145 	                 bool construct,
146 	                 bool loading = false,
147 	                 FormerBuildings former_buildings = FormerBuildings()) const;
148 
149 	virtual uint32_t get_conquers() const;
150 	virtual uint32_t vision_range() const;
151 
workarea_info()152 	const WorkareaInfo& workarea_info() const {
153 		return workarea_info_;
154 	}
155 
156 	// TODO(sirver): This should not be public. It is mutated by other classes
157 	// in many places.
158 	WorkareaInfo workarea_info_;
159 
160 	bool suitability(const Map&, const FCoords&) const;
161 	const BuildingHints& hints() const;
162 	void set_hints_trainingsites_max_percent(int percent);
163 
164 	uint32_t get_unoccupied_animation() const;
165 
get_built_over_immovable()166 	DescriptionIndex get_built_over_immovable() const {
167 		return built_over_immovable_;
168 	}
169 
170 protected:
171 	virtual Building& create_object() const = 0;
172 	Building& create_constructionsite() const;
173 
174 private:
175 	const Tribes& tribes_;
176 	const bool buildable_;          // the player can build this himself
177 	const bool can_be_dismantled_;  // the player can dismantle this building
178 	const bool destructible_;       // the player can destruct this himself
179 	Buildcost buildcost_;
180 	Buildcost return_dismantle_;  // Returned wares on dismantle
181 	Buildcost enhance_cost_;      // cost for enhancing
182 	Buildcost return_enhanced_;   // Returned ware for dismantling an enhanced building
183 	int32_t size_;                // size of the building
184 	bool mine_;
185 	bool port_;
186 	bool needs_seafaring_;  // This building should only be built on seafaring maps.
187 	bool needs_waterways_;  // This building should only be built on maps with waterways/ferries
188 	                        // enabled
189 	DescriptionIndex enhancement_;
190 	DescriptionIndex
191 	   enhanced_from_;        // The building this building was enhanced from, or INVALID_INDEX
192 	bool enhanced_building_;  // if it is one, it is bulldozable
193 	BuildingHints hints_;     // hints (knowledge) for computer players
194 	DescriptionIndex built_over_immovable_;  // can be built only on nodes where an immovable with
195 	                                         // this attribute stands
196 
197 	// for migration, 0 is the default, meaning get_conquers() + 4
198 	uint32_t vision_range_;
199 	DISALLOW_COPY_AND_ASSIGN(BuildingDescr);
200 };
201 
202 struct NoteBuilding {
203 	CAN_BE_SENT_AS_NOTE(NoteId::Building)
204 
205 	Serial serial;
206 
207 	enum class Action { kChanged, kStartWarp, kFinishWarp, kWorkersChanged };
208 	const Action action;
209 
NoteBuildingNoteBuilding210 	NoteBuilding(Serial init_serial, const Action& init_action)
211 	   : serial(init_serial), action(init_action) {
212 	}
213 };
214 
215 class Building : public PlayerImmovable {
216 	friend class BuildingDescr;
217 	friend class MapBuildingdataPacket;
218 
219 	MO_DESCR(BuildingDescr)
220 
221 public:
222 	// Player capabilities: which commands can a player issue for this building?
223 	enum {
224 		PCap_Bulldoze = 1,         // can bulldoze/remove this buildings
225 		PCap_Dismantle = 1 << 1,   // can dismantle this buildings
226 		PCap_Enhancable = 1 << 2,  // can be enhanced to something
227 	};
228 
229 public:
230 	enum class InfoStringFormat { kCensus, kStatistics, kTooltip };
231 
232 	explicit Building(const BuildingDescr&);
233 
234 	void load_finish(EditorGameBase&) override;
235 
236 	int32_t get_size() const override;
237 	bool get_passable() const override;
238 
239 	Flag& base_flag() override;
240 	virtual uint32_t get_playercaps() const;
241 
get_position()242 	virtual Coords get_position() const {
243 		return position_;
244 	}
245 	PositionList get_positions(const EditorGameBase&) const override;
246 
247 	std::string info_string(const InfoStringFormat& format);
248 
249 	// Return the overlay string that is displayed on the map view when enabled
250 	// by the player.
update_and_get_statistics_string()251 	const std::string& update_and_get_statistics_string() {
252 		update_statistics_string(&statistics_string_);
253 		return statistics_string_;
254 	}
255 
256 	/// \returns the queue for the matching ware or worker type or \throws WException.
257 	virtual InputQueue& inputqueue(DescriptionIndex, WareWorker);
258 
259 	virtual bool burn_on_destroy();
260 	void destroy(EditorGameBase&) override;
261 
262 	virtual bool fetch_from_flag(Game&);
263 	virtual bool get_building_work(Game&, Worker&, bool success);
264 
265 	bool leave_check_and_wait(Game&, Worker&);
266 	void leave_skip(Game&, Worker&);
267 
268 	// Get/Set the priority for this waretype for this building. 'type' defines
269 	// if this is for a worker or a ware, 'index' is the type of worker or ware.
270 	// If 'adjust' is false, the three possible states kPriorityHigh,
271 	// kPriorityNormal and kPriorityLow are returned, otherwise numerical
272 	// values adjusted to the preciousness of the ware in general are returned.
273 	virtual int32_t get_priority(WareWorker type, DescriptionIndex, bool adjust = true) const;
274 	void set_priority(int32_t type, DescriptionIndex ware_index, int32_t new_priority);
275 
276 	void collect_priorities(std::map<int32_t, std::map<DescriptionIndex, int32_t>>& p) const;
277 
278 	/**
279 	 * The former buildings vector keeps track of all former buildings
280 	 * that have been enhanced up to the current one. The current building
281 	 * index will be in the last position. For construction sites, it is
282 	 * empty except enhancements. For a dismantle site, the last item will
283 	 * be the one being dismantled.
284 	 */
get_former_buildings()285 	const FormerBuildings get_former_buildings() {
286 		return old_buildings_;
287 	}
288 
289 	void log_general_info(const EditorGameBase&) const override;
290 
291 	//  Use on training sites only.
change_train_priority(uint32_t,int32_t)292 	virtual void change_train_priority(uint32_t, int32_t) {
293 	}
switch_train_mode()294 	virtual void switch_train_mode() {
295 	}
296 
297 	///  Stores the PlayerNumber of the player who has defeated this building.
set_defeating_player(PlayerNumber const player_number)298 	void set_defeating_player(PlayerNumber const player_number) {
299 		defeating_player_ = player_number;
300 	}
301 
302 	void add_worker(Worker&) override;
303 	void remove_worker(Worker&) override;
304 
create_building_settings()305 	virtual const BuildingSettings* create_building_settings() const {
306 		return nullptr;
307 	}
308 
309 	// AttackTarget object associated with this building. If the building can
310 	// never be attacked (for example productionsites) this will be nullptr.
attack_target()311 	const AttackTarget* attack_target() const {
312 		return attack_target_;
313 	}
314 
315 	// SoldierControl object associated with this building. If the building can
316 	// not house soldiers (for example productionsites) this will be nullptr.
soldier_control()317 	const SoldierControl* soldier_control() const {
318 		return soldier_control_;
319 	}
mutable_soldier_control()320 	SoldierControl* mutable_soldier_control() {
321 		return soldier_control_;
322 	}
323 
324 	void send_message(Game& game,
325 	                  const Message::Type msgtype,
326 	                  const std::string& title,
327 	                  const std::string& icon_filename,
328 	                  const std::string& heading,
329 	                  const std::string& description,
330 	                  bool link_to_building_lifetime = true,
331 	                  uint32_t throttle_time = 0,
332 	                  uint32_t throttle_radius = 0);
333 
334 	void start_animation(EditorGameBase&, uint32_t anim);
335 
336 protected:
337 	// Updates 'statistics_string' with the string that should be displayed for
338 	// this building right now. Overwritten by child classes.
update_statistics_string(std::string *)339 	virtual void update_statistics_string(std::string*) {
340 	}
341 
342 	bool init(EditorGameBase&) override;
343 	void cleanup(EditorGameBase&) override;
344 	void act(Game&, uint32_t data) override;
345 
346 	void draw(uint32_t gametime,
347 	          InfoToDraw info_to_draw,
348 	          const Vector2f& point_on_dst,
349 	          const Coords& coords,
350 	          float scale,
351 	          RenderTarget* dst) override;
352 	void
353 	draw_info(InfoToDraw info_to_draw, const Vector2f& point_on_dst, float scale, RenderTarget* dst);
354 
355 	void set_seeing(bool see);
356 	void set_attack_target(AttackTarget* new_attack_target);
357 	void set_soldier_control(SoldierControl* new_soldier_control);
358 
359 	Coords position_;
360 	Flag* flag_;
361 
362 	uint32_t anim_;
363 	int32_t animstart_;
364 
365 	using LeaveQueue = std::vector<OPtr<Worker>>;
366 	LeaveQueue leave_queue_;     //  FIFO queue of workers leaving the building
367 	uint32_t leave_time_;        //  when to wake the next one from leave queue
368 	ObjectPointer leave_allow_;  //  worker that is allowed to leave now
369 
370 	//  The player who has defeated this building.
371 	PlayerNumber defeating_player_;
372 
373 	std::map<DescriptionIndex, int32_t> ware_priorities_;
374 
375 	/// Whether we see our vision_range area based on workers in the building
376 	bool seeing_;
377 
378 	// The former buildings names, with the current one in last position.
379 	FormerBuildings old_buildings_;
380 	const MapObjectDescr* was_immovable_;
381 
382 private:
383 	std::string statistics_string_;
384 	AttackTarget* attack_target_;      // owned by the base classes, set by 'set_attack_target'.
385 	SoldierControl* soldier_control_;  // owned by the base classes, set by 'set_soldier_control'.
386 };
387 }  // namespace Widelands
388 
389 #endif  // end of include guard: WL_LOGIC_MAP_OBJECTS_TRIBES_BUILDING_H
390