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_IMMOVABLE_H
21 #define WL_LOGIC_MAP_OBJECTS_IMMOVABLE_H
22 
23 #include <memory>
24 
25 #include "base/macros.h"
26 #include "logic/map_objects/buildcost.h"
27 #include "logic/map_objects/info_to_draw.h"
28 #include "logic/map_objects/map_object.h"
29 #include "logic/map_objects/tribes/wareworker.h"
30 #include "logic/map_objects/world/editor_category.h"
31 #include "logic/widelands_geometry.h"
32 #include "notifications/note_ids.h"
33 #include "notifications/notifications.h"
34 
35 class TribesLegacyLookupTable;
36 class WorldLegacyLookupTable;
37 
38 namespace Widelands {
39 
40 class Building;
41 class BuildingDescr;
42 class Economy;
43 class Map;
44 class TerrainAffinity;
45 class Worker;
46 class World;
47 struct Flag;
48 struct PlayerImmovable;
49 
50 struct NoteImmovable {
51 	CAN_BE_SENT_AS_NOTE(NoteId::Immovable)
52 
53 	PlayerImmovable* pi;
54 
55 	enum class Ownership { LOST, GAINED };
56 	Ownership ownership;
57 
NoteImmovableNoteImmovable58 	NoteImmovable(PlayerImmovable* const init_pi, Ownership const init_ownership)
59 	   : pi(init_pi), ownership(init_ownership) {
60 	}
61 };
62 
63 /**
64  * BaseImmovable is the base for all non-moving objects (immovables such as
65  * trees, buildings, flags, roads).
66  *
67  * The Immovable's size influences building capabilities around it.
68  * If size is NONE, the immovable can simply be removed by placing something on
69  * it (this is usually true for decorations).
70  *
71  * For more information, see the Map::recalc_* functions.
72  */
73 struct BaseImmovable : public MapObject {
74 	enum Size {
75 		NONE = 0,  ///< not robust (i.e. removable by building something over it)
76 		SMALL,     ///< small building or robust map element, including trees
77 		MEDIUM,    ///< medium size building
78 		BIG        ///< big building
79 	};
80 
81 	explicit BaseImmovable(const MapObjectDescr&);
82 
83 	virtual int32_t get_size() const = 0;
84 	virtual bool get_passable() const = 0;
85 
86 	virtual void set_owner(Player* player);
87 
88 	using PositionList = std::vector<Coords>;
89 	/**
90 	 * Return all coordinates occupied by this Immovable. We gurantee that the
91 	 * list always contains one entry and the first one is the main position
92 	 * if one can be chosen as main.
93 	 */
94 	virtual PositionList get_positions(const EditorGameBase&) const = 0;
95 
96 	// Draw this immovable onto 'dst' choosing the frame appropriate for
97 	// 'gametime'. 'info_to_draw' decides if census and statistics are written too.
98 	// The 'coords_to_draw' are passed one to give objects that occupy multiple
99 	// fields a way to only draw themselves once. The 'point_on_dst' determines
100 	// the point for the hotspot of the animation and 'scale' determines how big
101 	// the immovable will be plotted.
102 	virtual void draw(uint32_t gametime,
103 	                  InfoToDraw info_to_draw,
104 	                  const Vector2f& point_on_dst,
105 	                  const Coords& coords,
106 	                  float scale,
107 	                  RenderTarget* dst) = 0;
108 
109 	static int32_t string_to_size(const std::string& size);
110 	static std::string size_to_string(int32_t size);
111 
112 protected:
113 	void set_position(EditorGameBase&, const Coords&);
114 	void unset_position(EditorGameBase&, const Coords&);
115 };
116 
117 class Immovable;
118 struct ImmovableProgram;
119 struct ImmovableAction;
120 struct ImmovableActionData;
121 
122 /**
123  * Immovable represents a standard immovable such as trees or rocks.
124  */
125 class ImmovableDescr : public MapObjectDescr {
126 public:
127 	using Programs = std::map<std::string, ImmovableProgram*>;
128 
129 	/// World immovable
130 	ImmovableDescr(const std::string& init_descname, const LuaTable&, const World& world);
131 	/// Tribes immovable
132 	ImmovableDescr(const std::string& init_descname, const LuaTable&, const Tribes& tribes);
133 	~ImmovableDescr() override;
134 
get_size()135 	int32_t get_size() const {
136 		return size_;
137 	}
138 	ImmovableProgram const* get_program(const std::string&) const;
139 
140 	Immovable& create(EditorGameBase&,
141 	                  const Coords&,
142 	                  const Widelands::BuildingDescr* former_building_descr) const;
143 
owner_type()144 	MapObjectDescr::OwnerType owner_type() const {
145 		return owner_type_;
146 	}
147 
buildcost()148 	const Buildcost& buildcost() const {
149 		return buildcost_;
150 	}
151 
152 	// Returns the editor category, or nullptr if the immovable has no editor category
153 	// (e.g. Tribe immovables never have one).
154 	const EditorCategory* editor_category() const;
155 
156 	// A basic localized name for the immovable, used by trees
species()157 	const std::string& species() const {
158 		return species_;
159 	}
160 
161 	// Every immovable that can 'grow' needs to have terrain affinity defined,
162 	// all others do not. Returns true if this one has it defined.
163 	bool has_terrain_affinity() const;
164 
165 	// Returns the terrain affinity. If !has_terrain_affinity() this will return
166 	// an undefined value.
167 	const TerrainAffinity& terrain_affinity() const;
168 
169 protected:
170 	int32_t size_;
171 	Programs programs_;
172 
173 	/// Whether this ImmovableDescr belongs to a tribe or the world
174 	const MapObjectDescr::OwnerType owner_type_;
175 
176 	/// Buildcost for externally constructible immovables (for ship construction)
177 	/// \see ActConstruct
178 	Buildcost buildcost_;
179 
180 	std::string species_;
181 
182 private:
183 	// Common constructor functions for tribes and world.
184 	ImmovableDescr(const std::string& init_descname,
185 	               const LuaTable&,
186 	               MapObjectDescr::OwnerType type);
187 
188 	// Adds a default program if none was defined.
189 	void make_sure_default_program_is_there();
190 
191 	EditorCategory* editor_category_;  // not owned.
192 	std::unique_ptr<TerrainAffinity> terrain_affinity_;
193 	DISALLOW_COPY_AND_ASSIGN(ImmovableDescr);
194 };
195 
196 class Immovable : public BaseImmovable {
197 	friend class ImmovableDescr;
198 	friend struct ImmovableProgram;
199 	friend class Map;
200 
201 	MO_DESCR(ImmovableDescr)
202 
203 public:
204 	/// If this immovable was created by a building, 'former_building_descr' can be set in order to
205 	/// display information about it.
206 	Immovable(const ImmovableDescr&,
207 	          const Widelands::BuildingDescr* former_building_descr = nullptr);
208 	~Immovable() override;
209 
get_position()210 	Coords get_position() const {
211 		return position_;
212 	}
213 	PositionList get_positions(const EditorGameBase&) const override;
214 
215 	int32_t get_size() const override;
216 	bool get_passable() const override;
217 	void start_animation(const EditorGameBase&, uint32_t anim);
218 
219 	void program_step(Game& game, uint32_t const delay = 1) {
220 		if (delay)
221 			program_step_ = schedule_act(game, delay);
222 		increment_program_pointer();
223 	}
224 
225 	bool init(EditorGameBase&) override;
226 	void cleanup(EditorGameBase&) override;
227 	void act(Game&, uint32_t data) override;
228 	void draw(uint32_t gametime,
229 	          InfoToDraw info_to_draw,
230 	          const Vector2f& point_on_dst,
231 	          const Coords& coords,
232 	          float scale,
233 	          RenderTarget* dst) override;
234 
235 	void switch_program(Game& game, const std::string& programname);
236 	bool construct_ware(Game& game, DescriptionIndex index);
237 	bool construct_remaining_buildcost(Game& game, Buildcost* buildcost);
238 
239 	void set_action_data(ImmovableActionData* data);
get_action_data()240 	template <typename T> T* get_action_data() {
241 		if (!action_data_)
242 			return nullptr;
243 		if (T* data = dynamic_cast<T*>(action_data_.get()))
244 			return data;
245 		set_action_data(nullptr);
246 		return nullptr;
247 	}
248 
249 protected:
250 	// The building type that created this immovable, if any.
251 	const BuildingDescr* former_building_descr_;
252 
253 	Coords position_;
254 
255 	uint32_t anim_;
256 	int32_t animstart_;
257 
258 	const ImmovableProgram* program_;
259 	uint32_t program_ptr_;  ///< index of next instruction to execute
260 
261 /* GCC 4.0 has problems with friend declarations: It doesn't allow
262  * substructures of friend classes private access but we rely on this behaviour
263  * for ImmovableProgram::ActConstruct. As a dirty workaround, we make the
264  * following variables public for this versions but keep the protected for
265  * other GCC versions.
266  * See the related bug lp:688832.
267  */
268 #if (__GNUC__ == 4) && (__GNUC_MINOR__ == 0)
269 public:
270 	uint32_t anim_construction_total_;
271 	uint32_t anim_construction_done_;
272 	uint32_t program_step_;
273 
274 protected:
275 #else
276 	uint32_t anim_construction_total_;
277 	uint32_t anim_construction_done_;
278 	uint32_t program_step_;  ///< time of next step
279 #endif
280 
281 	/**
282 	 * Private persistent data for the currently active program action.
283 	 *
284 	 * \warning Use get_action_data to access this.
285 	 */
286 	std::unique_ptr<ImmovableActionData> action_data_;
287 
288 	// Load/save support
289 protected:
290 	struct Loader : public BaseImmovable::Loader {
291 		void load(FileRead&, uint8_t packet_version);
292 		void load_pointers() override;
293 		void load_finish() override;
294 	};
295 
296 public:
297 	// TODO(unknown): Remove as soon as we fully support the new system
has_new_save_support()298 	bool has_new_save_support() override {
299 		return true;
300 	}
301 
302 	void save(EditorGameBase&, MapObjectSaver&, FileWrite&) override;
303 	static MapObject::Loader* load(EditorGameBase&,
304 	                               MapObjectLoader&,
305 	                               FileRead&,
306 	                               const WorldLegacyLookupTable& world_lookup_table,
307 	                               const TribesLegacyLookupTable& tribes_lookup_table);
308 
309 private:
310 	/// If this immovable was created by a building, this can be set in order to display information
311 	/// about it. If this is a player immovable, you will need to set the owner first.
312 	void set_former_building(const BuildingDescr& building);
313 
314 	void increment_program_pointer();
315 	void draw_construction(uint32_t gametime,
316 	                       InfoToDraw info_to_draw,
317 	                       const Vector2f& point_on_dst,
318 	                       const Widelands::Coords& coords,
319 	                       float scale,
320 	                       RenderTarget* dst);
321 };
322 
323 /**
324  * PlayerImmovable is an immovable owned by a player that belongs to an economy:
325  * building, flag or road
326  *
327  * A PlayerImmovable can also house a number of workers, which are automatically
328  * turned into fugitives when the immovable is destroyed, and their economy is
329  * also adjusted automatically.
330  */
331 struct PlayerImmovable : public BaseImmovable {
332 	explicit PlayerImmovable(const MapObjectDescr&);
333 	~PlayerImmovable() override;
334 
get_economyPlayerImmovable335 	Economy* get_economy(WareWorker type) const {
336 		return type == wwWARE ? ware_economy_ : worker_economy_;
337 	}
economyPlayerImmovable338 	Economy& economy(WareWorker type) const {
339 		return *(type == wwWARE ? ware_economy_ : worker_economy_);
340 	}
341 
342 	virtual Flag& base_flag() = 0;
343 
344 	virtual void set_economy(Economy*, WareWorker);
345 
346 	virtual void add_worker(Worker&);
347 	virtual void remove_worker(Worker&);
348 
349 	using Workers = std::vector<Worker*>;
350 
351 	/**
352 	 * \return a list of workers that are currently located at this
353 	 * immovable. This is not the same as the list of production
354 	 * workers returned by \ref ProductionSite::working_positions
355 	 */
get_workersPlayerImmovable356 	const Workers& get_workers() const {
357 		return workers_;
358 	}
359 
360 	void log_general_info(const EditorGameBase&) const override;
361 
362 	/**
363 	 * These functions are called when a ware or worker arrives at
364 	 * this immovable as the destination of a transfer that does not
365 	 * have an associated request.
366 	 *
367 	 * At the time of this writing, this happens only for warehouses.
368 	 *
369 	 * \note This is independent of the \ref add_worker / \ref remove_worker
370 	 * functionality, which has to do with setting up locations.
371 	 */
372 	/*@{*/
373 	virtual void receive_ware(Game&, DescriptionIndex ware);
374 	virtual void receive_worker(Game&, Worker& worker);
375 	/*@}*/
376 
377 	void set_owner(Player*) override;
378 
379 protected:
380 	bool init(EditorGameBase&) override;
381 	void cleanup(EditorGameBase&) override;
382 
383 private:
384 	Economy* ware_economy_;
385 	Economy* worker_economy_;
386 
387 	Workers workers_;
388 
389 	// load/save support
390 protected:
391 	struct Loader : BaseImmovable::Loader {
392 		Loader();
393 
394 		void load(FileRead&);
395 	};
396 
397 public:
398 	void save(EditorGameBase&, MapObjectSaver&, FileWrite&) override;
399 };
400 }  // namespace Widelands
401 
402 #endif  // end of include guard: WL_LOGIC_MAP_OBJECTS_IMMOVABLE_H
403