1 /*
2  *  Copyright (c) 1997 - 2002 by Volker Meyer & Hansj�rg Malthaner
3  *
4  * This file is part of the Simutrans project under the artistic licence.
5  */
6 
7 #ifndef __BUILDING_DESC_H
8 #define __BUILDING_DESC_H
9 
10 #include <assert.h>
11 #include "image_array.h"
12 #include "obj_base_desc.h"
13 #include "skin_desc.h"
14 #include "../dataobj/koord.h"
15 
16 class building_desc_t;
17 class tool_t;
18 class karte_t;
19 class checksum_t;
20 
21 /*
22  *  Author:
23  *      Volker Meyer
24  *
25  *  Description:
26  *      Data for one tile of a potentially multi-tile building.
27  *
28  *  Child nodes:
29  *   0   Imagelist2D season 0 back
30  *   1   Imagelist2D season 0 front
31  *   2   Imagelist2D season 1 back
32  *   3   Imagelist2D season 1 front
33  *	... ...
34  */
35 class building_tile_desc_t : public obj_desc_t {
36 	friend class tile_reader_t;
37 
38 	const building_desc_t	*building;
39 
40 	uint8  seasons;
41 	uint8  phases;	    ///< number of animation phases
42 	uint16 index;
43 
44 public:
set_desc(const building_desc_t * building_desc)45 	void set_desc(const building_desc_t *building_desc) { building = building_desc; }
46 
get_desc()47 	const building_desc_t *get_desc() const { return building; }
48 
get_index()49 	uint16 get_index() const { return index; }
get_seasons()50 	uint8 get_seasons() const { return seasons; }
get_phases()51 	uint8 get_phases() const { return phases; }
52 
has_image()53 	bool has_image() const {
54 		return get_background(0,0,0)!=IMG_EMPTY  ||  get_foreground(0,0)!=IMG_EMPTY;
55 	}
56 
get_background(uint16 phase,uint16 height,uint8 season)57 	image_id get_background(uint16 phase, uint16 height, uint8 season) const
58 	{
59 		image_array_t const* const imglist = get_child<image_array_t>(0 + 2 * season);
60 		if(phase>0 && phase<phases) {
61 			if (image_t const* const image = imglist->get_image(height, phase)) {
62 				return image->get_id();
63 			}
64 		}
65 		// here if this phase does not exists ...
66 		image_t const* const image = imglist->get_image(height, 0);
67 		return image != NULL ? image->get_id() : IMG_EMPTY;
68 	}
69 
70 	// returns true, if the background is animated
is_background_animated(uint8 season)71 	bool is_background_animated(uint8 season) const
72 	{
73 		image_array_t const* const imglist = get_child<image_array_t>(0 + 2 * season);
74 		const uint16 max_h = imglist->get_count();
75 		for(  uint16 phase=1;  phase<phases;  phase++  ) {
76 			for(  uint16 h=0;  h<max_h;  h++  ) {
77 				if(  imglist->get_image( h, phase )  ) {
78 					return true;
79 				}
80 			}
81 		}
82 		return false;
83 	}
84 
get_foreground(uint16 phase,uint8 season)85 	image_id get_foreground(uint16 phase, uint8 season) const
86 	{
87 		image_array_t const* const imglist = get_child<image_array_t>(1 + 2 * season);
88 		if(phase>0 && phase<phases) {
89 			if (image_t const* const image = imglist->get_image(0, phase)) {
90 				return image->get_id();
91 			}
92 		}
93 		// here if this phase does not exists ...
94 		image_t const* const image = imglist->get_image(0, 0);
95 		return image != NULL ? image->get_id() : IMG_EMPTY;
96 	}
97 
98 	koord get_offset() const;
99 
100 	uint8 get_layout() const;
101 };
102 
103 /*
104  *  Author:
105  *      Volker Meyer
106  *
107  *  Description:
108  *      Data for one building, consists of potentially more than one tile.
109  *
110  *  Child nodes:
111  *	0   Name
112  *	1   Copyright
113  *	2   Tile 1
114  *	3   Tile 2
115  *	... ...
116  */
117 class building_desc_t : public obj_desc_timelined_t {
118 	friend class building_reader_t;
119 
120 public:
121 		/**
122 		 * Building types
123 		 */
124 		enum btype
125 		{
126 			unknown           =  0,
127 			attraction_city   =  1,
128 			attraction_land   =  2,
129 			monument          =  3,
130 			factory           =  4,
131 			townhall          =  5,
132 			others            =  6, ///< monorail foundation
133 			headquarters      =  7,
134 			dock              = 11, ///< dock, build on sloped coast
135 			// in these, the extra data points to a waytype
136 			depot             = 33,
137 			generic_stop      = 34,
138 			generic_extension = 35,
139 			flat_dock         = 36, ///< dock, but can start on a flat coast line
140 			// city buildings
141 			city_res          = 37, ///< residential city buildings
142 			city_com          = 38, ///< commercial  city buildings
143 			city_ind          = 39, ///< industrial  city buildings
144 		};
145 
146 
147 		enum flag_t {
148 			FLAG_NULL        = 0,
149 			FLAG_NO_INFO     = 1, ///< do not show info window
150 			FLAG_NO_PIT      = 2, ///< do not show construction pit
151 			FLAG_NEED_GROUND = 4, ///< needs ground drawn below
152 			FLAG_HAS_CURSOR  = 8  ///< there is cursor/icon for this
153 		};
154 private:
155 	/**
156 	 * Old named constants, only used for compatibility to load very old paks.
157 	 * These will be converted in building_reader_t::register_obj to a valid btype.
158 	 */
159 	enum old_building_types_t {
160 			bahnhof           =  8,
161 			bushalt           =  9,
162 			ladebucht         = 10,
163 			binnenhafen       = 12,
164 			airport           = 13,
165 			monorailstop      = 14,
166 			bahnhof_geb       = 16,
167 			bushalt_geb       = 17,
168 			ladebucht_geb     = 18,
169 			hafen_geb         = 19,
170 			binnenhafen_geb   = 20,
171 			airport_geb       = 21,
172 			monorail_geb      = 22,
173 			wartehalle        = 30,
174 			mail              = 31,
175 			lagerhalle        = 32,
176 		};
177 
178 	building_desc_t::btype type;
179 	uint16 animation_time;	// in ms
180 	uint32 extra_data;
181 		// extra data:
182 		// minimum population to build for city attractions,
183 		// waytype for depots
184 		// player level for headquarters
185 		// cluster number for city buildings (0 means no clustering)
186 	koord  size;
187 	flag_t flags;
188 	uint16 level;          // or passengers;
189 	uint8  layouts;        // 1 2, 4, 8  or 16
190 	uint8  enables;		// if it is a stop, what is enabled ...
191 	uint8  distribution_weight;         // Hajo: chance to build, special buildings, only other is weight factor
192 
193 
194 	/** @author: jamespetts.
195 	 * Additional fields for separate capacity/maintenance
196 	 * If these are not specified in the .dat file, they are set to
197 	 * PRICE_MAGIC then calculated from the "level" in the old way.
198 	 */
199 
200 	sint32 price;
201 	sint32 maintenance;
202 	uint16 capacity;
203 
204 #define PRICE_MAGIC (2147483647)
205 
206 
207 	climate_bits	allowed_climates;
208 
209 	/**
210 	 * Whether this building can or must be built underground.
211 	 * Only relevant for stations (generic_stop).
212 	 * 0 = cannot be built underground
213 	 * 1 = can only be built underground
214 	 * 2 = can be built either underground or above ground.
215 	 */
216 	uint8 allow_underground;
217 
is_type(building_desc_t::btype u)218 	bool is_type(building_desc_t::btype u) const {
219 		return type == u;
220 	}
221 
222 	tool_t *builder;
223 
224 public:
225 
226 	koord get_size(uint8 layout = 0) const {
227 		return (layout & 1) ? koord(size.y, size.x) : size;
228 	}
229 
230 	// size of the building
231 	sint16 get_y(uint8 layout = 0) const {
232 		return (layout & 1) ? size.x: size.y;
233 	}
234 
235 	sint16 get_x(uint8 layout = 0) const {
236 		return (layout & 1) ? size.y : size.x;
237 	}
238 
get_all_layouts()239 	uint8 get_all_layouts() const { return layouts; }
240 
get_extra()241 	uint32 get_extra() const { return extra_data; }
242 
243 	/** Returns waytype used for finance stats (distinguishes between tram track and train track) */
244 	waytype_t get_finance_waytype() const;
245 
246 	// ground is transparent
needs_ground()247 	bool needs_ground() const { return (flags & FLAG_NEED_GROUND) != 0; }
248 
249 	// no construction stage
no_construction_pit()250 	bool no_construction_pit() const { return (flags & FLAG_NO_PIT) != 0; }
251 
252 	// do not open info for this
no_info_window()253 	bool no_info_window() const { return (flags & FLAG_NO_INFO) != 0; }
254 
get_type()255 	building_desc_t::btype get_type() const { return type; }
256 
is_townhall()257 	bool is_townhall()      const { return is_type(townhall); }
is_headquarters()258 	bool is_headquarters()   const { return is_type(headquarters); }
is_attraction()259 	bool is_attraction() const { return is_type(attraction_land) || is_type(attraction_city); }
is_factory()260 	bool is_factory()       const { return is_type(factory); }
is_city_building()261 	bool is_city_building() const { return is_type(city_res) || is_type(city_com) || is_type(city_ind); }
is_transport_building()262 	bool is_transport_building() const { return type > headquarters  && type <= flat_dock; }
is_depot()263 	bool is_depot() const { return is_type(depot); }
264 
265 	bool is_connected_with_town() const;
266 
267 	/// @returns headquarters level (or -1 if building is not headquarters)
get_headquarters_level()268 	sint32 get_headquarters_level() const  { return (is_headquarters() ? get_extra() : -1) ; }
269 
270 	/**
271 	* the level is used in many places: for price, for capacity, ...
272 	* @author Hj. Malthaner
273 	*/
get_level()274 	uint16 get_level() const { return level; }
275 
276 	/**
277 	 * Mail generation level
278 	 * @author Hj. Malthaner
279 	 */
280 	uint16 get_mail_level() const;
281 
282 	// how often will this appear
get_distribution_weight()283 	uint8 get_distribution_weight() const { return distribution_weight; }
284 
get_tile(uint16 index)285 	const building_tile_desc_t *get_tile(uint16 index) const {
286 		assert(index < layouts * size.x * size.y);
287 		return get_child<building_tile_desc_t>(index + 2);
288 	}
289 
290 	const building_tile_desc_t *get_tile(uint8 layout, sint16 x, sint16 y) const;
291 
292 	// returns true,if building can be rotated
can_rotate()293 	bool can_rotate() const {
294 		if(size.x!=size.y  &&  layouts==1) {
295 			return false;
296 		}
297 		// check for missing tiles after rotation
298 		for( sint16 x=0;  x<size.x;  x++  ) {
299 			for( sint16 y=0;  y<size.y;  y++  ) {
300 				// only true, if one is missing
301 				if(get_tile( 0, x, y )->has_image()  ^  get_tile( 1, get_x(1)-y-1, x )->has_image()) {
302 					return false;
303 				}
304 			}
305 		}
306 		return true;
307 	}
308 
309 	uint8 adjust_layout(uint8 layout) const;
310 
311 	/**
312 	* Skin: cursor (index 0) and icon (index 1)
313 	* @author Hj. Malthaner
314 	*/
get_cursor()315 	const skin_desc_t * get_cursor() const {
316 		return flags & FLAG_HAS_CURSOR ? get_child<skin_desc_t>(2 + size.x * size.y * layouts) : 0;
317 	}
318 
319 	// the right house for this area?
is_allowed_climate(climate cl)320 	bool is_allowed_climate( climate cl ) const { return ((1<<cl)&allowed_climates)!=0; }
321 
322 	// the right house for this area?
is_allowed_climate_bits(climate_bits cl)323 	bool is_allowed_climate_bits( climate_bits cl ) const { return (cl&allowed_climates)!=0; }
324 
325 	// needed by place_finder
get_allowed_climate_bits()326 	climate_bits get_allowed_climate_bits() const { return allowed_climates; }
327 
328 	/**
329 	* @return station flags (only used for station buildings and oil rigs)
330 	* @author prissi
331 	*/
get_enabled()332 	uint8 get_enabled() const { return enables; }
333 
334 	/**
335 	* @return time for doing one step
336 	* @author prissi
337 	*/
get_animation_time()338 	uint16 get_animation_time() const { return animation_time; }
339 
340 	/**
341 	* @see above for maintenance/price/capacity variable information
342 	* @author Kieron Green/jamespetts
343 	*/
344 	sint32 get_maintenance(karte_t *world) const;
345 	sint32 get_price(karte_t *world) const;
get_capacity()346 	uint16 get_capacity() const { return capacity; }
347 
348 
349 	// default tool for building
get_builder()350 	tool_t *get_builder() const {
351 		return builder;
352 	}
set_builder(tool_t * tool)353 	void set_builder( tool_t *tool )  {
354 		builder = tool;
355 	}
356 
357 	void calc_checksum(checksum_t *chk) const;
358 
can_be_built_underground()359 	bool can_be_built_underground() const { return allow_underground > 0; }
can_be_built_aboveground()360 	bool can_be_built_aboveground() const { return allow_underground != 1; }
361 
get_clusters()362 	uint32 get_clusters() const {
363 		// Only meaningful for res, com, ind
364 		return is_city_building() ? extra_data : 0;
365 	}
366 };
367 
368 ENUM_BITSET(building_desc_t::flag_t)
369 
370 #endif
371