1 /***********************************************************************
2 Freeciv - Copyright (C) 1996 - A Kjeldberg, L Gregersen, P Unold
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; either version 2, or (at your option)
6 any later version.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12 ***********************************************************************/
13
14 /***********************************************************************
15 Functions for handling the tilespec files which describe
16 the files and contents of tilesets.
17 original author: David Pfitzner <dwp@mso.anu.edu.au>
18 ***********************************************************************/
19
20 #ifdef HAVE_CONFIG_H
21 #include <fc_config.h>
22 #endif
23
24 #include <stdio.h>
25 #include <stdlib.h> /* exit */
26 #include <stdarg.h>
27 #include <string.h>
28
29 /* utility */
30 #include "astring.h"
31 #include "bitvector.h"
32 #include "capability.h"
33 #include "deprecations.h"
34 #include "fcintl.h"
35 #include "log.h"
36 #include "mem.h"
37 #include "rand.h"
38 #include "registry.h"
39 #include "shared.h"
40 #include "string_vector.h"
41 #include "support.h"
42
43 /* common */
44 #include "base.h"
45 #include "effects.h"
46 #include "game.h" /* game.control.styles_count */
47 #include "government.h"
48 #include "map.h"
49 #include "movement.h"
50 #include "nation.h"
51 #include "player.h"
52 #include "road.h"
53 #include "specialist.h"
54 #include "unit.h"
55 #include "unitlist.h"
56
57 /* client/include */
58 #include "dialogs_g.h"
59 #include "graphics_g.h"
60 #include "gui_main_g.h"
61 #include "mapview_g.h" /* for update_map_canvas_visible */
62 #include "menu_g.h"
63 #include "themes_g.h"
64
65 /* client */
66 #include "citydlg_common.h" /* for generate_citydlg_dimensions() */
67 #include "client_main.h"
68 #include "climap.h" /* for client_tile_get_known() */
69 #include "colors_common.h"
70 #include "control.h" /* for fill_xxx */
71 #include "editor.h"
72 #include "goto.h"
73 #include "helpdata.h"
74 #include "options.h" /* for fill_xxx */
75 #include "themes_common.h"
76
77 #include "tilespec.h"
78
79 #define TILESPEC_CAPSTR "+Freeciv-2.6-tilespec duplicates_ok"
80 /*
81 * Tilespec capabilities acceptable to this program:
82 *
83 * +Freeciv-2.6-tilespec
84 * - basic format for Freeciv versions 2.6.x; required
85 *
86 * +Freeciv-tilespec-Devel-YYYY.MMM.DD
87 * - tilespec of the development version at the given date
88 *
89 * duplicates_ok
90 * - we can handle existence of duplicate tags (lattermost tag which
91 * appears is used; tilesets which have duplicates should specify
92 * "duplicates_ok")
93 */
94
95 #define SPEC_CAPSTR "+Freeciv-2.6-spec"
96 /*
97 * Individual spec file capabilities acceptable to this program:
98 *
99 * +Freeciv-2.6-spec
100 * - basic format for Freeciv versions 2.6.x; required
101 */
102
103 #define TILESPEC_SUFFIX ".tilespec"
104 #define TILE_SECTION_PREFIX "tile_"
105
106 /* This the way directional indices are now encoded: */
107 #define MAX_INDEX_CARDINAL 64
108 #define MAX_INDEX_HALF 16
109 #define MAX_INDEX_VALID 256
110
111 #define NUM_TILES_HP_BAR 11
112 #define NUM_TILES_DIGITS 10
113 #define NUM_TILES_SELECT 4
114 #define MAX_NUM_UPKEEP_SPRITES 10
115
116 #define SPECENUM_NAME extrastyle_id
117 #define SPECENUM_VALUE0 ESTYLE_ROAD_ALL_SEPARATE
118 #define SPECENUM_VALUE0NAME "RoadAllSeparate"
119 #define SPECENUM_VALUE1 ESTYLE_ROAD_PARITY_COMBINED
120 #define SPECENUM_VALUE1NAME "RoadParityCombined"
121 #define SPECENUM_VALUE2 ESTYLE_ROAD_ALL_COMBINED
122 #define SPECENUM_VALUE2NAME "RoadAllCombined"
123 #define SPECENUM_VALUE3 ESTYLE_RIVER
124 #define SPECENUM_VALUE3NAME "River"
125 #define SPECENUM_VALUE4 ESTYLE_SINGLE1
126 #define SPECENUM_VALUE4NAME "Single1"
127 #define SPECENUM_VALUE5 ESTYLE_SINGLE2
128 #define SPECENUM_VALUE5NAME "Single2"
129 #define SPECENUM_VALUE6 ESTYLE_3LAYER
130 #define SPECENUM_VALUE6NAME "3Layer"
131 #define SPECENUM_VALUE7 ESTYLE_CARDINALS
132 #define SPECENUM_VALUE7NAME "Cardinals"
133 #define SPECENUM_COUNT ESTYLE_COUNT
134 #include "specenum_gen.h"
135
136 /* This could be moved to common/map.h if there's more use for it. */
137 enum direction4 {
138 DIR4_NORTH = 0, DIR4_SOUTH, DIR4_EAST, DIR4_WEST
139 };
140 static const char direction4letters[4] = "udrl";
141 /* This must correspond to enum edge_type. */
142 static const char edge_name[EDGE_COUNT][3] = {"ns", "we", "ud", "lr"};
143
144 static const int DIR4_TO_DIR8[4] =
145 { DIR8_NORTH, DIR8_SOUTH, DIR8_EAST, DIR8_WEST };
146
147 enum match_style {
148 MATCH_NONE,
149 MATCH_SAME, /* "boolean" match */
150 MATCH_PAIR,
151 MATCH_FULL
152 };
153
154 enum sprite_type {
155 CELL_WHOLE, /* entire tile */
156 CELL_CORNER /* corner of tile */
157 };
158
159 struct drawing_data {
160 bool init;
161
162 char *name;
163
164 int num_layers; /* 1 thru MAX_NUM_LAYERS. */
165 #define MAX_NUM_LAYERS 3
166
167 struct drawing_layer {
168 bool is_tall;
169 int offset_x, offset_y;
170
171 #define MAX_NUM_MATCH_WITH 8
172 enum match_style match_style;
173 int match_index[1 + MAX_NUM_MATCH_WITH];
174 int match_indices; /* 0 = no match_type, 1 = no match_with */
175
176 enum sprite_type sprite_type;
177
178 struct sprite_vector base;
179 struct sprite *match[MAX_INDEX_CARDINAL];
180 struct sprite **cells;
181
182 /* List of those sprites in 'cells' that are allocated by some other
183 * means than load_sprite() and thus are not freed by unload_all_sprites(). */
184 struct sprite_vector allocated;
185 } layer[MAX_NUM_LAYERS];
186
187 bool is_reversed;
188
189 int blending; /* layer, 0 = none */
190 struct sprite *blender;
191 struct sprite *blend[4]; /* indexed by a direction4 */
192 };
193
194 struct city_style_threshold {
195 struct sprite *sprite;
196 };
197
198 struct city_sprite {
199 struct {
200 int land_num_thresholds;
201 struct city_style_threshold *land_thresholds;
202 } *styles;
203 int num_styles;
204 };
205
206 struct river_sprites {
207 struct sprite
208 *spec[MAX_INDEX_CARDINAL],
209 *outlet[MAX_INDEX_CARDINAL];
210 };
211
212 struct named_sprites {
213 struct sprite
214 *indicator[INDICATOR_COUNT][NUM_TILES_PROGRESS],
215 *treaty_thumb[2], /* 0=disagree, 1=agree */
216 *arrow[ARROW_LAST], /* 0=right arrow, 1=plus, 2=minus */
217
218 *icon[ICON_COUNT],
219
220 *events[E_COUNT],
221
222 /* The panel sprites for showing tax % allocations. */
223 *tax_luxury, *tax_science, *tax_gold,
224 *dither_tile; /* only used for isometric view */
225
226 struct {
227 struct sprite
228 *tile,
229 *worked_tile,
230 *unworked_tile;
231 } mask;
232
233 struct sprite *tech[A_LAST];
234 struct sprite *building[B_LAST];
235 struct sprite *government[G_LAST];
236
237 struct {
238 struct sprite *icon[U_LAST];
239 struct sprite *facing[U_LAST][DIR8_MAGIC_MAX];
240 unsigned int default_dir_seed[U_LAST];
241 } units;
242
243 struct sprite *resource[MAX_NUM_RESOURCES];
244
245 struct sprite_vector nation_flag;
246 struct sprite_vector nation_shield;
247
248 struct citizen_graphic {
249 /* Each citizen type has up to MAX_NUM_CITIZEN_SPRITES different
250 * sprites, as defined by the tileset. */
251 int count;
252 struct sprite *sprite[MAX_NUM_CITIZEN_SPRITES];
253 } citizen[CITIZEN_LAST], specialist[SP_MAX];
254 struct sprite *spaceship[SPACESHIP_COUNT];
255 struct {
256 int hot_x, hot_y;
257 struct sprite *frame[NUM_CURSOR_FRAMES];
258 } cursor[CURSOR_LAST];
259 struct {
260 struct sprite_vector unit;
261 struct sprite *nuke;
262 } explode;
263 struct {
264 struct sprite
265 *hp_bar[NUM_TILES_HP_BAR],
266 *vet_lev[MAX_VET_LEVELS],
267 *select[NUM_TILES_SELECT],
268 *auto_attack,
269 *auto_settler,
270 *auto_explore,
271 *fortified,
272 *fortifying,
273 *go_to, /* goto is a C keyword :-) */
274 *irrigate,
275 *plant,
276 *pillage,
277 *sentry,
278 *stack,
279 *loaded,
280 *transform,
281 *connect,
282 *patrol,
283 *convert,
284 *battlegroup[MAX_NUM_BATTLEGROUPS],
285 *lowfuel,
286 *tired;
287 } unit;
288 struct {
289 struct sprite
290 *unhappy[MAX_NUM_UPKEEP_SPRITES],
291 *output[O_LAST][MAX_NUM_UPKEEP_SPRITES];
292 } upkeep;
293 struct {
294 struct sprite
295 *disorder,
296 *size[NUM_TILES_DIGITS],
297 *size_tens[NUM_TILES_DIGITS],
298 *size_hundreds[NUM_TILES_DIGITS],
299 *tile_foodnum[NUM_TILES_DIGITS],
300 *tile_shieldnum[NUM_TILES_DIGITS],
301 *tile_tradenum[NUM_TILES_DIGITS];
302 struct city_sprite
303 *tile,
304 *single_wall,
305 *wall[NUM_WALL_TYPES],
306 *occupied;
307 struct sprite_vector worked_tile_overlay;
308 struct sprite_vector unworked_tile_overlay;
309 } city;
310 struct citybar_sprites citybar;
311 struct editor_sprites editor;
312 struct {
313 struct {
314 struct sprite *specific;
315 struct sprite *turns[NUM_TILES_DIGITS];
316 struct sprite *turns_tens[NUM_TILES_DIGITS];
317 struct sprite *turns_hundreds[NUM_TILES_DIGITS];
318 } s[GTS_COUNT];
319 struct sprite *waypoint;
320 } path;
321 struct {
322 struct sprite *attention;
323 } user;
324 struct {
325 struct sprite
326 *fog,
327 **fullfog,
328 *darkness[MAX_INDEX_CARDINAL]; /* first unused */
329 } tx; /* terrain extra */
330 struct {
331 struct sprite
332 *activity,
333 *rmact;
334 enum extrastyle_id extrastyle;
335 union {
336 struct sprite *single;
337 struct sprite *cardinals[MAX_INDEX_CARDINAL];
338 struct {
339 struct sprite
340 *background,
341 *middleground,
342 *foreground;
343 } bmf;
344 struct {
345 struct sprite
346 /* for extrastyles ESTYLE_ROAD_ALL_SEPARATE and ESTYLE_ROAD_PARITY_COMBINED */
347 *isolated,
348 *corner[8]; /* Indexed by direction; only non-cardinal dirs used. */
349 union {
350 /* for ESTYLE_ROAD_ALL_SEPARATE */
351 struct sprite *dir[8]; /* all entries used */
352 /* ESTYLE_ROAD_PARITY_COMBINED */
353 struct {
354 struct sprite
355 *even[MAX_INDEX_HALF], /* first unused */
356 *odd[MAX_INDEX_HALF]; /* first unused */
357 } combo;
358 /* ESTYLE_ALL_SEPARATE */
359 struct sprite *total[MAX_INDEX_VALID];
360 struct river_sprites rivers;
361 } ru;
362 } road;
363 } u;
364 } extras[MAX_EXTRA_TYPES];
365 struct {
366 struct sprite
367 *main[EDGE_COUNT],
368 *city[EDGE_COUNT],
369 *worked[EDGE_COUNT],
370 *unavailable,
371 *nonnative,
372 *selected[EDGE_COUNT],
373 *coastline[EDGE_COUNT],
374 *borders[EDGE_COUNT][2];
375 } grid;
376 struct {
377 struct sprite_vector overlays;
378 } colors;
379 struct {
380 struct sprite *color; /* Generic background color */
381 struct sprite *graphic; /* Generic background graphic */
382 } background;
383 struct {
384 struct sprite *grid_borders[EDGE_COUNT][2];
385 struct sprite *color;
386 struct sprite *background;
387 } player[MAX_NUM_PLAYER_SLOTS];
388
389 struct drawing_data *drawing[MAX_NUM_ITEMS];
390 };
391
392 struct specfile {
393 struct sprite *big_sprite;
394 char *file_name;
395 };
396
397 #define SPECLIST_TAG specfile
398 #define SPECLIST_TYPE struct specfile
399 #include "speclist.h"
400
401 #define specfile_list_iterate(list, pitem) \
402 TYPED_LIST_ITERATE(struct specfile, list, pitem)
403 #define specfile_list_iterate_end LIST_ITERATE_END
404
405 /*
406 * Information about an individual sprite. All fields except 'sprite' are
407 * filled at the time of the scan of the specfile. 'Sprite' is
408 * set/cleared on demand in load_sprite/unload_sprite.
409 */
410 struct small_sprite {
411 int ref_count;
412
413 /* The sprite is in this file. */
414 char *file;
415
416 /* Or, the sprite is in this file at the location. */
417 struct specfile *sf;
418 int x, y, width, height;
419
420 /* A little more (optional) data. */
421 int hot_x, hot_y;
422
423 struct sprite *sprite;
424 };
425
426 /* 'struct small_sprite_list' and related functions. */
427 #define SPECLIST_TAG small_sprite
428 #define SPECLIST_TYPE struct small_sprite
429 #include "speclist.h"
430 #define small_sprite_list_iterate(list, pitem) \
431 TYPED_LIST_ITERATE(struct small_sprite, list, pitem)
432 #define small_sprite_list_iterate_end LIST_ITERATE_END
433
434 /* 'struct sprite_hash' and related functions. */
435 #define SPECHASH_TAG sprite
436 #define SPECHASH_ASTR_KEY_TYPE
437 #define SPECHASH_IDATA_TYPE struct small_sprite *
438 #include "spechash.h"
439 #define sprite_hash_iterate(hash, tag_name, sprite) \
440 TYPED_HASH_ITERATE(const char *, struct small_sprite *, \
441 hash, tag_name, sprite)
442 #define sprite_hash_iterate_end HASH_ITERATE_END
443
444 /* 'struct drawing_hash' and related functions. */
445 static void drawing_data_destroy(struct drawing_data *draw);
446
447 #define SPECHASH_TAG drawing
448 #define SPECHASH_CSTR_KEY_TYPE
449 #define SPECHASH_IDATA_TYPE struct drawing_data *
450 #define SPECHASH_IDATA_FREE drawing_data_destroy
451 #include "spechash.h"
452
453 #define SPECHASH_TAG estyle
454 #define SPECHASH_ASTR_KEY_TYPE
455 #define SPECHASH_ENUM_DATA_TYPE extrastyle_id
456 #include "spechash.h"
457
458 struct tileset {
459 char name[512];
460 char given_name[MAX_LEN_NAME];
461 char version[MAX_LEN_NAME];
462 int priority;
463
464 char *summary;
465 char *description;
466 float scale;
467
468 enum ts_type type;
469 int hex_width, hex_height;
470 int ts_topo_idx;
471
472 int normal_tile_width, normal_tile_height;
473 int full_tile_width, full_tile_height;
474 int unit_tile_width, unit_tile_height;
475 int small_sprite_width, small_sprite_height;
476
477 int max_upkeep_height;
478
479 char *main_intro_filename;
480 char *minimap_intro_filename;
481
482 int city_names_font_size, city_productions_font_size;
483
484 enum fog_style fogstyle;
485 enum darkness_style darkness_style;
486 int darkness_layer;
487
488 int unit_flag_offset_x, unit_flag_offset_y;
489 int city_flag_offset_x, city_flag_offset_y;
490 int unit_offset_x, unit_offset_y;
491 int city_offset_x, city_offset_y;
492
493 int citybar_offset_y;
494 int tilelabel_offset_y;
495 int activity_offset_x;
496 int activity_offset_y;
497 int occupied_offset_x;
498 int occupied_offset_y;
499 int unit_upkeep_offset_y;
500 int unit_upkeep_small_offset_y;
501
502 #define NUM_CORNER_DIRS 4
503 #define TILES_PER_CORNER 4
504 int num_valid_tileset_dirs, num_cardinal_tileset_dirs;
505 int num_index_valid, num_index_cardinal;
506 enum direction8 valid_tileset_dirs[8], cardinal_tileset_dirs[8];
507
508 struct tileset_layer {
509 char **match_types;
510 size_t match_count;
511 } layers[MAX_NUM_LAYERS];
512
513 struct specfile_list *specfiles;
514 struct small_sprite_list *small_sprites;
515
516 /* This hash table maps tilespec tags to struct small_sprites. */
517 struct sprite_hash *sprite_hash;
518
519 /* This hash table maps terrain graphic strings to drawing data. */
520 struct drawing_hash *tile_hash;
521
522 struct estyle_hash *estyle_hash;
523
524 struct named_sprites sprites;
525
526 struct color_system *color_system;
527
528 struct extra_type_list *style_lists[ESTYLE_COUNT];
529
530 struct extra_type_list *flagged_bases_list;
531
532 int num_preferred_themes;
533 char** preferred_themes;
534 };
535
536 struct tileset *tileset;
537 struct tileset *unscaled_tileset;
538
539 int focus_unit_state = 0;
540
541 static bool tileset_update = FALSE;
542
543
544 static int fill_unit_type_sprite_array(const struct tileset *t,
545 struct drawn_sprite *sprs,
546 const struct unit_type *putype,
547 enum direction8 facing);
548 static int fill_unit_sprite_array(const struct tileset *t,
549 struct drawn_sprite *sprs,
550 const struct unit *punit,
551 bool stack, bool backdrop);
552 static bool load_river_sprites(struct tileset *t,
553 struct river_sprites *store, const char *tag_pfx);
554
555 static void tileset_setup_base(struct tileset *t,
556 const struct extra_type *pextra);
557 static void tileset_setup_road(struct tileset *t,
558 struct extra_type *pextra);
559
560 static bool is_extra_drawing_enabled(struct extra_type *pextra);
561
562 static int fill_basic_road_sprite_array(const struct tileset *t,
563 struct drawn_sprite *sprs,
564 const struct extra_type *pextra);
565 static int fill_basic_base_sprite_array(const struct tileset *t,
566 struct drawn_sprite *sprs,
567 const struct extra_type *pextra);
568
569 static void tileset_player_free(struct tileset *t, int plrid);
570
571 /****************************************************************************
572 Called when ever there's problem in ruleset/tileset compatibility
573 ****************************************************************************/
tileset_error(enum log_level level,const char * format,...)574 void tileset_error(enum log_level level, const char *format, ...)
575 {
576 char buf[2048];
577 va_list args;
578
579 va_start(args, format);
580 fc_vsnprintf(buf, sizeof(buf), format, args);
581 va_end(args);
582
583 log_base(level, "%s", buf);
584
585 if (level <= LOG_NORMAL) {
586 show_tileset_error(buf);
587 }
588
589 if (level == LOG_FATAL) {
590 exit(EXIT_FAILURE);
591 }
592 }
593
594 /****************************************************************************
595 Create a new drawing data.
596 ****************************************************************************/
drawing_data_new(void)597 static struct drawing_data *drawing_data_new(void)
598 {
599 struct drawing_data *draw = fc_calloc(1, sizeof(*draw));
600
601 draw->name = NULL;
602
603 return draw;
604 }
605
606 /****************************************************************************
607 Free a drawing data.
608 ****************************************************************************/
drawing_data_destroy(struct drawing_data * draw)609 static void drawing_data_destroy(struct drawing_data *draw)
610 {
611 int i;
612
613 fc_assert_ret(NULL != draw);
614
615 if (draw->name != NULL) {
616 free(draw->name);
617 }
618 for (i = 0; i < 4; i++) {
619 if (draw->blend[i]) {
620 free_sprite(draw->blend[i]);
621 }
622 }
623 for (i = 0; i < draw->num_layers; i++) {
624 int vec_size = sprite_vector_size(&draw->layer[i].allocated);
625 int j;
626
627 for (j = 0; j < vec_size; j++) {
628 free_sprite(draw->layer[i].allocated.p[j]);
629 }
630
631 sprite_vector_free(&draw->layer[i].base);
632 sprite_vector_free(&draw->layer[i].allocated);
633 free(draw->layer[i].cells);
634 }
635 free(draw);
636 }
637
638 /****************************************************************************
639 Return unscaled tileset if it exists, or default otherwise
640 ****************************************************************************/
get_tileset(void)641 struct tileset* get_tileset(void)
642 {
643 if (unscaled_tileset != NULL) {
644 return unscaled_tileset;
645 } else {
646 return tileset;
647 }
648 }
649
650 /****************************************************************************
651 Return the name of the given tileset.
652 ****************************************************************************/
tileset_basename(const struct tileset * t)653 const char *tileset_basename(const struct tileset *t)
654 {
655 return t->name;
656 }
657
658 /****************************************************************************
659 Return whether the current tileset is isometric.
660 ****************************************************************************/
tileset_is_isometric(const struct tileset * t)661 bool tileset_is_isometric(const struct tileset *t)
662 {
663 return t->type == TS_ISOMETRIC;
664 }
665
666 /****************************************************************************
667 Return the hex_width of the current tileset. For iso-hex tilesets this
668 value will be > 0 and is_isometric will be set.
669 ****************************************************************************/
tileset_hex_width(const struct tileset * t)670 int tileset_hex_width(const struct tileset *t)
671 {
672 return t->hex_width;
673 }
674
675 /****************************************************************************
676 Return the hex_height of the current tileset. For hex tilesets this
677 value will be > 0 and is_isometric will be set.
678 ****************************************************************************/
tileset_hex_height(const struct tileset * t)679 int tileset_hex_height(const struct tileset *t)
680 {
681 return t->hex_height;
682 }
683
684 /****************************************************************************
685 Return the tile width of the current tileset. This is the tesselation
686 width of the tiled plane. This means it's the width of the bounding box
687 of the basic map tile.
688
689 For best results:
690 - The value should be even (or a multiple of 4 in iso-view).
691 - In iso-view, the width should be twice the height (to give a
692 perspective of 30 degrees above the horizon).
693 - In non-iso-view, width and height should be equal (overhead
694 perspective).
695 - In hex or iso-hex view, remember this is the tesselation vector.
696 hex_width and hex_height then give the size of the side of the
697 hexagon. Calculating the dimensions of a "regular" hexagon or
698 iso-hexagon may be tricky.
699 However these requirements are not absolute and callers should not
700 depend on them (although some do).
701 ****************************************************************************/
tileset_tile_width(const struct tileset * t)702 int tileset_tile_width(const struct tileset *t)
703 {
704 return t->normal_tile_width;
705 }
706
707 /****************************************************************************
708 Return the tile height of the current tileset. This is the tesselation
709 height of the tiled plane. This means it's the height of the bounding box
710 of the basic map tile.
711
712 See also tileset_tile_width.
713 ****************************************************************************/
tileset_tile_height(const struct tileset * t)714 int tileset_tile_height(const struct tileset *t)
715 {
716 return t->normal_tile_height;
717 }
718
719 /****************************************************************************
720 Return the full tile width of the current tileset. This is the maximum
721 width that any mapview sprite will have.
722
723 Note: currently this is always equal to the tile width.
724 ****************************************************************************/
tileset_full_tile_width(const struct tileset * t)725 int tileset_full_tile_width(const struct tileset *t)
726 {
727 return t->full_tile_width;
728 }
729
730 /****************************************************************************
731 Return the full tile height of the current tileset. This is the maximum
732 height that any mapview sprite will have. This may be greater than the
733 tile width in which case the extra area is above the "normal" tile.
734
735 Some callers assume the full height is 50% larger than the height in
736 iso-view, and equal in non-iso view.
737 ****************************************************************************/
tileset_full_tile_height(const struct tileset * t)738 int tileset_full_tile_height(const struct tileset *t)
739 {
740 return t->full_tile_height;
741 }
742
743 /****************************************************************************
744 Return the unit tile width of the current tileset.
745 ****************************************************************************/
tileset_unit_width(const struct tileset * t)746 int tileset_unit_width(const struct tileset *t)
747 {
748 return t->unit_tile_width;
749 }
750
751 /****************************************************************************
752 Return the unit tile height of the current tileset.
753 ****************************************************************************/
tileset_unit_height(const struct tileset * t)754 int tileset_unit_height(const struct tileset *t)
755 {
756 return t->unit_tile_height;
757 }
758
759 /****************************************************************************
760 Calculate the height of a unit upkeep icons.
761 ****************************************************************************/
calculate_max_upkeep_height(const struct tileset * t)762 static int calculate_max_upkeep_height(const struct tileset *t)
763 {
764 int i;
765 int max = 0;
766
767 for (i = 0; i < MAX_NUM_UPKEEP_SPRITES; i++) {
768 if (t->sprites.upkeep.unhappy[i] != NULL) {
769 int width, height;
770
771 /* TODO: We want only height, getting the width might waste CPU
772 * depending on gui-specific implementation. */
773 get_sprite_dimensions(t->sprites.upkeep.unhappy[i], &width, &height);
774
775 max = MAX(max, height);
776 }
777 }
778
779 output_type_iterate(o) {
780 for (i = 0; i < MAX_NUM_UPKEEP_SPRITES; i++) {
781 if (t->sprites.upkeep.output[o][i] != NULL) {
782 int width, height;
783
784 /* TODO: We want only height, getting the width might waste CPU
785 * depending on gui-specific implementation. */
786 get_sprite_dimensions(t->sprites.upkeep.output[o][i], &width, &height);
787
788 max = MAX(max, height);
789 }
790 }
791 } output_type_iterate_end;
792
793 return max;
794 }
795
796 /****************************************************************************
797 Get the height of a unit upkeep icons.
798 ****************************************************************************/
tileset_upkeep_height(const struct tileset * t)799 static int tileset_upkeep_height(const struct tileset *t)
800 {
801 /* Return cached value */
802 return t->max_upkeep_height;
803 }
804
805 /****************************************************************************
806 Suitable canvas height for a unit icon that includes upkeep sprites.
807 ****************************************************************************/
tileset_unit_with_upkeep_height(const struct tileset * t)808 int tileset_unit_with_upkeep_height(const struct tileset *t)
809 {
810 int uk_bottom = tileset_unit_layout_offset_y(tileset) + tileset_upkeep_height(tileset);
811 int u_bottom = tileset_unit_height(tileset);
812
813 return MAX(uk_bottom, u_bottom);
814 }
815
816 /****************************************************************************
817 Suitable canvas height for a unit icon that includes upkeep sprites,
818 using small space layout.
819 ****************************************************************************/
tileset_unit_with_small_upkeep_height(const struct tileset * t)820 int tileset_unit_with_small_upkeep_height(const struct tileset *t)
821 {
822 return tileset_unit_layout_small_offset_y(tileset) + tileset_upkeep_height(tileset);
823 }
824
825 /****************************************************************************
826 Offset to layout extra unit sprites, such as upkeep.
827 ****************************************************************************/
tileset_unit_layout_offset_y(const struct tileset * t)828 int tileset_unit_layout_offset_y(const struct tileset *t)
829 {
830 return t->unit_upkeep_offset_y;
831 }
832
833 /****************************************************************************
834 Offset to layout extra unit sprites, such as upkeep, requesting small
835 space layout.
836 ****************************************************************************/
tileset_unit_layout_small_offset_y(const struct tileset * t)837 int tileset_unit_layout_small_offset_y(const struct tileset *t)
838 {
839 return t->unit_upkeep_small_offset_y;
840 }
841
842 /****************************************************************************
843 Return the small sprite width of the current tileset. The small sprites
844 are used for various theme graphics (e.g., citymap citizens/specialists
845 as well as panel indicator icons).
846 ****************************************************************************/
tileset_small_sprite_width(const struct tileset * t)847 int tileset_small_sprite_width(const struct tileset *t)
848 {
849 return t->small_sprite_width;
850 }
851
852 /****************************************************************************
853 Return the offset from the origin of the city tile at which to place the
854 city bar text.
855 ****************************************************************************/
tileset_citybar_offset_y(const struct tileset * t)856 int tileset_citybar_offset_y(const struct tileset *t)
857 {
858 return t->citybar_offset_y;
859 }
860
861 /****************************************************************************
862 Return the offset from the origin of the tile at which to place the
863 label text.
864 ****************************************************************************/
tileset_tilelabel_offset_y(const struct tileset * t)865 int tileset_tilelabel_offset_y(const struct tileset *t)
866 {
867 return t->tilelabel_offset_y;
868 }
869
870 /****************************************************************************
871 Returns tileset scale
872 ****************************************************************************/
tileset_scale(const struct tileset * t)873 float tileset_scale(const struct tileset *t)
874 {
875 return tileset->scale;
876 }
877
878 /****************************************************************************
879 Return the small sprite height of the current tileset. The small sprites
880 are used for various theme graphics (e.g., citymap citizens/specialists
881 as well as panel indicator icons).
882 ****************************************************************************/
tileset_small_sprite_height(const struct tileset * t)883 int tileset_small_sprite_height(const struct tileset *t)
884 {
885 return t->small_sprite_height;
886 }
887
888 /****************************************************************************
889 Return the path within the data directories where the main intro graphics
890 file can be found. (It is left up to the GUI code to load and unload this
891 file.)
892 ****************************************************************************/
tileset_main_intro_filename(const struct tileset * t)893 const char *tileset_main_intro_filename(const struct tileset *t)
894 {
895 return t->main_intro_filename;
896 }
897
898 /****************************************************************************
899 Return the path within the data directories where the mini intro graphics
900 file can be found. (It is left up to the GUI code to load and unload this
901 file.)
902 ****************************************************************************/
tileset_mini_intro_filename(const struct tileset * t)903 const char *tileset_mini_intro_filename(const struct tileset *t)
904 {
905 return t->minimap_intro_filename;
906 }
907
908 /****************************************************************************
909 Return the number of possible colors for city overlays.
910 ****************************************************************************/
tileset_num_city_colors(const struct tileset * t)911 int tileset_num_city_colors(const struct tileset *t)
912 {
913 return t->sprites.city.worked_tile_overlay.size;
914 }
915
916 /****************************************************************************
917 Return TRUE if the client will use the code to generate the fog.
918 ****************************************************************************/
tileset_use_hard_coded_fog(const struct tileset * t)919 bool tileset_use_hard_coded_fog(const struct tileset *t)
920 {
921 return FOG_AUTO == t->fogstyle;
922 }
923
924 /**************************************************************************
925 Initialize.
926 **************************************************************************/
tileset_new(void)927 static struct tileset *tileset_new(void)
928 {
929 struct tileset *t = fc_calloc(1, sizeof(*t));
930
931 t->specfiles = specfile_list_new();
932 t->small_sprites = small_sprite_list_new();
933 return t;
934 }
935
936 /**************************************************************************
937 Return the tileset name of the direction. This is similar to
938 dir_get_name but you shouldn't change this or all tilesets will break.
939 **************************************************************************/
dir_get_tileset_name(enum direction8 dir)940 static const char *dir_get_tileset_name(enum direction8 dir)
941 {
942 switch (dir) {
943 case DIR8_NORTH:
944 return "n";
945 case DIR8_NORTHEAST:
946 return "ne";
947 case DIR8_EAST:
948 return "e";
949 case DIR8_SOUTHEAST:
950 return "se";
951 case DIR8_SOUTH:
952 return "s";
953 case DIR8_SOUTHWEST:
954 return "sw";
955 case DIR8_WEST:
956 return "w";
957 case DIR8_NORTHWEST:
958 return "nw";
959 }
960 log_error("Wrong direction8 variant: %d.", dir);
961 return "";
962 }
963
964 /****************************************************************************
965 Return TRUE iff the dir is valid in this tileset.
966 ****************************************************************************/
is_valid_tileset_dir(const struct tileset * t,enum direction8 dir)967 static bool is_valid_tileset_dir(const struct tileset *t,
968 enum direction8 dir)
969 {
970 if (t->hex_width > 0) {
971 return dir != DIR8_NORTHEAST && dir != DIR8_SOUTHWEST;
972 } else if (t->hex_height > 0) {
973 return dir != DIR8_NORTHWEST && dir != DIR8_SOUTHEAST;
974 } else {
975 return TRUE;
976 }
977 }
978
979 /****************************************************************************
980 Return TRUE iff the dir is cardinal in this tileset.
981
982 "Cardinal", in this sense, means that a tile will share a border with
983 another tile in the direction rather than sharing just a single vertex.
984 ****************************************************************************/
is_cardinal_tileset_dir(const struct tileset * t,enum direction8 dir)985 static bool is_cardinal_tileset_dir(const struct tileset *t,
986 enum direction8 dir)
987 {
988 if (t->hex_width > 0 || t->hex_height > 0) {
989 return is_valid_tileset_dir(t, dir);
990 } else {
991 return (dir == DIR8_NORTH || dir == DIR8_EAST
992 || dir == DIR8_SOUTH || dir == DIR8_WEST);
993 }
994 }
995
996 /**********************************************************************
997 Convert properties of the actual topology to an index of different
998 tileset topology types.
999 ***********************************************************************/
ts_topology_index(int actual_topology)1000 static int ts_topology_index(int actual_topology)
1001 {
1002 int idx;
1003
1004 if ((actual_topology & TF_HEX)
1005 && (actual_topology & TF_ISO)) {
1006 idx = TS_TOPO_ISOHEX;
1007 } else if (actual_topology & TF_ISO) {
1008 idx = TS_TOPO_ISO;
1009 } else if (actual_topology & TF_HEX) {
1010 idx = TS_TOPO_HEX;
1011 } else {
1012 idx = TS_TOPO_OVERHEAD;
1013 }
1014
1015 return idx;
1016 }
1017
1018 /**********************************************************************
1019 Returns a static list of tilesets available on the system by
1020 searching all data directories for files matching TILESPEC_SUFFIX.
1021 ***********************************************************************/
get_tileset_list(const struct option * poption)1022 const struct strvec *get_tileset_list(const struct option *poption)
1023 {
1024 static struct strvec *tilesets[4] = { NULL, NULL, NULL, NULL };
1025 int topo = option_get_cb_data(poption);
1026 int idx;
1027
1028 idx = ts_topology_index(topo);
1029
1030 fc_assert_ret_val(idx < ARRAY_SIZE(tilesets), NULL);
1031
1032 if (tilesets[idx] == NULL) {
1033 /* Note: this means you must restart the client after installing a new
1034 tileset. */
1035 struct strvec *list = fileinfolist(get_data_dirs(), TILESPEC_SUFFIX);
1036
1037 tilesets[idx] = strvec_new();
1038 strvec_iterate(list, file) {
1039 struct tileset *t = tileset_read_toplevel(file, FALSE, topo, 1.0f);
1040
1041 if (t) {
1042 strvec_append(tilesets[idx], file);
1043 tileset_free(t);
1044 }
1045 } strvec_iterate_end;
1046 strvec_destroy(list);
1047 }
1048
1049 return tilesets[idx];
1050 }
1051
1052 /**********************************************************************
1053 Gets full filename for tilespec file, based on input name.
1054 Returned data is allocated, and freed by user as required.
1055 Input name may be null, in which case uses default.
1056 Falls back to default if can't find specified name;
1057 dies if can't find default.
1058 ***********************************************************************/
tilespec_fullname(const char * tileset_name)1059 static char *tilespec_fullname(const char *tileset_name)
1060 {
1061 if (tileset_name) {
1062 char fname[strlen(tileset_name) + strlen(TILESPEC_SUFFIX) + 1];
1063 const char *dname;
1064
1065 fc_snprintf(fname, sizeof(fname),
1066 "%s%s", tileset_name, TILESPEC_SUFFIX);
1067
1068 dname = fileinfoname(get_data_dirs(), fname);
1069
1070 if (dname) {
1071 return fc_strdup(dname);
1072 }
1073 }
1074
1075 return NULL;
1076 }
1077
1078 /**********************************************************************
1079 Checks options in filename match what we require and support.
1080 Die if not.
1081 'which' should be "tilespec" or "spec".
1082 ***********************************************************************/
check_tilespec_capabilities(struct section_file * file,const char * which,const char * us_capstr,const char * filename,bool verbose)1083 static bool check_tilespec_capabilities(struct section_file *file,
1084 const char *which,
1085 const char *us_capstr,
1086 const char *filename,
1087 bool verbose)
1088 {
1089 enum log_level level = verbose ? LOG_ERROR : LOG_DEBUG;
1090
1091 const char *file_capstr = secfile_lookup_str(file, "%s.options", which);
1092
1093 if (NULL == file_capstr) {
1094 log_base(level, "\"%s\": %s file doesn't have a capability string",
1095 filename, which);
1096 return FALSE;
1097 }
1098 if (!has_capabilities(us_capstr, file_capstr)) {
1099 log_base(level, "\"%s\": %s file appears incompatible:",
1100 filename, which);
1101 log_base(level, " datafile options: %s", file_capstr);
1102 log_base(level, " supported options: %s", us_capstr);
1103 return FALSE;
1104 }
1105 if (!has_capabilities(file_capstr, us_capstr)) {
1106 log_base(level, "\"%s\": %s file requires option(s) "
1107 "that client doesn't support:", filename, which);
1108 log_base(level, " datafile options: %s", file_capstr);
1109 log_base(level, " supported options: %s", us_capstr);
1110 return FALSE;
1111 }
1112
1113 return TRUE;
1114 }
1115
1116 /**********************************************************************
1117 Frees the tilespec toplevel data, in preparation for re-reading it.
1118
1119 See tilespec_read_toplevel().
1120 ***********************************************************************/
tileset_free_toplevel(struct tileset * t)1121 static void tileset_free_toplevel(struct tileset *t)
1122 {
1123 int i, j;
1124
1125 if (t->main_intro_filename) {
1126 free(t->main_intro_filename);
1127 t->main_intro_filename = NULL;
1128 }
1129 if (t->minimap_intro_filename) {
1130 free(t->minimap_intro_filename);
1131 t->minimap_intro_filename = NULL;
1132 }
1133
1134 if (t->preferred_themes) {
1135 for (i = 0; i < t->num_preferred_themes; i++) {
1136 free(t->preferred_themes[i]);
1137 }
1138 free(t->preferred_themes);
1139 t->preferred_themes = NULL;
1140 }
1141 t->num_preferred_themes = 0;
1142
1143 if (t->tile_hash) {
1144 drawing_hash_destroy(t->tile_hash);
1145 t->tile_hash = NULL; /* Helpful for sanity. */
1146 }
1147 if (t->estyle_hash) {
1148 estyle_hash_destroy(t->estyle_hash);
1149 t->estyle_hash = NULL;
1150 }
1151 for (i = 0; i < ESTYLE_COUNT; i++) {
1152 if (t->style_lists[i] != NULL) {
1153 extra_type_list_destroy(t->style_lists[i]);
1154 t->style_lists[i] = NULL;
1155 }
1156 }
1157
1158 if (t->flagged_bases_list != NULL) {
1159 extra_type_list_destroy(t->flagged_bases_list);
1160 t->flagged_bases_list = NULL;
1161 }
1162
1163 for (i = 0; i < MAX_NUM_LAYERS; i++) {
1164 struct tileset_layer *tslp = &t->layers[i];
1165
1166 if (tslp->match_types) {
1167 for (j = 0; j < tslp->match_count; j++) {
1168 free(tslp->match_types[j]);
1169 }
1170 free(tslp->match_types);
1171 tslp->match_types = NULL;
1172 }
1173 }
1174
1175 if (t->color_system) {
1176 color_system_free(t->color_system);
1177 t->color_system = NULL;
1178 }
1179
1180 if (t->summary != NULL) {
1181 free(t->summary);
1182 t->summary = NULL;
1183 }
1184 if (t->description != NULL) {
1185 free(t->description);
1186 t->description = NULL;
1187 }
1188 }
1189
1190 /**************************************************************************
1191 Clean up.
1192 **************************************************************************/
tileset_free(struct tileset * t)1193 void tileset_free(struct tileset *t)
1194 {
1195 int i;
1196
1197 tileset_free_tiles(t);
1198 tileset_free_toplevel(t);
1199 for (i = 0; i < ARRAY_SIZE(t->sprites.player); i++) {
1200 tileset_player_free(t, i);
1201 }
1202 specfile_list_destroy(t->specfiles);
1203 small_sprite_list_destroy(t->small_sprites);
1204 free(t);
1205 }
1206
1207 /**********************************************************************
1208 Read a new tilespec in when first starting the game.
1209
1210 Call this function with the (guessed) name of the tileset, when
1211 starting the client.
1212
1213 Returns TRUE iff tileset with suggested tileset_name was loaded.
1214 ***********************************************************************/
tilespec_try_read(const char * tileset_name,bool verbose,int topo_id,bool global_default)1215 bool tilespec_try_read(const char *tileset_name, bool verbose, int topo_id,
1216 bool global_default)
1217 {
1218 bool original;
1219
1220 if (tileset_name == NULL
1221 || !(tileset = tileset_read_toplevel(tileset_name, verbose,
1222 topo_id, 1.0f))) {
1223 struct strvec *list = fileinfolist(get_data_dirs(), TILESPEC_SUFFIX);
1224
1225 original = FALSE;
1226 strvec_iterate(list, file) {
1227 struct tileset *t = tileset_read_toplevel(file, FALSE, topo_id, 1.0f);
1228
1229 if (t) {
1230 if (!tileset) {
1231 tileset = t;
1232 } else if (t->priority > tileset->priority
1233 || (topo_id >= 0
1234 && tileset_topo_index(tileset) != tileset_topo_index(t))) {
1235 tileset_free(tileset);
1236 tileset = t;
1237 } else {
1238 tileset_free(t);
1239 }
1240 }
1241 } strvec_iterate_end;
1242 strvec_destroy(list);
1243
1244 if (!tileset) {
1245 tileset_error(LOG_FATAL, _("No usable default tileset found, aborting!"));
1246 }
1247
1248 log_verbose("Trying tileset \"%s\".", tileset->name);
1249 } else {
1250 original = TRUE;
1251 }
1252 option_set_default_ts(tileset);
1253
1254 if (global_default) {
1255 sz_strlcpy(gui_options.default_tileset_name, tileset_basename(tileset));
1256 }
1257
1258 return original;
1259 }
1260
1261 /**********************************************************************
1262 Read a new tilespec in from scratch.
1263
1264 Unlike the initial reading code, which reads pieces one at a time,
1265 this gets rid of the old data and reads in the new all at once. If the
1266 new tileset fails to load the old tileset may be reloaded; otherwise the
1267 client will exit. If a NULL name is given the current tileset will be
1268 reread.
1269
1270 It will also call the necessary functions to redraw the graphics.
1271
1272 Returns TRUE iff new tileset has been succesfully loaded.
1273 ***********************************************************************/
tilespec_reread(const char * new_tileset_name,bool game_fully_initialized,float scale)1274 bool tilespec_reread(const char *new_tileset_name,
1275 bool game_fully_initialized, float scale)
1276 {
1277 int id;
1278 struct tile *center_tile;
1279 enum client_states state = client_state();
1280 const char *name = new_tileset_name ? new_tileset_name : tileset->name;
1281 char tileset_name[strlen(name) + 1], old_name[strlen(tileset->name) + 1];
1282 bool new_tileset_in_use;
1283 int ts_topo;
1284
1285 /* Make local copies since these values may be freed down below */
1286 sz_strlcpy(tileset_name, name);
1287 sz_strlcpy(old_name, tileset->name);
1288
1289 log_normal(_("Loading tileset \"%s\"."), tileset_name);
1290
1291 /* Step 0: Record old data.
1292 *
1293 * We record the current mapcanvas center, etc.
1294 */
1295 center_tile = get_center_tile_mapcanvas();
1296
1297 /* Step 1: Cleanup.
1298 *
1299 * Free old tileset or keep it in memeory if we are loading the same
1300 * tileset with scaling and old one was not scaled.
1301 */
1302
1303 if (strcmp(tileset_name, old_name) == 0 && tileset->scale == 1.0f
1304 && scale != 1.0f) {
1305 if (unscaled_tileset) {
1306 tileset_free(unscaled_tileset);
1307 }
1308 unscaled_tileset = tileset;
1309 } else {
1310 tileset_free(tileset);
1311 }
1312
1313 /* Step 2: Read.
1314 *
1315 * We read in the new tileset. This should be pretty straightforward.
1316 */
1317 tileset = tileset_read_toplevel(tileset_name, FALSE, -1, scale);
1318 if (tileset != NULL) {
1319 new_tileset_in_use = TRUE;
1320 } else {
1321 new_tileset_in_use = FALSE;
1322
1323 if (!(tileset = tileset_read_toplevel(old_name, FALSE, -1, scale))) {
1324 /* Always fails. */
1325 fc_assert_exit_msg(NULL != tileset,
1326 "Failed to re-read the currently loaded tileset.");
1327 }
1328 }
1329 tileset_load_tiles(tileset);
1330 if (game_fully_initialized) {
1331 tileset_use_preferred_theme(tileset);
1332 }
1333
1334 if (game_fully_initialized) {
1335 if (game.client.ruleset_ready) {
1336 tileset_background_init(tileset);
1337 } /* else we'll get round to it on PACKET_RULESET_GAME */
1338 players_iterate(pplayer) {
1339 tileset_player_init(tileset, pplayer);
1340 } players_iterate_end;
1341 boot_help_texts(); /* "About Current Tileset" */
1342 }
1343
1344 /* Step 3: Setup
1345 *
1346 * This is a seriously sticky problem. On startup, we build a hash
1347 * from all the sprite data. Then, when we connect to a server, the
1348 * server sends us ruleset data a piece at a time and we use this data
1349 * to assemble the sprite structures. But if we change while connected
1350 * we have to reassemble all of these. This should just involve
1351 * calling tilespec_setup_*** on everything. But how do we tell what
1352 * "everything" is?
1353 *
1354 * The below code just does things straightforwardly, by setting up
1355 * each possible sprite again. Hopefully it catches everything, and
1356 * doesn't mess up too badly if we change tilesets while not connected
1357 * to a server.
1358 */
1359 if (!game.client.ruleset_ready) {
1360 /* The ruleset data is not sent until this point. */
1361 return new_tileset_in_use;
1362 }
1363
1364 if (tileset_map_topo_compatible(game.map.topology_id, tileset, &ts_topo)
1365 == TOPO_INCOMP_HARD) {
1366 tileset_error(LOG_NORMAL, _("Map topology (%s) and tileset (%s) incompatible."),
1367 describe_topology(game.map.topology_id), describe_topology(ts_topo));
1368 }
1369
1370 terrain_type_iterate(pterrain) {
1371 tileset_setup_tile_type(tileset, pterrain);
1372 } terrain_type_iterate_end;
1373 resource_type_iterate(presource) {
1374 tileset_setup_resource(tileset, presource);
1375 } resource_type_iterate_end;
1376 unit_type_iterate(punittype) {
1377 tileset_setup_unit_type(tileset, punittype);
1378 } unit_type_iterate_end;
1379 governments_iterate(gov) {
1380 tileset_setup_government(tileset, gov);
1381 } governments_iterate_end;
1382 extra_type_iterate(pextra) {
1383 tileset_setup_extra(tileset, pextra);
1384 } extra_type_iterate_end;
1385 nations_iterate(pnation) {
1386 tileset_setup_nation_flag(tileset, pnation);
1387 } nations_iterate_end;
1388 improvement_iterate(pimprove) {
1389 tileset_setup_impr_type(tileset, pimprove);
1390 } improvement_iterate_end;
1391 advance_iterate(A_FIRST, padvance) {
1392 tileset_setup_tech_type(tileset, padvance);
1393 } advance_iterate_end;
1394 specialist_type_iterate(sp) {
1395 tileset_setup_specialist_type(tileset, sp);
1396 } specialist_type_iterate_end;
1397
1398 for (id = 0; id < game.control.styles_count; id++) {
1399 tileset_setup_city_tiles(tileset, id);
1400 }
1401
1402 if (state < C_S_RUNNING) {
1403 /* Below redraws do not apply before this. */
1404 return new_tileset_in_use;
1405 }
1406
1407 /* Step 4: Draw.
1408 *
1409 * Do any necessary redraws.
1410 */
1411 generate_citydlg_dimensions();
1412 tileset_changed();
1413 can_slide = FALSE;
1414 center_tile_mapcanvas(center_tile);
1415 /* update_map_canvas_visible forces a full redraw. Otherwise with fast
1416 * drawing we might not get one. Of course this is slower. */
1417 update_map_canvas_visible();
1418 can_slide = TRUE;
1419
1420 return new_tileset_in_use;
1421 }
1422
1423 /**************************************************************************
1424 This is merely a wrapper for tilespec_reread (above) for use in
1425 options.c and the client local options dialog.
1426 **************************************************************************/
tilespec_reread_callback(struct option * poption)1427 void tilespec_reread_callback(struct option *poption)
1428 {
1429 const char *tileset_name;
1430 enum client_states state = client_state();
1431
1432 if ((state == C_S_RUNNING || state == C_S_OVER)
1433 && option_get_cb_data(poption) != (game.map.topology_id & (TF_ISO | TF_HEX))) {
1434 /* Changed option was not for current topology */
1435 return;
1436 }
1437
1438 tileset_name = option_str_get(poption);
1439
1440 /* As it's going to be 'current' tileset, make it global default if
1441 * options saved. */
1442 sz_strlcpy(gui_options.default_tileset_name, tileset_name);
1443
1444 fc_assert_ret(NULL != tileset_name && tileset_name[0] != '\0');
1445 tileset_update = TRUE;
1446 tilespec_reread(tileset_name, client.conn.established, 1.0f);
1447 tileset_update = FALSE;
1448 menus_init();
1449 }
1450
1451 /**************************************************************************
1452 Read a new tilespec in from scratch. Keep UI frozen while tileset is
1453 partially loaded; in inconsistent state.
1454
1455 See tilespec_reread() for details.
1456 **************************************************************************/
tilespec_reread_frozen_refresh(const char * tname)1457 void tilespec_reread_frozen_refresh(const char *tname)
1458 {
1459 tileset_update = TRUE;
1460 tilespec_reread(tname, TRUE, 1.0f);
1461 tileset_update = FALSE;
1462 menus_init();
1463 }
1464
1465 /**************************************************************************
1466 Loads the given graphics file (found in the data path) into a newly
1467 allocated sprite.
1468 **************************************************************************/
load_gfx_file(const char * gfx_filename)1469 static struct sprite *load_gfx_file(const char *gfx_filename)
1470 {
1471 const char **gfx_fileexts = gfx_fileextensions(), *gfx_fileext;
1472 struct sprite *s;
1473
1474 /* Try out all supported file extensions to find one that works. */
1475 while ((gfx_fileext = *gfx_fileexts++)) {
1476 const char *real_full_name;
1477 char full_name[strlen(gfx_filename) + strlen(".")
1478 + strlen(gfx_fileext) + 1];
1479
1480 sprintf(full_name, "%s.%s", gfx_filename, gfx_fileext);
1481 if ((real_full_name = fileinfoname(get_data_dirs(), full_name))) {
1482 log_debug("trying to load gfx file \"%s\".", real_full_name);
1483 s = load_gfxfile(real_full_name);
1484 if (s) {
1485 return s;
1486 }
1487 }
1488 }
1489
1490 log_error("Could not load gfx file \"%s\".", gfx_filename);
1491 return NULL;
1492 }
1493
1494 /**************************************************************************
1495 Ensure that the big sprite of the given spec file is loaded.
1496 **************************************************************************/
ensure_big_sprite(struct specfile * sf)1497 static void ensure_big_sprite(struct specfile *sf)
1498 {
1499 struct section_file *file;
1500 const char *gfx_filename;
1501
1502 if (sf->big_sprite) {
1503 /* Looks like it's already loaded. */
1504 return;
1505 }
1506
1507 /* Otherwise load it. The big sprite will sometimes be freed and will have
1508 * to be reloaded, but most of the time it's just loaded once, the small
1509 * sprites are extracted, and then it's freed. */
1510 if (!(file = secfile_load(sf->file_name, TRUE))) {
1511 tileset_error(LOG_FATAL, _("Could not open '%s':\n%s"), sf->file_name, secfile_error());
1512 }
1513
1514 if (!check_tilespec_capabilities(file, "spec",
1515 SPEC_CAPSTR, sf->file_name, TRUE)) {
1516 tileset_error(LOG_FATAL, _("Incompatible tileset capabilities"));
1517 }
1518
1519 gfx_filename = secfile_lookup_str(file, "file.gfx");
1520
1521 sf->big_sprite = load_gfx_file(gfx_filename);
1522
1523 if (!sf->big_sprite) {
1524 tileset_error(LOG_FATAL, _("Could not load gfx file for the spec file \"%s\"."),
1525 sf->file_name);
1526 }
1527 secfile_destroy(file);
1528 }
1529
1530 /**************************************************************************
1531 Scan all sprites declared in the given specfile. This means that the
1532 positions of the sprites in the big_sprite are saved in the
1533 small_sprite structs.
1534 **************************************************************************/
scan_specfile(struct tileset * t,struct specfile * sf,bool duplicates_ok)1535 static void scan_specfile(struct tileset *t, struct specfile *sf,
1536 bool duplicates_ok)
1537 {
1538 struct section_file *file;
1539 struct section_list *sections;
1540 int i;
1541
1542 if (!(file = secfile_load(sf->file_name, TRUE))) {
1543 tileset_error(LOG_FATAL, _("Could not open '%s':\n%s"), sf->file_name, secfile_error());
1544 }
1545 if (!check_tilespec_capabilities(file, "spec",
1546 SPEC_CAPSTR, sf->file_name, TRUE)) {
1547 tileset_error(LOG_FATAL, _("Specfile %s has incompatible capabilities"), sf->file_name);
1548 }
1549
1550 /* Currently unused */
1551 (void) secfile_entry_lookup(file, "info.artists");
1552
1553 /* Not used here */
1554 (void) secfile_entry_lookup(file, "file.gfx");
1555
1556 if ((sections = secfile_sections_by_name_prefix(file, "grid_"))) {
1557 section_list_iterate(sections, psection) {
1558 int j, k;
1559 int x_top_left, y_top_left, dx, dy;
1560 int pixel_border_x;
1561 int pixel_border_y;
1562 const char *sec_name = section_name(psection);
1563
1564 pixel_border_x = secfile_lookup_int_default(file, 0, "%s.pixel_border",
1565 sec_name);
1566 pixel_border_y = secfile_lookup_int_default(file, pixel_border_x, "%s.pixel_border_y",
1567 sec_name);
1568 pixel_border_x = secfile_lookup_int_default(file, pixel_border_x, "%s.pixel_border_x",
1569 sec_name);
1570 if (!secfile_lookup_int(file, &x_top_left, "%s.x_top_left", sec_name)
1571 || !secfile_lookup_int(file, &y_top_left,
1572 "%s.y_top_left", sec_name)
1573 || !secfile_lookup_int(file, &dx, "%s.dx", sec_name)
1574 || !secfile_lookup_int(file, &dy, "%s.dy", sec_name)) {
1575 log_error("%s grid \"%s\" invalid: %s",
1576 sf->file_name, sec_name, secfile_error());
1577 continue;
1578 }
1579
1580 j = -1;
1581 while (NULL != secfile_entry_lookup(file, "%s.tiles%d.tag",
1582 sec_name, ++j)) {
1583 struct small_sprite *ss;
1584 int row, column;
1585 int xr, yb;
1586 const char **tags;
1587 size_t num_tags;
1588 int hot_x, hot_y;
1589
1590 if (!secfile_lookup_int(file, &row, "%s.tiles%d.row", sec_name, j)
1591 || !secfile_lookup_int(file, &column, "%s.tiles%d.column",
1592 sec_name, j)
1593 || !(tags = secfile_lookup_str_vec(file, &num_tags,
1594 "%s.tiles%d.tag",
1595 sec_name, j))) {
1596 log_error("%s small sprite \"%s.tiles%d\" invalid: %s",
1597 sf->file_name, sec_name, j, secfile_error());
1598 continue;
1599 }
1600 hot_x = secfile_lookup_int_default(file, 0, "%s.tiles%d.hot_x",
1601 sec_name, j);
1602 hot_y = secfile_lookup_int_default(file, 0, "%s.tiles%d.hot_y",
1603 sec_name, j);
1604
1605 /* there must be at least 1 because of the while(): */
1606 fc_assert_action(num_tags > 0, continue);
1607
1608 xr = x_top_left + (dx + pixel_border_x) * column;
1609 yb = y_top_left + (dy + pixel_border_y) * row;
1610
1611 ss = fc_malloc(sizeof(*ss));
1612 ss->ref_count = 0;
1613 ss->file = NULL;
1614 ss->x = xr;
1615 ss->y = yb;
1616 ss->width = dx;
1617 ss->height = dy;
1618 ss->sf = sf;
1619 ss->sprite = NULL;
1620 ss->hot_x = hot_x;
1621 ss->hot_y = hot_y;
1622
1623 small_sprite_list_prepend(t->small_sprites, ss);
1624
1625 if (!duplicates_ok) {
1626 for (k = 0; k < num_tags; k++) {
1627 if (!sprite_hash_insert(t->sprite_hash, tags[k], ss)) {
1628 log_error("warning: %s already has a sprite for \"%s\".",
1629 tileset_name_get(t), tags[k]);
1630 }
1631 }
1632 } else {
1633 for (k = 0; k < num_tags; k++) {
1634 (void) sprite_hash_replace(t->sprite_hash, tags[k], ss);
1635 }
1636 }
1637
1638 free(tags);
1639 tags = NULL;
1640 }
1641 } section_list_iterate_end;
1642 section_list_destroy(sections);
1643 }
1644
1645 /* Load "extra" sprites. Each sprite is one file. */
1646 i = -1;
1647 while (NULL != secfile_entry_lookup(file, "extra.sprites%d.tag", ++i)) {
1648 struct small_sprite *ss;
1649 const char **tags;
1650 const char *filename;
1651 size_t num_tags, k;
1652 int hot_x, hot_y;
1653
1654 if (!(tags = secfile_lookup_str_vec(file, &num_tags,
1655 "extra.sprites%d.tag", i))
1656 || !(filename = secfile_lookup_str(file,
1657 "extra.sprites%d.file", i))) {
1658 log_error("%s extra sprite \"extra.sprites%d\" invalid: %s",
1659 sf->file_name, i, secfile_error());
1660 continue;
1661 }
1662 hot_x = secfile_lookup_int_default(file, 0, "extra.sprites%d.hot_x", i);
1663 hot_y = secfile_lookup_int_default(file, 0, "extra.sprites%d.hot_y", i);
1664
1665 ss = fc_malloc(sizeof(*ss));
1666 ss->ref_count = 0;
1667 ss->file = fc_strdup(filename);
1668 ss->sf = NULL;
1669 ss->sprite = NULL;
1670 ss->hot_x = hot_x;
1671 ss->hot_y = hot_y;
1672
1673 small_sprite_list_prepend(t->small_sprites, ss);
1674
1675 if (!duplicates_ok) {
1676 for (k = 0; k < num_tags; k++) {
1677 if (!sprite_hash_insert(t->sprite_hash, tags[k], ss)) {
1678 log_error("warning: %s already have a sprite for \"%s\".",
1679 tileset_name_get(t), tags[k]);
1680 }
1681 }
1682 } else {
1683 for (k = 0; k < num_tags; k++) {
1684 (void) sprite_hash_replace(t->sprite_hash, tags[k], ss);
1685 }
1686 }
1687 free(tags);
1688 }
1689
1690 secfile_check_unused(file);
1691 secfile_destroy(file);
1692 }
1693
1694 /**********************************************************************
1695 Returns the correct name of the gfx file (with path and extension)
1696 Must be free'd when no longer used
1697 ***********************************************************************/
tilespec_gfx_filename(const char * gfx_filename)1698 static char *tilespec_gfx_filename(const char *gfx_filename)
1699 {
1700 const char *gfx_current_fileext;
1701 const char **gfx_fileexts = gfx_fileextensions();
1702
1703 while ((gfx_current_fileext = *gfx_fileexts++)) {
1704 const char *real_full_name;
1705 char *full_name =
1706 fc_malloc(strlen(gfx_filename) + strlen(".")
1707 + strlen(gfx_current_fileext) + 1);
1708
1709 sprintf(full_name, "%s.%s", gfx_filename, gfx_current_fileext);
1710
1711 real_full_name = fileinfoname(get_data_dirs(), full_name);
1712 free(full_name);
1713 if (real_full_name) {
1714 return fc_strdup(real_full_name);
1715 }
1716 }
1717
1718 tileset_error(LOG_FATAL, _("Couldn't find a supported gfx file extension for \"%s\"."),
1719 gfx_filename);
1720
1721 return NULL;
1722 }
1723
1724 /**********************************************************************
1725 Determine the sprite_type string.
1726 ***********************************************************************/
check_sprite_type(const char * sprite_type,const char * tile_section)1727 static int check_sprite_type(const char *sprite_type, const char *tile_section)
1728 {
1729 if (fc_strcasecmp(sprite_type, "corner") == 0) {
1730 return CELL_CORNER;
1731 }
1732 if (fc_strcasecmp(sprite_type, "single") == 0) {
1733 return CELL_WHOLE;
1734 }
1735 if (fc_strcasecmp(sprite_type, "whole") == 0) {
1736 return CELL_WHOLE;
1737 }
1738 log_error("[%s] unknown sprite_type \"%s\".", tile_section, sprite_type);
1739 return CELL_WHOLE;
1740 }
1741
1742 /**********************************************************************
1743 Finds and reads the toplevel tilespec file based on given name.
1744 Sets global variables, including tile sizes and full names for
1745 intro files.
1746 topology_id of -1 means any topology is acceptable.
1747 ***********************************************************************/
tileset_read_toplevel(const char * tileset_name,bool verbose,int topology_id,float scale)1748 struct tileset *tileset_read_toplevel(const char *tileset_name, bool verbose,
1749 int topology_id, float scale)
1750 {
1751 struct section_file *file;
1752 char *fname;
1753 const char *c;
1754 int i;
1755 size_t num_spec_files;
1756 const char **spec_filenames;
1757 size_t num_preferred_themes;
1758 struct section_list *sections = NULL;
1759 const char *file_capstr;
1760 bool duplicates_ok, is_hex;
1761 enum direction8 dir;
1762 struct tileset *t = NULL;
1763 const char *extraname;
1764 const char *tstr;
1765 int topo;
1766
1767 fname = tilespec_fullname(tileset_name);
1768 if (!fname) {
1769 if (verbose) {
1770 log_error("Can't find tileset \"%s\".", tileset_name);
1771 }
1772 return NULL;
1773 }
1774 log_verbose("tilespec file is \"%s\".", fname);
1775
1776 if (!(file = secfile_load(fname, TRUE))) {
1777 log_error("Could not open '%s':\n%s", fname, secfile_error());
1778 free(fname);
1779 return NULL;
1780 }
1781
1782 if (!check_tilespec_capabilities(file, "tilespec",
1783 TILESPEC_CAPSTR, fname, verbose)) {
1784 secfile_destroy(file);
1785 free(fname);
1786 return NULL;
1787 }
1788
1789 t = tileset_new();
1790 t->scale = scale;
1791 file_capstr = secfile_lookup_str(file, "%s.options", "tilespec");
1792 duplicates_ok = (NULL != file_capstr
1793 && has_capabilities("+duplicates_ok", file_capstr));
1794
1795 tstr = secfile_lookup_str(file, "tilespec.name");
1796 /* Tileset name found */
1797 sz_strlcpy(t->given_name, tstr);
1798 tstr = secfile_lookup_str_default(file, "", "tilespec.version");
1799 if (tstr[0] != '\0') {
1800 /* Tileset version found */
1801 sz_strlcpy(t->version, tstr);
1802 } else {
1803 /* No version information */
1804 t->version[0] = '\0';
1805 }
1806
1807 tstr = secfile_lookup_str_default(file, "", "tilespec.summary");
1808 if (tstr[0] != '\0') {
1809 int len;
1810
1811 /* Tileset summary found */
1812 len = strlen(tstr);
1813 t->summary = fc_malloc(len + 1);
1814 fc_strlcpy(t->summary, tstr, len + 1);
1815 } else {
1816 /* No summary */
1817 if (t->summary != NULL) {
1818 free(t->summary);
1819 t->summary = NULL;
1820 }
1821 }
1822
1823 tstr = secfile_lookup_str_default(file, "", "tilespec.description");
1824 if (tstr[0] != '\0') {
1825 int len;
1826
1827 /* Tileset description found */
1828 len = strlen(tstr);
1829 t->description = fc_malloc(len + 1);
1830 fc_strlcpy(t->description, tstr, len + 1);
1831 } else {
1832 /* No description */
1833 if (t->description != NULL) {
1834 free(t->description);
1835 t->description = NULL;
1836 }
1837 }
1838
1839 sz_strlcpy(t->name, tileset_name);
1840 if (!secfile_lookup_int(file, &t->priority, "tilespec.priority")
1841 || !secfile_lookup_bool(file, &is_hex, "tilespec.is_hex")) {
1842 log_error("Tileset \"%s\" invalid: %s", t->name, secfile_error());
1843 goto ON_ERROR;
1844 }
1845
1846 tstr = secfile_lookup_str(file, "tilespec.type");
1847 if (tstr == NULL) {
1848 log_error("Tileset \"%s\": no tileset type", t->name);
1849 goto ON_ERROR;
1850 }
1851
1852 t->type = ts_type_by_name(tstr, fc_strcasecmp);
1853 if (!ts_type_is_valid(t->type)) {
1854 log_error("Tileset \"%s\": unknown tileset type \"%s\"", t->name, tstr);
1855 goto ON_ERROR;
1856 }
1857
1858 if (t->type == TS_ISOMETRIC) {
1859 topo = TF_ISO;
1860 } else {
1861 topo = 0;
1862 }
1863
1864 /* Read hex-tileset information. */
1865 t->hex_width = t->hex_height = 0;
1866 if (is_hex) {
1867 int hex_side;
1868
1869 if (!secfile_lookup_int(file, &hex_side, "tilespec.hex_side")) {
1870 log_error("Tileset \"%s\" invalid: %s", t->name, secfile_error());
1871 goto ON_ERROR;
1872 }
1873 hex_side = hex_side * t->scale;
1874 if (t->type == TS_ISOMETRIC) {
1875 t->hex_width = hex_side;
1876 } else {
1877 t->hex_height = hex_side;
1878 }
1879
1880 topo |= TF_HEX;
1881
1882 /* Hex tilesets are drawn the same as isometric. */
1883 /* FIXME: There will be other legal values to be used with hex
1884 * tileset in the future, and this would just overwrite it. */
1885 t->type = TS_ISOMETRIC;
1886 }
1887
1888 if (topology_id >= 0 && topo != (topology_id & (TF_ISO | TF_HEX))) {
1889 /* Not of requested topology */
1890 goto ON_ERROR;
1891 }
1892
1893 t->ts_topo_idx = ts_topology_index(topo);
1894
1895 if (!is_view_supported(t->type)) {
1896 /* TRANS: "Overhead" or "Isometric" */
1897 log_normal(_("Client does not support %s tilesets."),
1898 _(ts_type_name(t->type)));
1899 log_normal(_("Using default tileset instead."));
1900 fc_assert(tileset_name != NULL);
1901 goto ON_ERROR;
1902 }
1903
1904 /* Create arrays of valid and cardinal tileset dirs. These depend
1905 * entirely on the tileset, not the topology. They are also in clockwise
1906 * rotational ordering. */
1907 t->num_valid_tileset_dirs = t->num_cardinal_tileset_dirs = 0;
1908 dir = DIR8_NORTH;
1909 do {
1910 if (is_valid_tileset_dir(t, dir)) {
1911 t->valid_tileset_dirs[t->num_valid_tileset_dirs] = dir;
1912 t->num_valid_tileset_dirs++;
1913 }
1914 if (is_cardinal_tileset_dir(t, dir)) {
1915 t->cardinal_tileset_dirs[t->num_cardinal_tileset_dirs] = dir;
1916 t->num_cardinal_tileset_dirs++;
1917 }
1918
1919 dir = dir_cw(dir);
1920 } while (dir != DIR8_NORTH);
1921 fc_assert(t->num_valid_tileset_dirs % 2 == 0); /* Assumed elsewhere. */
1922 t->num_index_valid = 1 << t->num_valid_tileset_dirs;
1923 t->num_index_cardinal = 1 << t->num_cardinal_tileset_dirs;
1924
1925 if (!secfile_lookup_int(file, &t->normal_tile_width,
1926 "tilespec.normal_tile_width")
1927 || !secfile_lookup_int(file, &t->normal_tile_height,
1928 "tilespec.normal_tile_height")) {
1929 log_error("Tileset \"%s\" invalid: %s", t->name, secfile_error());
1930 goto ON_ERROR;
1931 }
1932 t->normal_tile_width = ceil(t->scale * t->normal_tile_width);
1933 // Adjust width to be multiple of 8
1934 if (scale != 1.0f) {
1935 i = t->normal_tile_width;
1936 while (i % 8 != 0) {
1937 i++;
1938 }
1939 t->scale = (t->scale * i) / t->normal_tile_width;
1940 t->normal_tile_width = i;
1941 }
1942 t->normal_tile_height = ceil(t->scale * t->normal_tile_height);
1943 if (t->type == TS_ISOMETRIC) {
1944 t->full_tile_width = t->normal_tile_width;
1945 if (tileset_hex_height(t) > 0) {
1946 t->full_tile_height = t->normal_tile_height;
1947 } else {
1948 t->full_tile_height = 3 * t->normal_tile_height / 2;
1949 }
1950 } else {
1951 t->full_tile_width = t->normal_tile_width;
1952 t->full_tile_height = t->normal_tile_height;
1953 }
1954 t->unit_tile_width
1955 = secfile_lookup_int_default(file, t->full_tile_width, "tilespec.unit_width");
1956 t->unit_tile_height
1957 = secfile_lookup_int_default(file, t->full_tile_height, "tilespec.unit_height");
1958 if (!secfile_lookup_int(file, &t->small_sprite_width,
1959 "tilespec.small_tile_width")
1960 || !secfile_lookup_int(file, &t->small_sprite_height,
1961 "tilespec.small_tile_height")) {
1962 log_error("Tileset \"%s\" invalid: %s", t->name, secfile_error());
1963 goto ON_ERROR;
1964 }
1965 if (t->unit_tile_width != t->full_tile_width && t->scale != 1.0f) {
1966 t->unit_tile_width = ceil(t->unit_tile_width * t->scale);
1967 }
1968 if (t->unit_tile_height != t->full_tile_height && t->scale != 1.0f) {
1969 t->unit_tile_height = ceil(t->unit_tile_height * t->scale);
1970 }
1971 t->small_sprite_width = t->small_sprite_width * t->scale;
1972 t->small_sprite_height = t->small_sprite_height * t->scale;
1973 log_verbose("tile sizes %dx%d, %d%d unit, %d%d small",
1974 t->normal_tile_width, t->normal_tile_height,
1975 t->full_tile_width, t->full_tile_height,
1976 t->small_sprite_width, t->small_sprite_height);
1977
1978 tstr = secfile_lookup_str(file, "tilespec.fog_style");
1979 if (tstr == NULL) {
1980 log_error("Tileset \"%s\": no fog_style", t->name);
1981 goto ON_ERROR;
1982 }
1983
1984 t->fogstyle = fog_style_by_name(tstr, fc_strcasecmp);
1985 if (!fog_style_is_valid(t->fogstyle)) {
1986 log_error("Tileset \"%s\": unknown fog_style \"%s\"", t->name, tstr);
1987 goto ON_ERROR;
1988 }
1989
1990 tstr = secfile_lookup_str(file, "tilespec.darkness_style");
1991 if (tstr == NULL) {
1992 log_error("Tileset \"%s\": no darkness_style", t->name);
1993 goto ON_ERROR;
1994 }
1995
1996 t->darkness_style = darkness_style_by_name(tstr, fc_strcasecmp);
1997 if (!darkness_style_is_valid(t->darkness_style)) {
1998 log_error("Tileset \"%s\": unknown darkness_style \"%s\"", t->name, tstr);
1999 goto ON_ERROR;
2000 }
2001
2002 if (t->darkness_style == DARKNESS_ISORECT
2003 && (t->type == TS_OVERHEAD || t->hex_width > 0 || t->hex_height > 0)) {
2004 log_error("Invalid darkness style set in tileset \"%s\".", t->name);
2005 goto ON_ERROR;
2006 }
2007 t->darkness_layer = secfile_lookup_int_default(file, 0, "tilespec.darkness_layer");
2008 if (t->darkness_layer < 0 || t->darkness_layer >= TERRAIN_LAYER_COUNT) {
2009 tileset_error(LOG_ERROR, "Invalid darkness layer %d in tileset \"%s\"",
2010 t->darkness_layer, t->name);
2011 goto ON_ERROR;
2012 }
2013
2014 if (!secfile_lookup_int(file, &t->unit_flag_offset_x,
2015 "tilespec.unit_flag_offset_x")
2016 || !secfile_lookup_int(file, &t->unit_flag_offset_y,
2017 "tilespec.unit_flag_offset_y")
2018 || !secfile_lookup_int(file, &t->city_flag_offset_x,
2019 "tilespec.city_flag_offset_x")
2020 || !secfile_lookup_int(file, &t->city_flag_offset_y,
2021 "tilespec.city_flag_offset_y")
2022 || !secfile_lookup_int(file, &t->unit_offset_x,
2023 "tilespec.unit_offset_x")
2024 || !secfile_lookup_int(file, &t->unit_offset_y,
2025 "tilespec.unit_offset_y")
2026 || !secfile_lookup_int(file, &t->activity_offset_x,
2027 "tilespec.activity_offset_x")
2028 || !secfile_lookup_int(file, &t->activity_offset_y,
2029 "tilespec.activity_offset_y")
2030 || !secfile_lookup_int(file, &t->city_offset_x,
2031 "tilespec.city_offset_x")
2032 || !secfile_lookup_int(file, &t->city_offset_y,
2033 "tilespec.city_offset_y")
2034 || !secfile_lookup_int(file, &t->citybar_offset_y,
2035 "tilespec.citybar_offset_y")
2036 || !secfile_lookup_int(file, &t->tilelabel_offset_y,
2037 "tilespec.tilelabel_offset_y")
2038 || !secfile_lookup_int(file, &t->occupied_offset_x,
2039 "tilespec.occupied_offset_x")
2040 || !secfile_lookup_int(file, &t->occupied_offset_y,
2041 "tilespec.occupied_offset_y")
2042 || !secfile_lookup_int(file, &t->city_names_font_size,
2043 "tilespec.city_names_font_size")
2044 || !secfile_lookup_int(file, &t->city_productions_font_size,
2045 "tilespec.city_productions_font_size")) {
2046 log_error("Tileset \"%s\" invalid: %s", t->name, secfile_error());
2047 goto ON_ERROR;
2048 }
2049
2050 t->unit_upkeep_offset_y = secfile_lookup_int_default(file, tileset_tile_height(t),
2051 "tilespec.unit_upkeep_offset_y");
2052 t->unit_upkeep_small_offset_y = secfile_lookup_int_default(file, t->unit_upkeep_offset_y,
2053 "tilespec.unit_upkeep_small_offset_y");
2054 t->unit_flag_offset_x = t->scale * t->unit_flag_offset_x;
2055 t->unit_flag_offset_y = t->scale * t->unit_flag_offset_y;
2056 t->city_flag_offset_x = t->scale * t->city_flag_offset_x;
2057 t->city_flag_offset_y = t->scale * t->city_flag_offset_y;
2058 t->unit_offset_x = t->scale * t->unit_offset_x;
2059 t->unit_offset_y = t->scale * t->unit_offset_y;
2060 t->activity_offset_x = t->scale * t->activity_offset_x;
2061 t->activity_offset_y = t->scale * t->activity_offset_y;
2062 t->city_offset_x = t->scale * t->city_offset_x;
2063 t->city_offset_y = t->scale * t->city_offset_y;
2064 t->citybar_offset_y = t->scale * t->citybar_offset_y;
2065 t->tilelabel_offset_y = t->scale * t->tilelabel_offset_y;
2066 t->occupied_offset_x = t->scale * t->occupied_offset_x;
2067 t->occupied_offset_y = t->scale * t->occupied_offset_y;
2068 if (t->scale != 1.0f
2069 && t->unit_upkeep_offset_y != tileset_tile_height(t)) {
2070 t->unit_upkeep_offset_y = t->scale * t->unit_upkeep_offset_y;
2071 }
2072 if (t->scale != 1.0f
2073 && t->unit_upkeep_small_offset_y != t->unit_upkeep_offset_y) {
2074 t->unit_upkeep_small_offset_y = t->scale * t->unit_upkeep_small_offset_y;
2075 }
2076 /* Tell client, although many clients ignore this in favour of their
2077 * own configuration */
2078 set_city_names_font_sizes(t->city_names_font_size,
2079 t->city_productions_font_size);
2080
2081 c = secfile_lookup_str(file, "tilespec.main_intro_file");
2082 t->main_intro_filename = tilespec_gfx_filename(c);
2083 log_debug("intro file %s", t->main_intro_filename);
2084
2085 c = secfile_lookup_str_default(file, NULL, "tilespec.minimap_intro_file");
2086 if (c == NULL) {
2087 t->minimap_intro_filename = NULL;
2088 } else {
2089 t->minimap_intro_filename = tilespec_gfx_filename(c);
2090 log_debug("radar file %s", t->minimap_intro_filename);
2091 }
2092
2093 /* Terrain layer info. */
2094 for (i = 0; i < MAX_NUM_LAYERS; i++) {
2095 struct tileset_layer *tslp = &t->layers[i];
2096 int j, k;
2097
2098 tslp->match_types =
2099 (char **) secfile_lookup_str_vec(file, &tslp->match_count,
2100 "layer%d.match_types", i);
2101 for (j = 0; j < tslp->match_count; j++) {
2102 tslp->match_types[j] = fc_strdup(tslp->match_types[j]);
2103
2104 for (k = 0; k < j; k++) {
2105 if (tslp->match_types[k][0] == tslp->match_types[j][0]) {
2106 tileset_error(LOG_FATAL, _("[layer%d] match_types: \"%s\" initial "
2107 "('%c') is not unique."),
2108 i, tslp->match_types[j], tslp->match_types[j][0]);
2109 /* FIXME: Returns NULL. */
2110 }
2111 }
2112 }
2113 }
2114
2115 /* Tile drawing info. */
2116 sections = secfile_sections_by_name_prefix(file, TILE_SECTION_PREFIX);
2117 if (NULL == sections || 0 == section_list_size(sections)) {
2118 tileset_error(LOG_ERROR, _("No [%s] sections supported by tileset \"%s\"."),
2119 TILE_SECTION_PREFIX, fname);
2120 goto ON_ERROR;
2121 }
2122
2123 fc_assert(t->tile_hash == NULL);
2124 t->tile_hash = drawing_hash_new();
2125
2126 section_list_iterate(sections, psection) {
2127 const char *sec_name = section_name(psection);
2128 struct drawing_data *draw = drawing_data_new();
2129 const char *sprite_type;
2130 int l;
2131 const char *terrain_name;
2132
2133 terrain_name = secfile_lookup_str(file, "%s.tag", sec_name);
2134
2135 if (terrain_name != NULL) {
2136 draw->name = fc_strdup(terrain_name);
2137 } else {
2138 tileset_error(LOG_ERROR, _("No terrain tag given in section [%s]."), sec_name);
2139 drawing_data_destroy(draw);
2140 goto ON_ERROR;
2141 }
2142
2143 draw->blending = secfile_lookup_int_default(file, 0, "%s.blend_layer",
2144 sec_name);
2145 draw->blending = CLIP(0, draw->blending, MAX_NUM_LAYERS);
2146
2147 draw->is_reversed = secfile_lookup_bool_default(file, FALSE,
2148 "%s.is_reversed",
2149 sec_name);
2150 draw->num_layers = secfile_lookup_int_default(file, 0, "%s.num_layers",
2151 sec_name);
2152 draw->num_layers = CLIP(1, draw->num_layers, MAX_NUM_LAYERS);
2153
2154 for (l = 0; l < draw->num_layers; l++) {
2155 struct drawing_layer *dlp = &draw->layer[l];
2156 struct tileset_layer *tslp = &t->layers[l];
2157 const char *match_type;
2158 const char **match_with;
2159 size_t count;
2160
2161 dlp->is_tall
2162 = secfile_lookup_bool_default(file, FALSE, "%s.layer%d_is_tall",
2163 sec_name, l);
2164 dlp->offset_x
2165 = secfile_lookup_int_default(file, 0, "%s.layer%d_offset_x",
2166 sec_name, l);
2167 dlp->offset_y
2168 = secfile_lookup_int_default(file, 0, "%s.layer%d_offset_y",
2169 sec_name, l);
2170 dlp->offset_x = ceil(t->scale * dlp->offset_x);
2171 dlp->offset_y = ceil(t->scale * dlp->offset_y);
2172
2173 match_type = secfile_lookup_str_default(file, NULL,
2174 "%s.layer%d_match_type",
2175 sec_name, l);
2176 if (match_type) {
2177 int j;
2178
2179 /* Determine our match_type. */
2180 for (j = 0; j < tslp->match_count; j++) {
2181 if (fc_strcasecmp(tslp->match_types[j], match_type) == 0) {
2182 break;
2183 }
2184 }
2185 if (j >= tslp->match_count) {
2186 log_error("[%s] invalid match_type \"%s\".", sec_name, match_type);
2187 } else {
2188 dlp->match_index[dlp->match_indices++] = j;
2189 }
2190 }
2191
2192 match_with = secfile_lookup_str_vec(file, &count,
2193 "%s.layer%d_match_with",
2194 sec_name, l);
2195 if (match_with) {
2196 int j, k;
2197
2198 if (count > MAX_NUM_MATCH_WITH) {
2199 log_error("[%s] match_with has too many types (%d, max %d)",
2200 sec_name, (int) count, MAX_NUM_MATCH_WITH);
2201 count = MAX_NUM_MATCH_WITH;
2202 }
2203
2204 if (1 < dlp->match_indices) {
2205 log_error("[%s] previous match_with ignored.", sec_name);
2206 dlp->match_indices = 1;
2207 } else if (1 > dlp->match_indices) {
2208 log_error("[%s] missing match_type, using \"%s\".",
2209 sec_name, tslp->match_types[0]);
2210 dlp->match_index[0] = 0;
2211 dlp->match_indices = 1;
2212 }
2213
2214 for (k = 0; k < count; k++) {
2215 for (j = 0; j < tslp->match_count; j++) {
2216 if (fc_strcasecmp(tslp->match_types[j], match_with[k]) == 0) {
2217 break;
2218 }
2219 }
2220 if (j >= tslp->match_count) {
2221 log_error("[%s] layer%d_match_with: invalid \"%s\".",
2222 sec_name, l, match_with[k]);
2223 } else if (1 < count) {
2224 int m;
2225
2226 for (m = 0; m < dlp->match_indices; m++) {
2227 if (dlp->match_index[m] == j) {
2228 log_error("[%s] layer%d_match_with: duplicate \"%s\".",
2229 sec_name, l, match_with[k]);
2230 break;
2231 }
2232 }
2233 if (m >= dlp->match_indices) {
2234 dlp->match_index[dlp->match_indices++] = j;
2235 }
2236 } else {
2237 dlp->match_index[dlp->match_indices++] = j;
2238 }
2239 }
2240 free(match_with);
2241 match_with = NULL;
2242 }
2243
2244 /* Check match_indices */
2245 switch (dlp->match_indices) {
2246 case 0:
2247 case 1:
2248 dlp->match_style = MATCH_NONE;
2249 break;
2250 case 2:
2251 if (dlp->match_index[0] == dlp->match_index[1] ) {
2252 dlp->match_style = MATCH_SAME;
2253 } else {
2254 dlp->match_style = MATCH_PAIR;
2255 }
2256 break;
2257 default:
2258 dlp->match_style = MATCH_FULL;
2259 break;
2260 };
2261
2262 sprite_type
2263 = secfile_lookup_str_default(file, "whole", "%s.layer%d_sprite_type",
2264 sec_name, l);
2265 dlp->sprite_type = check_sprite_type(sprite_type, sec_name);
2266
2267 switch (dlp->sprite_type) {
2268 case CELL_WHOLE:
2269 /* OK, no problem */
2270 break;
2271 case CELL_CORNER:
2272 if (dlp->is_tall
2273 || dlp->offset_x > 0
2274 || dlp->offset_y > 0) {
2275 log_error("[%s] layer %d: you cannot have tall terrain or\n"
2276 "a sprite offset with a cell-based drawing method.",
2277 sec_name, l);
2278 dlp->is_tall = FALSE;
2279 dlp->offset_x = dlp->offset_y = 0;
2280 }
2281 break;
2282 };
2283 }
2284
2285 if (!drawing_hash_insert(t->tile_hash, draw->name, draw)) {
2286 log_error("warning: multiple tile sections containing terrain tag \"%s\".",
2287 draw->name);
2288 goto ON_ERROR;
2289 }
2290 } section_list_iterate_end;
2291 section_list_destroy(sections);
2292 sections = NULL;
2293
2294 t->estyle_hash = estyle_hash_new();
2295
2296 for (i = 0; i < ESTYLE_COUNT; i++) {
2297 t->style_lists[i] = extra_type_list_new();
2298 }
2299 t->flagged_bases_list = extra_type_list_new();
2300
2301 for (i = 0; (extraname = secfile_lookup_str_default(file, NULL,
2302 "extras.styles%d.name",
2303 i)); i++) {
2304 const char *style_name;
2305 enum extrastyle_id style;
2306
2307 style_name = secfile_lookup_str_default(file, "Single1",
2308 "extras.styles%d.style", i);
2309 style = extrastyle_id_by_name(style_name, fc_strcasecmp);
2310 if (!extrastyle_id_is_valid(style)) {
2311 log_error("Unknown extra style \"%s\" for road \"%s\"",
2312 style_name, extraname);
2313 goto ON_ERROR;
2314 }
2315
2316 if (!estyle_hash_insert(t->estyle_hash, extraname, style)) {
2317 log_error("warning: duplicate extrastyle entry [%s].", extraname);
2318 goto ON_ERROR;
2319 }
2320 }
2321
2322 spec_filenames = secfile_lookup_str_vec(file, &num_spec_files,
2323 "tilespec.files");
2324 if (NULL == spec_filenames || 0 == num_spec_files) {
2325 log_error("No tile graphics files specified in \"%s\"", fname);
2326 goto ON_ERROR;
2327 }
2328
2329 fc_assert(t->sprite_hash == NULL);
2330 t->sprite_hash = sprite_hash_new();
2331 for (i = 0; i < num_spec_files; i++) {
2332 struct specfile *sf = fc_malloc(sizeof(*sf));
2333 const char *dname;
2334
2335 log_debug("spec file %s", spec_filenames[i]);
2336
2337 sf->big_sprite = NULL;
2338 dname = fileinfoname(get_data_dirs(), spec_filenames[i]);
2339 if (!dname) {
2340 if (verbose) {
2341 log_error("Can't find spec file \"%s\".", spec_filenames[i]);
2342 }
2343 goto ON_ERROR;
2344 }
2345 sf->file_name = fc_strdup(dname);
2346 scan_specfile(t, sf, duplicates_ok);
2347
2348 specfile_list_prepend(t->specfiles, sf);
2349 }
2350 free(spec_filenames);
2351
2352 t->color_system = color_system_read(file);
2353
2354 /* FIXME: remove this hack. */
2355 t->preferred_themes =
2356 (char **) secfile_lookup_str_vec(file, &num_preferred_themes,
2357 "tilespec.preferred_themes");
2358 if (num_preferred_themes <= 0) {
2359 t->preferred_themes =
2360 (char **) secfile_lookup_str_vec(file, &num_preferred_themes,
2361 "tilespec.prefered_themes");
2362 if (num_preferred_themes > 0) {
2363 log_deprecation("Entry tilespec.prefered_themes in tilespec."
2364 " Use correct spelling tilespec.preferred_themes instead");
2365 }
2366 }
2367 t->num_preferred_themes = num_preferred_themes;
2368 for (i = 0; i < t->num_preferred_themes; i++) {
2369 t->preferred_themes[i] = fc_strdup(t->preferred_themes[i]);
2370 }
2371
2372 secfile_check_unused(file);
2373 secfile_destroy(file);
2374 log_verbose("finished reading \"%s\".", fname);
2375 free(fname);
2376
2377 return t;
2378
2379 ON_ERROR:
2380 secfile_destroy(file);
2381 free(fname);
2382 tileset_free(t);
2383 if (NULL != sections) {
2384 section_list_destroy(sections);
2385 }
2386 return NULL;
2387 }
2388
2389 /**********************************************************************
2390 Returns a text name for the citizen, as used in the tileset.
2391 ***********************************************************************/
citizen_rule_name(enum citizen_category citizen)2392 static const char *citizen_rule_name(enum citizen_category citizen)
2393 {
2394 /* These strings are used in reading the tileset. Do not
2395 * translate. */
2396 switch (citizen) {
2397 case CITIZEN_HAPPY:
2398 return "happy";
2399 case CITIZEN_CONTENT:
2400 return "content";
2401 case CITIZEN_UNHAPPY:
2402 return "unhappy";
2403 case CITIZEN_ANGRY:
2404 return "angry";
2405 default:
2406 break;
2407 }
2408 log_error("Unknown citizen type: %d.", (int) citizen);
2409 return NULL;
2410 }
2411
2412 /****************************************************************************
2413 Return a directional string for the cardinal directions. Normally the
2414 binary value 1000 will be converted into "n1e0s0w0". This is in a
2415 clockwise ordering.
2416 ****************************************************************************/
cardinal_index_str(const struct tileset * t,int idx)2417 static const char *cardinal_index_str(const struct tileset *t, int idx)
2418 {
2419 static char c[64];
2420 int i;
2421
2422 c[0] = '\0';
2423 for (i = 0; i < t->num_cardinal_tileset_dirs; i++) {
2424 int value = (idx >> i) & 1;
2425
2426 cat_snprintf(c, sizeof(c), "%s%d",
2427 dir_get_tileset_name(t->cardinal_tileset_dirs[i]), value);
2428 }
2429
2430 return c;
2431 }
2432
2433 /****************************************************************************
2434 Do the same thing as cardinal_str, except including all valid directions.
2435 The returned string is a pointer to static memory.
2436 ****************************************************************************/
valid_index_str(const struct tileset * t,int idx)2437 static char *valid_index_str(const struct tileset *t, int idx)
2438 {
2439 static char c[64];
2440 int i;
2441
2442 c[0] = '\0';
2443 for (i = 0; i < t->num_valid_tileset_dirs; i++) {
2444 int value = (idx >> i) & 1;
2445
2446 cat_snprintf(c, sizeof(c), "%s%d",
2447 dir_get_tileset_name(t->valid_tileset_dirs[i]), value);
2448 }
2449
2450 return c;
2451 }
2452
2453 /**************************************************************************
2454 Loads the sprite. If the sprite is already loaded a reference
2455 counter is increased. Can return NULL if the sprite couldn't be
2456 loaded.
2457 Scale means if sprite should be scaled, smooth if scaling might use
2458 other scaling algorithm than nearest neighbor.
2459 **************************************************************************/
load_sprite(struct tileset * t,const char * tag_name,bool scale,bool smooth)2460 static struct sprite *load_sprite(struct tileset *t, const char *tag_name,
2461 bool scale, bool smooth)
2462 {
2463 struct small_sprite *ss;
2464 float sprite_scale = 1.0f;
2465
2466 log_debug("load_sprite(tag='%s')", tag_name);
2467 /* Lookup information about where the sprite is found. */
2468 if (!sprite_hash_lookup(t->sprite_hash, tag_name, &ss)) {
2469 return NULL;
2470 }
2471
2472 fc_assert(ss->ref_count >= 0);
2473
2474 if (!ss->sprite) {
2475 /* If the sprite hasn't been loaded already, then load it. */
2476 fc_assert(ss->ref_count == 0);
2477 if (ss->file) {
2478 int w, h;
2479 struct sprite *s;
2480
2481 if (scale) {
2482 s = load_gfx_file(ss->file);
2483 get_sprite_dimensions(s, &w, &h);
2484 ss->sprite = crop_sprite(s, 0, 0, w,
2485 h, NULL, -1, -1, t->scale, smooth);
2486 free_sprite(s);
2487 } else {
2488 ss->sprite = load_gfx_file(ss->file);
2489 }
2490 if (!ss->sprite) {
2491 tileset_error(LOG_FATAL, _("Couldn't load gfx file \"%s\" for sprite '%s'."),
2492 ss->file, tag_name);
2493 }
2494 } else {
2495 int sf_w, sf_h;
2496
2497 ensure_big_sprite(ss->sf);
2498 get_sprite_dimensions(ss->sf->big_sprite, &sf_w, &sf_h);
2499 if (ss->x < 0 || ss->x + ss->width > sf_w
2500 || ss->y < 0 || ss->y + ss->height > sf_h) {
2501 tileset_error(LOG_ERROR, _("Sprite '%s' in file \"%s\" isn't within the image!"),
2502 tag_name, ss->sf->file_name);
2503 return NULL;
2504 }
2505 if (scale) {
2506 sprite_scale = t->scale;
2507 }
2508 ss->sprite = crop_sprite(ss->sf->big_sprite, ss->x, ss->y, ss->width,
2509 ss->height, NULL, -1, -1, sprite_scale,
2510 smooth);
2511 }
2512 }
2513
2514 /* Track the reference count so we know when to free the sprite. */
2515 ss->ref_count++;
2516
2517 return ss->sprite;
2518 }
2519
2520 /**************************************************************************
2521 Create a sprite with the given color and tag.
2522 **************************************************************************/
create_plr_sprite(struct color * pcolor)2523 static struct sprite *create_plr_sprite(struct color *pcolor)
2524 {
2525 struct sprite *sprite;
2526
2527 fc_assert_ret_val(pcolor != NULL, NULL);
2528
2529 if (tileset->scale == 1.0f) {
2530 sprite = create_sprite(128, 64, pcolor);
2531 } else {
2532 sprite = create_sprite(tileset->full_tile_width,
2533 tileset->full_tile_height, pcolor);
2534 }
2535
2536 return sprite;
2537 }
2538
2539 /**************************************************************************
2540 Unloads the sprite. Decrease the reference counter. If the last
2541 reference is removed the sprite is freed.
2542 **************************************************************************/
unload_sprite(struct tileset * t,const char * tag_name)2543 static void unload_sprite(struct tileset *t, const char *tag_name)
2544 {
2545 struct small_sprite *ss;
2546
2547 sprite_hash_lookup(t->sprite_hash, tag_name, &ss);
2548 fc_assert_ret(ss);
2549 fc_assert_ret(ss->ref_count >= 1);
2550 fc_assert_ret(ss->sprite);
2551
2552 ss->ref_count--;
2553
2554 if (ss->ref_count == 0) {
2555 /* Nobody's using the sprite anymore, so we should free it. We know
2556 * where to find it if we need it again. */
2557 log_debug("freeing sprite '%s'.", tag_name);
2558 free_sprite(ss->sprite);
2559 ss->sprite = NULL;
2560 }
2561 }
2562
2563 /**************************************************************************
2564 Return TRUE iff the specified sprite exists in the tileset (whether
2565 or not it is currently loaded).
2566 **************************************************************************/
sprite_exists(const struct tileset * t,const char * tag_name)2567 static bool sprite_exists(const struct tileset *t, const char *tag_name)
2568 {
2569 /* Lookup information about where the sprite is found. */
2570 return sprite_hash_lookup(t->sprite_hash, tag_name, NULL);
2571 }
2572
2573 /* Not very safe, but convenient: */
2574 #define SET_SPRITE(field, tag) \
2575 do { \
2576 t->sprites.field = load_sprite(t, tag, TRUE, TRUE); \
2577 if (t->sprites.field == NULL) { \
2578 tileset_error(LOG_FATAL, _("Sprite for tag '%s' missing."), tag); \
2579 } \
2580 } while(FALSE)
2581
2582 #define SET_SPRITE_NOTSMOOTH(field, tag) \
2583 do { \
2584 t->sprites.field = load_sprite(t, tag, TRUE, FALSE); \
2585 if (t->sprites.field == NULL) { \
2586 tileset_error(LOG_FATAL, _("Sprite for tag '%s' missing."), tag); \
2587 } \
2588 } while(FALSE)
2589
2590 #define SET_SPRITE_UNSCALED(field, tag) \
2591 do { \
2592 t->sprites.field = load_sprite(t, tag, FALSE, FALSE); \
2593 if (t->sprites.field == NULL) { \
2594 tileset_error(LOG_FATAL, _("Sprite for tag '%s' missing."), tag); \
2595 } \
2596 } while(FALSE)
2597
2598 /* Sets sprites.field to tag or (if tag isn't available) to alt */
2599 #define SET_SPRITE_ALT(field, tag, alt) \
2600 do { \
2601 t->sprites.field = load_sprite(t, tag, TRUE, TRUE); \
2602 if (!t->sprites.field) { \
2603 t->sprites.field = load_sprite(t, alt, TRUE, TRUE); \
2604 } \
2605 if (t->sprites.field == NULL) { \
2606 tileset_error(LOG_FATAL, _("Sprite for tags '%s' and alternate '%s' are " \
2607 "both missing."), tag, alt); \
2608 } \
2609 } while(FALSE)
2610
2611 /* Sets sprites.field to tag, or NULL if not available */
2612 #define SET_SPRITE_OPT(field, tag) \
2613 t->sprites.field = load_sprite(t, tag, TRUE, TRUE)
2614
2615 #define SET_SPRITE_ALT_OPT(field, tag, alt) \
2616 do { \
2617 t->sprites.field = tiles_lookup_sprite_tag_alt(t, LOG_VERBOSE, tag, alt,\
2618 "sprite", #field, TRUE); \
2619 } while (FALSE)
2620
2621 /****************************************************************************
2622 Setup the graphics for specialist types.
2623 ****************************************************************************/
tileset_setup_specialist_type(struct tileset * t,Specialist_type_id id)2624 void tileset_setup_specialist_type(struct tileset *t, Specialist_type_id id)
2625 {
2626 /* Load the specialist sprite graphics. */
2627 char buffer[512];
2628 int j;
2629 const char *name = specialist_rule_name(specialist_by_number(id));
2630 const char *graphic_alt = specialist_by_number(id)->graphic_alt;
2631
2632 for (j = 0; j < MAX_NUM_CITIZEN_SPRITES; j++) {
2633 /* Try rule name + index number */
2634 fc_snprintf(buffer, sizeof(buffer), "specialist.%s_%d", name, j);
2635 t->sprites.specialist[id].sprite[j] = load_sprite(t, buffer, FALSE,
2636 FALSE);
2637
2638 /* Break if no more index specific sprites are defined */
2639 if (!t->sprites.specialist[id].sprite[j]) {
2640 break;
2641 }
2642 }
2643
2644 /* Nothing? Try the alt tag */
2645 if (j == 0) {
2646 t->sprites.specialist[id].sprite[j] = load_sprite(t, graphic_alt, FALSE,
2647 FALSE);
2648
2649 if (t->sprites.specialist[id].sprite[j]) {
2650 j = 1;
2651 }
2652 }
2653
2654 t->sprites.specialist[id].count = j;
2655
2656 /* Still nothing? Give up. */
2657 if (j == 0) {
2658 tileset_error(LOG_FATAL, _("No graphics for specialist \"%s\"."), name);
2659 }
2660 }
2661
2662 /****************************************************************************
2663 Setup the graphics for (non-specialist) citizen types.
2664 ****************************************************************************/
tileset_setup_citizen_types(struct tileset * t)2665 static void tileset_setup_citizen_types(struct tileset *t)
2666 {
2667 int i, j;
2668 char buffer[512];
2669
2670 /* Load the citizen sprite graphics, no specialist. */
2671 for (i = 0; i < CITIZEN_LAST; i++) {
2672 const char *name = citizen_rule_name(i);
2673
2674 for (j = 0; j < MAX_NUM_CITIZEN_SPRITES; j++) {
2675 fc_snprintf(buffer, sizeof(buffer), "citizen.%s_%d", name, j);
2676 t->sprites.citizen[i].sprite[j] = load_sprite(t, buffer, FALSE, FALSE);
2677 if (!t->sprites.citizen[i].sprite[j]) {
2678 break;
2679 }
2680 }
2681 t->sprites.citizen[i].count = j;
2682 if (j == 0) {
2683 tileset_error(LOG_FATAL, _("No graphics for citizen \"%s\"."), name);
2684 }
2685 }
2686 }
2687
2688 /****************************************************************************
2689 Return the sprite in the city_sprite listing that corresponds to this
2690 city - based on city style and size.
2691
2692 See also load_city_sprite, free_city_sprite.
2693 ****************************************************************************/
get_city_sprite(const struct city_sprite * city_sprite,const struct city * pcity)2694 static struct sprite *get_city_sprite(const struct city_sprite *city_sprite,
2695 const struct city *pcity)
2696 {
2697 /* get style and match the best tile based on city size */
2698 int style = style_of_city(pcity);
2699 int num_thresholds;
2700 struct city_style_threshold *thresholds;
2701 int img_index;
2702
2703 fc_assert_ret_val(style < city_sprite->num_styles, NULL);
2704
2705 num_thresholds = city_sprite->styles[style].land_num_thresholds;
2706 thresholds = city_sprite->styles[style].land_thresholds;
2707
2708 if (num_thresholds == 0) {
2709 return NULL;
2710 }
2711
2712 /* Get the sprite with the index defined by the effects. */
2713 img_index = pcity->client.city_image;
2714 if (img_index == -100) {
2715 /* Server doesn't know right value as this is from old savegame.
2716 * Guess here based on *client* side information as was done in
2717 * versions where information was not saved to savegame - this should
2718 * give us right answer of what city looked like by the time it was
2719 * put under FoW. */
2720 img_index = get_city_bonus(pcity, EFT_CITY_IMAGE);
2721 }
2722 img_index = CLIP(0, img_index, num_thresholds - 1);
2723
2724 return thresholds[img_index].sprite;
2725 }
2726
2727 /****************************************************************************
2728 Allocates one threshold set for city sprite
2729 ****************************************************************************/
load_city_thresholds_sprites(struct tileset * t,const char * tag,char * graphic,char * graphic_alt,struct city_style_threshold ** thresholds)2730 static int load_city_thresholds_sprites(struct tileset *t, const char *tag,
2731 char *graphic, char *graphic_alt,
2732 struct city_style_threshold **thresholds)
2733 {
2734 char buffer[128];
2735 char *gfx_in_use = graphic;
2736 int num_thresholds = 0;
2737 struct sprite *sprite;
2738 int size;
2739
2740 *thresholds = NULL;
2741
2742 for (size = 0; size < MAX_CITY_SIZE; size++) {
2743 fc_snprintf(buffer, sizeof(buffer), "%s_%s_%d",
2744 gfx_in_use, tag, size);
2745 if ((sprite = load_sprite(t, buffer, TRUE, TRUE))) {
2746 num_thresholds++;
2747 *thresholds = fc_realloc(*thresholds, num_thresholds * sizeof(**thresholds));
2748 (*thresholds)[num_thresholds - 1].sprite = sprite;
2749 } else if (size == 0) {
2750 if (gfx_in_use == graphic) {
2751 /* Try again with graphic_alt. */
2752 size--;
2753 gfx_in_use = graphic_alt;
2754 } else {
2755 /* Don't load any others if the 0 element isn't there. */
2756 break;
2757 }
2758 }
2759 }
2760
2761 return num_thresholds;
2762 }
2763
2764 /****************************************************************************
2765 Allocates and loads a new city sprite from the given sprite tags.
2766
2767 tag may be NULL.
2768
2769 See also get_city_sprite, free_city_sprite.
2770 ****************************************************************************/
load_city_sprite(struct tileset * t,const char * tag)2771 static struct city_sprite *load_city_sprite(struct tileset *t,
2772 const char *tag)
2773 {
2774 struct city_sprite *city_sprite = fc_malloc(sizeof(*city_sprite));
2775 int style;
2776
2777 /* Store number of styles we have allocated memory for.
2778 * game.control.styles_count might change if client disconnects from
2779 * server and connects new one. */
2780 city_sprite->num_styles = game.control.styles_count;
2781 city_sprite->styles = fc_malloc(city_sprite->num_styles
2782 * sizeof(*city_sprite->styles));
2783
2784 for (style = 0; style < city_sprite->num_styles; style++) {
2785 city_sprite->styles[style].land_num_thresholds =
2786 load_city_thresholds_sprites(t, tag, city_styles[style].graphic,
2787 city_styles[style].graphic_alt,
2788 &city_sprite->styles[style].land_thresholds);
2789 }
2790
2791 return city_sprite;
2792 }
2793
2794 /****************************************************************************
2795 Frees a city sprite.
2796
2797 See also get_city_sprite, load_city_sprite.
2798 ****************************************************************************/
free_city_sprite(struct city_sprite * city_sprite)2799 static void free_city_sprite(struct city_sprite *city_sprite)
2800 {
2801 int style;
2802
2803 if (!city_sprite) {
2804 return;
2805 }
2806 for (style = 0; style < city_sprite->num_styles; style++) {
2807 if (city_sprite->styles[style].land_thresholds) {
2808 free(city_sprite->styles[style].land_thresholds);
2809 }
2810 }
2811 free(city_sprite->styles);
2812 free(city_sprite);
2813 }
2814
2815 /**********************************************************************
2816 Initialize 'sprites' structure based on hardwired tags which
2817 freeciv always requires.
2818 ***********************************************************************/
tileset_lookup_sprite_tags(struct tileset * t)2819 static void tileset_lookup_sprite_tags(struct tileset *t)
2820 {
2821 char buffer[512], buffer2[512];
2822 const int W = t->normal_tile_width, H = t->normal_tile_height;
2823 int i, j, f;
2824
2825 fc_assert_ret(t->sprite_hash != NULL);
2826
2827 SET_SPRITE_UNSCALED(treaty_thumb[0], "treaty.disagree_thumb_down");
2828 SET_SPRITE_UNSCALED(treaty_thumb[1], "treaty.agree_thumb_up");
2829
2830 for (j = 0; j < INDICATOR_COUNT; j++) {
2831 const char *names[] = {"science_bulb", "warming_sun", "cooling_flake"};
2832
2833 for (i = 0; i < NUM_TILES_PROGRESS; i++) {
2834 fc_snprintf(buffer, sizeof(buffer), "s.%s_%d", names[j], i);
2835 SET_SPRITE_UNSCALED(indicator[j][i], buffer);
2836 }
2837 }
2838
2839 SET_SPRITE(arrow[ARROW_RIGHT], "s.right_arrow");
2840 SET_SPRITE(arrow[ARROW_PLUS], "s.plus");
2841 SET_SPRITE(arrow[ARROW_MINUS], "s.minus");
2842 if (t->type == TS_ISOMETRIC) {
2843 SET_SPRITE(dither_tile, "t.dither_tile");
2844 }
2845
2846 if (tileset_is_isometric(tileset)) {
2847 SET_SPRITE_NOTSMOOTH(mask.tile, "mask.tile");
2848 } else {
2849 SET_SPRITE(mask.tile, "mask.tile");
2850 }
2851 SET_SPRITE(mask.worked_tile, "mask.worked_tile");
2852 SET_SPRITE(mask.unworked_tile, "mask.unworked_tile");
2853
2854 SET_SPRITE_UNSCALED(tax_luxury, "s.tax_luxury");
2855 SET_SPRITE_UNSCALED(tax_science, "s.tax_science");
2856 SET_SPRITE_UNSCALED(tax_gold, "s.tax_gold");
2857
2858 tileset_setup_citizen_types(t);
2859
2860 for (i = 0; i < SPACESHIP_COUNT; i++) {
2861 const char *names[SPACESHIP_COUNT]
2862 = {"solar_panels", "life_support", "habitation",
2863 "structural", "fuel", "propulsion", "exhaust"};
2864
2865 fc_snprintf(buffer, sizeof(buffer), "spaceship.%s", names[i]);
2866 SET_SPRITE(spaceship[i], buffer);
2867 }
2868
2869 for (i = 0; i < CURSOR_LAST; i++) {
2870 for (f = 0; f < NUM_CURSOR_FRAMES; f++) {
2871 const char *names[CURSOR_LAST] =
2872 {"goto", "patrol", "paradrop", "nuke", "select",
2873 "invalid", "attack", "edit_paint", "edit_add", "wait"};
2874 struct small_sprite *ss;
2875
2876 fc_assert(ARRAY_SIZE(names) == CURSOR_LAST);
2877 fc_snprintf(buffer, sizeof(buffer), "cursor.%s%d", names[i], f);
2878 SET_SPRITE(cursor[i].frame[f], buffer);
2879 if (sprite_hash_lookup(t->sprite_hash, buffer, &ss)) {
2880 t->sprites.cursor[i].hot_x = ss->hot_x;
2881 t->sprites.cursor[i].hot_y = ss->hot_y;
2882 }
2883 }
2884 }
2885
2886 for (i = 0; i < ICON_COUNT; i++) {
2887 const char *names[ICON_COUNT] = {"freeciv", "citydlg"};
2888
2889 fc_snprintf(buffer, sizeof(buffer), "icon.%s", names[i]);
2890 SET_SPRITE(icon[i], buffer);
2891 }
2892
2893 for (i = 0; i < E_COUNT; i++) {
2894 const char *tag = get_event_tag(i);
2895
2896 SET_SPRITE(events[i], tag);
2897 }
2898
2899 SET_SPRITE(explode.nuke, "explode.nuke");
2900
2901 sprite_vector_init(&t->sprites.explode.unit);
2902 for (i = 0; ; i++) {
2903 struct sprite *sprite;
2904
2905 fc_snprintf(buffer, sizeof(buffer), "explode.unit_%d", i);
2906 sprite = load_sprite(t, buffer, TRUE, TRUE);
2907 if (!sprite) {
2908 break;
2909 }
2910 sprite_vector_append(&t->sprites.explode.unit, sprite);
2911 }
2912
2913 SET_SPRITE(unit.auto_attack, "unit.auto_attack");
2914 SET_SPRITE(unit.auto_settler, "unit.auto_settler");
2915 SET_SPRITE(unit.auto_explore, "unit.auto_explore");
2916 SET_SPRITE(unit.fortified, "unit.fortified");
2917 SET_SPRITE(unit.fortifying, "unit.fortifying");
2918 SET_SPRITE(unit.go_to, "unit.goto");
2919 SET_SPRITE(unit.irrigate, "unit.irrigate");
2920 SET_SPRITE(unit.plant, "unit.plant");
2921 SET_SPRITE(unit.pillage, "unit.pillage");
2922 SET_SPRITE(unit.sentry, "unit.sentry");
2923 SET_SPRITE(unit.convert, "unit.convert");
2924 SET_SPRITE(unit.stack, "unit.stack");
2925 SET_SPRITE(unit.loaded, "unit.loaded");
2926 SET_SPRITE(unit.transform, "unit.transform");
2927 SET_SPRITE(unit.connect, "unit.connect");
2928 SET_SPRITE(unit.patrol, "unit.patrol");
2929 for (i = 0; i < MAX_NUM_BATTLEGROUPS; i++) {
2930 fc_snprintf(buffer, sizeof(buffer), "unit.battlegroup_%d", i);
2931 fc_snprintf(buffer2, sizeof(buffer2), "city.size_%d", i + 1);
2932 fc_assert(MAX_NUM_BATTLEGROUPS < NUM_TILES_DIGITS);
2933 SET_SPRITE_ALT(unit.battlegroup[i], buffer, buffer2);
2934 }
2935 SET_SPRITE(unit.lowfuel, "unit.lowfuel");
2936 SET_SPRITE(unit.tired, "unit.tired");
2937
2938 for(i=0; i<NUM_TILES_HP_BAR; i++) {
2939 fc_snprintf(buffer, sizeof(buffer), "unit.hp_%d", i*10);
2940 SET_SPRITE(unit.hp_bar[i], buffer);
2941 }
2942
2943 for (i = 0; i < MAX_VET_LEVELS; i++) {
2944 /* Veteran level sprites are optional. For instance "green" units
2945 * usually have no special graphic. */
2946 fc_snprintf(buffer, sizeof(buffer), "unit.vet_%d", i);
2947 t->sprites.unit.vet_lev[i] = load_sprite(t, buffer, TRUE, TRUE);
2948 }
2949
2950 t->sprites.unit.select[0] = NULL;
2951 if (sprite_exists(t, "unit.select0")) {
2952 for (i = 0; i < NUM_TILES_SELECT; i++) {
2953 fc_snprintf(buffer, sizeof(buffer), "unit.select%d", i);
2954 SET_SPRITE(unit.select[i], buffer);
2955 }
2956 }
2957
2958 SET_SPRITE(citybar.shields, "citybar.shields");
2959 SET_SPRITE(citybar.food, "citybar.food");
2960 SET_SPRITE(citybar.trade, "citybar.trade");
2961 SET_SPRITE(citybar.occupied, "citybar.occupied");
2962 SET_SPRITE(citybar.background, "citybar.background");
2963 sprite_vector_init(&t->sprites.citybar.occupancy);
2964 for (i = 0; ; i++) {
2965 struct sprite *sprite;
2966
2967 fc_snprintf(buffer, sizeof(buffer), "citybar.occupancy_%d", i);
2968 sprite = load_sprite(t, buffer, TRUE, TRUE);
2969 if (!sprite) {
2970 break;
2971 }
2972 sprite_vector_append(&t->sprites.citybar.occupancy, sprite);
2973 }
2974 if (t->sprites.citybar.occupancy.size < 2) {
2975 tileset_error(LOG_FATAL, _("Missing necessary citybar.occupancy_N sprites."));
2976 }
2977
2978 #define SET_EDITOR_SPRITE(x) SET_SPRITE(editor.x, "editor." #x)
2979 SET_EDITOR_SPRITE(erase);
2980 SET_EDITOR_SPRITE(brush);
2981 SET_EDITOR_SPRITE(copy);
2982 SET_EDITOR_SPRITE(paste);
2983 SET_EDITOR_SPRITE(copypaste);
2984 SET_EDITOR_SPRITE(startpos);
2985 SET_EDITOR_SPRITE(terrain);
2986 SET_EDITOR_SPRITE(terrain_resource);
2987 SET_EDITOR_SPRITE(terrain_special);
2988 SET_EDITOR_SPRITE(unit);
2989 SET_EDITOR_SPRITE(city);
2990 SET_EDITOR_SPRITE(vision);
2991 SET_EDITOR_SPRITE(territory);
2992 SET_EDITOR_SPRITE(properties);
2993 SET_EDITOR_SPRITE(road);
2994 SET_EDITOR_SPRITE(military_base);
2995 #undef SET_EDITOR_SPRITE
2996
2997 SET_SPRITE(city.disorder, "city.disorder");
2998
2999 /* Fallbacks for goto path turn numbers:
3000 * path.step_%d, path.exhausted_mp_%d
3001 * --> path.turns_%d
3002 * --> city.size_%d */
3003 #define SET_GOTO_TURN_SPRITE(state, state_name, factor, factor_name) \
3004 fc_snprintf(buffer, sizeof(buffer), "path." state_name "_%d" #factor, i); \
3005 SET_SPRITE_OPT(path.s[state].turns ## factor_name [i], buffer); \
3006 if (t->sprites.path.s[state].turns ## factor_name [i] == NULL) { \
3007 t->sprites.path.s[state].turns ## factor_name [i] = \
3008 t->sprites.path.s[GTS_MP_LEFT].turns ## factor_name [i]; \
3009 }
3010 for(i=0; i<NUM_TILES_DIGITS; i++) {
3011 fc_snprintf(buffer, sizeof(buffer), "city.size_%d", i);
3012 SET_SPRITE(city.size[i], buffer);
3013 fc_snprintf(buffer2, sizeof(buffer2), "path.turns_%d", i);
3014 SET_SPRITE_ALT(path.s[GTS_MP_LEFT].turns[i], buffer2, buffer);
3015 SET_GOTO_TURN_SPRITE(GTS_TURN_STEP, "step",,);
3016 SET_GOTO_TURN_SPRITE(GTS_EXHAUSTED_MP, "exhausted_mp",,);
3017
3018 fc_snprintf(buffer, sizeof(buffer), "city.size_%d0", i);
3019 SET_SPRITE(city.size_tens[i], buffer);
3020 fc_snprintf(buffer2, sizeof(buffer2), "path.turns_%d0", i);
3021 SET_SPRITE_ALT(path.s[GTS_MP_LEFT].turns_tens[i], buffer2, buffer);
3022 SET_GOTO_TURN_SPRITE(GTS_TURN_STEP, "step", 0, _tens);
3023 SET_GOTO_TURN_SPRITE(GTS_EXHAUSTED_MP, "exhausted_mp", 0, _tens);
3024
3025 fc_snprintf(buffer, sizeof(buffer), "city.size_%d00", i);
3026 SET_SPRITE_OPT(city.size_hundreds[i], buffer);
3027 fc_snprintf(buffer2, sizeof(buffer2), "path.turns_%d00", i);
3028 SET_SPRITE_ALT_OPT(path.s[GTS_MP_LEFT].turns_hundreds[i], buffer2,
3029 buffer);
3030 SET_GOTO_TURN_SPRITE(GTS_TURN_STEP, "step", 00, _hundreds);
3031 SET_GOTO_TURN_SPRITE(GTS_EXHAUSTED_MP, "exhausted_mp", 00, _hundreds);
3032
3033 fc_snprintf(buffer, sizeof(buffer), "city.t_food_%d", i);
3034 SET_SPRITE(city.tile_foodnum[i], buffer);
3035 fc_snprintf(buffer, sizeof(buffer), "city.t_shields_%d", i);
3036 SET_SPRITE(city.tile_shieldnum[i], buffer);
3037 fc_snprintf(buffer, sizeof(buffer), "city.t_trade_%d", i);
3038 SET_SPRITE(city.tile_tradenum[i], buffer);
3039 }
3040 #undef SET_GOTO_TURN_SPRITE
3041
3042 /* Must have at least one upkeep sprite per output type (and unhappy) */
3043 /* The rest are optional; we copy the previous sprite for unspecified ones */
3044 fc_strlcpy(buffer, "upkeep.unhappy", sizeof(buffer));
3045 SET_SPRITE(upkeep.unhappy[0], buffer);
3046 for(i=1; i<MAX_NUM_UPKEEP_SPRITES; i++) {
3047 fc_snprintf(buffer2, sizeof(buffer2), "upkeep.unhappy%d", i+1);
3048 if (sprite_exists(t, buffer2)) {
3049 SET_SPRITE(upkeep.unhappy[i], buffer2);
3050 fc_strlcpy(buffer, buffer2, sizeof(buffer));
3051 } else {
3052 SET_SPRITE(upkeep.unhappy[i], buffer);
3053 }
3054 }
3055 output_type_iterate(o) {
3056 fc_snprintf(buffer, sizeof(buffer),
3057 "upkeep.%s", get_output_identifier(o));
3058 SET_SPRITE_OPT(upkeep.output[o][0], buffer);
3059 for(i=1; i<MAX_NUM_UPKEEP_SPRITES; i++) {
3060 fc_snprintf(buffer2, sizeof(buffer2),
3061 "upkeep.%s%d", get_output_identifier(o), i+1);
3062 if (sprite_exists(t, buffer2)) {
3063 SET_SPRITE(upkeep.output[o][i], buffer2);
3064 fc_strlcpy(buffer, buffer2, sizeof(buffer));
3065 } else {
3066 /* Optional, as maybe the upkeep 1 sprite didn't exist either */
3067 SET_SPRITE_OPT(upkeep.output[o][i], buffer);
3068 }
3069 }
3070 } output_type_iterate_end;
3071
3072 t->max_upkeep_height = calculate_max_upkeep_height(t);
3073
3074 SET_SPRITE(user.attention, "user.attention");
3075
3076 SET_SPRITE_OPT(path.s[GTS_MP_LEFT].specific, "path.normal");
3077 SET_SPRITE_OPT(path.s[GTS_EXHAUSTED_MP].specific, "path.exhausted_mp");
3078 SET_SPRITE_OPT(path.s[GTS_TURN_STEP].specific, "path.step");
3079 SET_SPRITE(path.waypoint, "path.waypoint");
3080
3081 SET_SPRITE_NOTSMOOTH(tx.fog, "tx.fog");
3082
3083 sprite_vector_init(&t->sprites.colors.overlays);
3084 for (i = 0; ; i++) {
3085 struct sprite *sprite;
3086
3087 fc_snprintf(buffer, sizeof(buffer), "colors.overlay_%d", i);
3088 sprite = load_sprite(t, buffer, TRUE, TRUE);
3089 if (!sprite) {
3090 break;
3091 }
3092 sprite_vector_append(&t->sprites.colors.overlays, sprite);
3093 }
3094 if (i == 0) {
3095 tileset_error(LOG_FATAL, _("Missing overlay-color sprite colors.overlay_0."));
3096 }
3097
3098 /* Chop up and build the overlay graphics. */
3099 sprite_vector_reserve(&t->sprites.city.worked_tile_overlay,
3100 sprite_vector_size(&t->sprites.colors.overlays));
3101 sprite_vector_reserve(&t->sprites.city.unworked_tile_overlay,
3102 sprite_vector_size(&t->sprites.colors.overlays));
3103 for (i = 0; i < sprite_vector_size(&t->sprites.colors.overlays); i++) {
3104 struct sprite *color, *color_mask;
3105 struct sprite *worked, *unworked;
3106
3107 color = *sprite_vector_get(&t->sprites.colors.overlays, i);
3108 color_mask = crop_sprite(color, 0, 0, W, H, t->sprites.mask.tile, 0, 0,
3109 1.0f, FALSE);
3110 worked = crop_sprite(color_mask, 0, 0, W, H,
3111 t->sprites.mask.worked_tile, 0, 0, 1.0f, FALSE);
3112 unworked = crop_sprite(color_mask, 0, 0, W, H,
3113 t->sprites.mask.unworked_tile, 0, 0, 1.0f, FALSE);
3114 free_sprite(color_mask);
3115 t->sprites.city.worked_tile_overlay.p[i] = worked;
3116 t->sprites.city.unworked_tile_overlay.p[i] = unworked;
3117 }
3118
3119
3120 {
3121 SET_SPRITE(grid.unavailable, "grid.unavailable");
3122 SET_SPRITE_OPT(grid.nonnative, "grid.nonnative");
3123
3124 for (i = 0; i < EDGE_COUNT; i++) {
3125 int be;
3126
3127 if (i == EDGE_UD && t->hex_width == 0) {
3128 continue;
3129 } else if (i == EDGE_LR && t->hex_height == 0) {
3130 continue;
3131 }
3132
3133 fc_snprintf(buffer, sizeof(buffer), "grid.main.%s", edge_name[i]);
3134 SET_SPRITE(grid.main[i], buffer);
3135
3136 fc_snprintf(buffer, sizeof(buffer), "grid.city.%s", edge_name[i]);
3137 SET_SPRITE(grid.city[i], buffer);
3138
3139 fc_snprintf(buffer, sizeof(buffer), "grid.worked.%s", edge_name[i]);
3140 SET_SPRITE(grid.worked[i], buffer);
3141
3142 fc_snprintf(buffer, sizeof(buffer), "grid.selected.%s", edge_name[i]);
3143 SET_SPRITE(grid.selected[i], buffer);
3144
3145 fc_snprintf(buffer, sizeof(buffer), "grid.coastline.%s", edge_name[i]);
3146 SET_SPRITE(grid.coastline[i], buffer);
3147
3148 for (be = 0; be < 2; be++) {
3149 fc_snprintf(buffer, sizeof(buffer), "grid.borders.%c",
3150 edge_name[i][be]);
3151 SET_SPRITE(grid.borders[i][be], buffer);
3152 }
3153 }
3154 }
3155
3156 switch (t->darkness_style) {
3157 case DARKNESS_NONE:
3158 /* Nothing. */
3159 break;
3160 case DARKNESS_ISORECT:
3161 {
3162 /* Isometric: take a single tx.darkness tile and split it into 4. */
3163 struct sprite *darkness = load_sprite(t, "tx.darkness", TRUE, FALSE);
3164 const int ntw = t->normal_tile_width, nth = t->normal_tile_height;
3165 int offsets[4][2] = {{ntw / 2, 0}, {0, nth / 2}, {ntw / 2, nth / 2}, {0, 0}};
3166
3167 if (!darkness) {
3168 tileset_error(LOG_FATAL, _("Sprite tx.darkness missing."));
3169 }
3170 for (i = 0; i < 4; i++) {
3171 t->sprites.tx.darkness[i] = crop_sprite(darkness, offsets[i][0],
3172 offsets[i][1], ntw / 2,
3173 nth / 2, NULL, 0, 0, 1.0f,
3174 FALSE);
3175 }
3176 }
3177 break;
3178 case DARKNESS_CARD_SINGLE:
3179 for (i = 0; i < t->num_cardinal_tileset_dirs; i++) {
3180 enum direction8 dir = t->cardinal_tileset_dirs[i];
3181
3182 fc_snprintf(buffer, sizeof(buffer), "tx.darkness_%s",
3183 dir_get_tileset_name(dir));
3184 SET_SPRITE_NOTSMOOTH(tx.darkness[i], buffer);
3185 }
3186 break;
3187 case DARKNESS_CARD_FULL:
3188 for(i = 1; i < t->num_index_cardinal; i++) {
3189 fc_snprintf(buffer, sizeof(buffer), "tx.darkness_%s",
3190 cardinal_index_str(t, i));
3191 SET_SPRITE_NOTSMOOTH(tx.darkness[i], buffer);
3192 }
3193 break;
3194 case DARKNESS_CORNER:
3195 t->sprites.tx.fullfog = fc_realloc(t->sprites.tx.fullfog,
3196 81 * sizeof(*t->sprites.tx.fullfog));
3197 for (i = 0; i < 81; i++) {
3198 /* Unknown, fog, known. */
3199 char ids[] = {'u', 'f', 'k'};
3200 char buf[512] = "t.fog";
3201 int values[4], vi, k = i;
3202
3203 for (vi = 0; vi < 4; vi++) {
3204 values[vi] = k % 3;
3205 k /= 3;
3206
3207 cat_snprintf(buf, sizeof(buf), "_%c", ids[values[vi]]);
3208 }
3209 fc_assert(k == 0);
3210
3211 t->sprites.tx.fullfog[i] = load_sprite(t, buf, TRUE, FALSE);
3212 }
3213 break;
3214 };
3215
3216 /* no other place to initialize these variables */
3217 sprite_vector_init(&t->sprites.nation_flag);
3218 sprite_vector_init(&t->sprites.nation_shield);
3219 }
3220
3221 /**************************************************************************
3222 Load sprites of one river type.
3223 **************************************************************************/
load_river_sprites(struct tileset * t,struct river_sprites * store,const char * tag_pfx)3224 static bool load_river_sprites(struct tileset *t,
3225 struct river_sprites *store, const char *tag_pfx)
3226 {
3227 int i;
3228 char buffer[512];
3229
3230 for (i = 0; i < t->num_index_cardinal; i++) {
3231 fc_snprintf(buffer, sizeof(buffer), "%s_s_%s",
3232 tag_pfx, cardinal_index_str(t, i));
3233 store->spec[i] = load_sprite(t, buffer, TRUE, TRUE);
3234 if (store->spec[i] == NULL) {
3235 return FALSE;
3236 }
3237 }
3238
3239 for (i = 0; i < t->num_cardinal_tileset_dirs; i++) {
3240 fc_snprintf(buffer, sizeof(buffer), "%s_outlet_%s",
3241 tag_pfx, dir_get_tileset_name(t->cardinal_tileset_dirs[i]));
3242 store->outlet[i] = load_sprite(t, buffer, TRUE, TRUE);
3243 if (store->outlet[i] == NULL) {
3244 if (t->cardinal_tileset_dirs[i] == DIR8_NORTHWEST
3245 || t->cardinal_tileset_dirs[i] == DIR8_NORTHEAST
3246 || t->cardinal_tileset_dirs[i] == DIR8_SOUTHEAST
3247 || t->cardinal_tileset_dirs[i] == DIR8_SOUTHWEST) {
3248 log_debug("Missing \"%s\", support for this is deprecated.", buffer);
3249 } else {
3250 return FALSE;
3251 }
3252 }
3253 }
3254
3255 return TRUE;
3256 }
3257
3258 /**************************************************************************
3259 Frees any internal buffers which are created by load_sprite. Should
3260 be called after the last (for a given period of time) load_sprite
3261 call. This saves a fair amount of memory, but it will take extra time
3262 the next time we start loading sprites again.
3263 **************************************************************************/
finish_loading_sprites(struct tileset * t)3264 void finish_loading_sprites(struct tileset *t)
3265 {
3266 specfile_list_iterate(t->specfiles, sf) {
3267 if (sf->big_sprite) {
3268 free_sprite(sf->big_sprite);
3269 sf->big_sprite = NULL;
3270 }
3271 } specfile_list_iterate_end;
3272 }
3273
3274 /**********************************************************************
3275 Load the tiles; requires tilespec_read_toplevel() called previously.
3276 Leads to tile_sprites being allocated and filled with pointers
3277 to sprites. Also sets up and populates sprite_hash, and calls func
3278 to initialize 'sprites' structure.
3279 ***********************************************************************/
tileset_load_tiles(struct tileset * t)3280 void tileset_load_tiles(struct tileset *t)
3281 {
3282 tileset_lookup_sprite_tags(t);
3283 finish_loading_sprites(t);
3284 }
3285
3286 /**********************************************************************
3287 Lookup sprite to match tag, or else to match alt if don't find,
3288 or else return NULL, and emit log message.
3289 ***********************************************************************/
tiles_lookup_sprite_tag_alt(struct tileset * t,enum log_level level,const char * tag,const char * alt,const char * what,const char * name,bool scale)3290 struct sprite *tiles_lookup_sprite_tag_alt(struct tileset *t,
3291 enum log_level level,
3292 const char *tag, const char *alt,
3293 const char *what,
3294 const char *name,
3295 bool scale)
3296 {
3297 struct sprite *sp;
3298
3299 /* (should get sprite_hash before connection) */
3300 fc_assert_ret_val_msg(NULL != t->sprite_hash, NULL,
3301 "attempt to lookup for %s \"%s\" before "
3302 "sprite_hash setup", what, name);
3303
3304 sp = load_sprite(t, tag, scale, TRUE);
3305 if (sp) return sp;
3306
3307 sp = load_sprite(t, alt, scale, TRUE);
3308 if (sp) {
3309 log_verbose("Using alternate graphic \"%s\" "
3310 "(instead of \"%s\") for %s \"%s\".",
3311 alt, tag, what, name);
3312 return sp;
3313 }
3314
3315 tileset_error(level, _("Don't have graphics tags \"%s\" or \"%s\" for %s \"%s\"."),
3316 tag, alt, what, name);
3317
3318 return NULL;
3319 }
3320
3321 /**********************************************************************
3322 Helper function to load sprite for one unit orientation
3323 ***********************************************************************/
tileset_setup_unit_direction(struct tileset * t,int uidx,const char * base_str,enum direction8 dir,const char * dirsuffix)3324 static bool tileset_setup_unit_direction(struct tileset *t,
3325 int uidx,
3326 const char *base_str,
3327 enum direction8 dir,
3328 const char *dirsuffix)
3329 {
3330 char buf[2048];
3331
3332 fc_snprintf(buf, sizeof(buf), "%s_%s", base_str, dirsuffix);
3333
3334 /* We don't use _alt graphics here, as that could lead to loading
3335 * real icon gfx, but alternative orientation gfx. Tileset author
3336 * probably meant icon gfx to be used as fallback for all orientations */
3337 t->sprites.units.facing[uidx][dir] = load_sprite(t, buf, TRUE, TRUE);
3338
3339 if (t->sprites.units.facing[uidx][dir] != NULL) {
3340 return TRUE;
3341 }
3342
3343 return FALSE;
3344 }
3345
3346 /**********************************************************************
3347 Try to setup all unit type sprites from single tag
3348 ***********************************************************************/
tileset_setup_unit_type_from_tag(struct tileset * t,int uidx,const char * tag)3349 static bool tileset_setup_unit_type_from_tag(struct tileset *t,
3350 int uidx, const char *tag)
3351 {
3352 bool facing_sprites = TRUE;
3353
3354 t->sprites.units.icon[uidx] = load_sprite(t, tag, TRUE, TRUE);
3355
3356 #define LOAD_FACING_SPRITE(dir, dname) \
3357 if (!tileset_setup_unit_direction(t, uidx, tag, dir, dname)) { \
3358 facing_sprites = FALSE; \
3359 }
3360
3361 LOAD_FACING_SPRITE(DIR8_NORTHWEST, "nw");
3362 LOAD_FACING_SPRITE(DIR8_NORTH, "n");
3363 LOAD_FACING_SPRITE(DIR8_NORTHEAST, "ne");
3364 LOAD_FACING_SPRITE(DIR8_WEST, "w");
3365 LOAD_FACING_SPRITE(DIR8_EAST, "e");
3366 LOAD_FACING_SPRITE(DIR8_SOUTHWEST, "sw");
3367 LOAD_FACING_SPRITE(DIR8_SOUTH, "s");
3368 LOAD_FACING_SPRITE(DIR8_SOUTHEAST, "se");
3369
3370 if (!facing_sprites && t->sprites.units.icon[uidx] == NULL) {
3371 /* Neither icon gfx or orientation sprites */
3372 return FALSE;
3373 }
3374
3375 /* Fix a random orientation for displaying unit type in help etc.
3376 * We don't necessarily know the map topology yet, so choose a seed
3377 * that can be used to pick a valid direction later (24 is lcm(6,8)).
3378 * See get_unittype_sprite(). */
3379 t->sprites.units.default_dir_seed[uidx] = fc_rand(24);
3380
3381 return TRUE;
3382
3383 #undef LOAD_FACING_SPRITE
3384 }
3385
3386 /**********************************************************************
3387 Set unit_type sprite value; should only happen after
3388 tilespec_load_tiles().
3389 ***********************************************************************/
tileset_setup_unit_type(struct tileset * t,struct unit_type * ut)3390 void tileset_setup_unit_type(struct tileset *t, struct unit_type *ut)
3391 {
3392 int uidx = utype_index(ut);
3393
3394 if (!tileset_setup_unit_type_from_tag(t, uidx, ut->graphic_str)
3395 && !tileset_setup_unit_type_from_tag(t, uidx, ut->graphic_alt)) {
3396 tileset_error(LOG_FATAL, _("Missing %s unit sprite for tags \"%s\" and alternative \"%s\"."),
3397 utype_rule_name(ut), ut->graphic_str, ut->graphic_alt);
3398 }
3399 }
3400
3401 /**********************************************************************
3402 Set improvement_type sprite value; should only happen after
3403 tilespec_load_tiles().
3404 ***********************************************************************/
tileset_setup_impr_type(struct tileset * t,struct impr_type * pimprove)3405 void tileset_setup_impr_type(struct tileset *t,
3406 struct impr_type *pimprove)
3407 {
3408 t->sprites.building[improvement_index(pimprove)] =
3409 tiles_lookup_sprite_tag_alt(t, LOG_VERBOSE, pimprove->graphic_str,
3410 pimprove->graphic_alt, "improvement",
3411 improvement_rule_name(pimprove), FALSE);
3412
3413 /* should maybe do something if NULL, eg generic default? */
3414 }
3415
3416 /**********************************************************************
3417 Set tech_type sprite value; should only happen after
3418 tilespec_load_tiles().
3419 ***********************************************************************/
tileset_setup_tech_type(struct tileset * t,struct advance * padvance)3420 void tileset_setup_tech_type(struct tileset *t,
3421 struct advance *padvance)
3422 {
3423 if (valid_advance(padvance)) {
3424 t->sprites.tech[advance_index(padvance)] =
3425 tiles_lookup_sprite_tag_alt(t, LOG_VERBOSE, padvance->graphic_str,
3426 padvance->graphic_alt, "technology",
3427 advance_rule_name(padvance), FALSE);
3428
3429 /* should maybe do something if NULL, eg generic default? */
3430 } else {
3431 t->sprites.tech[advance_index(padvance)] = NULL;
3432 }
3433 }
3434
3435 /****************************************************************************
3436 Set resource sprite values; should only happen after
3437 tilespec_load_tiles().
3438 ****************************************************************************/
tileset_setup_resource(struct tileset * t,const struct resource * presource)3439 void tileset_setup_resource(struct tileset *t,
3440 const struct resource *presource)
3441 {
3442 fc_assert_ret(NULL != presource);
3443 t->sprites.resource[resource_index(presource)] =
3444 tiles_lookup_sprite_tag_alt(t, LOG_VERBOSE, presource->graphic_str,
3445 presource->graphic_alt, "resource",
3446 resource_rule_name(presource), TRUE);
3447 }
3448
3449 /****************************************************************************
3450 Set extra sprite values; should only happen after
3451 tilespec_load_tiles().
3452 ****************************************************************************/
tileset_setup_extra(struct tileset * t,struct extra_type * pextra)3453 void tileset_setup_extra(struct tileset *t,
3454 struct extra_type *pextra)
3455 {
3456 const int id = extra_index(pextra);
3457 enum extrastyle_id extrastyle;
3458
3459 if (!fc_strcasecmp(pextra->graphic_str, "none")) {
3460 /* Extra without graphics */
3461 t->sprites.extras[id].extrastyle = extrastyle_id_invalid();
3462 } else {
3463
3464 if (!estyle_hash_lookup(t->estyle_hash, pextra->graphic_str,
3465 &extrastyle)
3466 && !estyle_hash_lookup(t->estyle_hash, pextra->graphic_alt,
3467 &extrastyle)) {
3468 tileset_error(LOG_FATAL, _("No extrastyle for \"%s\" or \"%s\"."),
3469 pextra->graphic_str,
3470 pextra->graphic_alt);
3471 }
3472
3473 t->sprites.extras[id].extrastyle = extrastyle;
3474
3475 extra_type_list_append(t->style_lists[extrastyle], pextra);
3476
3477 if (extra_has_flag(pextra, EF_SHOW_FLAG)) {
3478 extra_type_list_append(t->flagged_bases_list, pextra);
3479 }
3480
3481 switch (extrastyle) {
3482 case ESTYLE_3LAYER:
3483 tileset_setup_base(t, pextra);
3484 break;
3485
3486 case ESTYLE_ROAD_ALL_SEPARATE:
3487 case ESTYLE_ROAD_PARITY_COMBINED:
3488 case ESTYLE_ROAD_ALL_COMBINED:
3489 case ESTYLE_RIVER:
3490 tileset_setup_road(t, pextra);
3491 break;
3492
3493 case ESTYLE_SINGLE1:
3494 case ESTYLE_SINGLE2:
3495 SET_SPRITE_ALT(extras[id].u.single, pextra->graphic_str, pextra->graphic_alt);
3496 break;
3497
3498 case ESTYLE_CARDINALS:
3499 {
3500 int i;
3501 char buffer[512];
3502
3503 /* We use direction-specific irrigation and farmland graphics, if they
3504 * are available. If not, we just fall back to the basic irrigation
3505 * graphics. */
3506 for (i = 0; i < t->num_index_cardinal; i++) {
3507 fc_snprintf(buffer, sizeof(buffer), "%s_%s",
3508 pextra->graphic_str, cardinal_index_str(t, i));
3509 t->sprites.extras[id].u.cardinals[i] = load_sprite(t, buffer,
3510 TRUE, TRUE);
3511 if (!t->sprites.extras[id].u.cardinals[i]) {
3512 t->sprites.extras[id].u.cardinals[i] = load_sprite(t,
3513 pextra->graphic_str, TRUE,
3514 TRUE);
3515 }
3516 if (!t->sprites.extras[id].u.cardinals[i]) {
3517 fc_snprintf(buffer, sizeof(buffer), "%s_%s",
3518 pextra->graphic_alt, cardinal_index_str(t, i));
3519 t->sprites.extras[id].u.cardinals[i] = load_sprite(t, buffer,
3520 TRUE, TRUE);
3521 }
3522 if (!t->sprites.extras[id].u.cardinals[i]) {
3523 t->sprites.extras[id].u.cardinals[i] = load_sprite(t,
3524 pextra->graphic_alt, TRUE,
3525 TRUE);
3526 }
3527 if (!t->sprites.extras[id].u.cardinals[i]) {
3528 tileset_error(LOG_FATAL, _("Sprite for tags '%s' and alternate '%s' are "
3529 "both missing."),
3530 pextra->graphic_str, pextra->graphic_alt);
3531 }
3532 }
3533 }
3534 break;
3535 case ESTYLE_COUNT:
3536 break;
3537 }
3538 }
3539
3540 if (!fc_strcasecmp(pextra->activity_gfx, "none")) {
3541 t->sprites.extras[id].activity = NULL;
3542 } else {
3543 t->sprites.extras[id].activity = load_sprite(t, pextra->activity_gfx,
3544 TRUE, TRUE);
3545 if (t->sprites.extras[id].activity == NULL) {
3546 t->sprites.extras[id].activity = load_sprite(t, pextra->act_gfx_alt,
3547 TRUE, TRUE);
3548 }
3549 if (t->sprites.extras[id].activity == NULL) {
3550 t->sprites.extras[id].activity = load_sprite(t, pextra->act_gfx_alt2,
3551 TRUE, TRUE);
3552 }
3553 if (t->sprites.extras[id].activity == NULL) {
3554 tileset_error(LOG_FATAL, _("Missing %s building activity sprite for tags \"%s\" and alternatives \"%s\" and \"%s\"."),
3555 extra_rule_name(pextra), pextra->activity_gfx,
3556 pextra->act_gfx_alt, pextra->act_gfx_alt2);
3557 }
3558 }
3559
3560 if (!fc_strcasecmp(pextra->rmact_gfx, "none")) {
3561 t->sprites.extras[id].rmact = NULL;
3562 } else {
3563 t->sprites.extras[id].rmact = load_sprite(t, pextra->rmact_gfx, TRUE,
3564 TRUE);
3565 if (t->sprites.extras[id].rmact == NULL) {
3566 t->sprites.extras[id].rmact = load_sprite(t, pextra->rmact_gfx_alt,
3567 TRUE, TRUE);
3568 if (t->sprites.extras[id].rmact == NULL) {
3569 tileset_error(LOG_FATAL, _("Missing %s removal activity sprite for tags \"%s\" and alternative \"%s\"."),
3570 extra_rule_name(pextra), pextra->rmact_gfx, pextra->rmact_gfx_alt);
3571 }
3572 }
3573 }
3574 }
3575
3576 /****************************************************************************
3577 Set road sprite values; should only happen after
3578 tilespec_load_tiles().
3579 ****************************************************************************/
tileset_setup_road(struct tileset * t,struct extra_type * pextra)3580 static void tileset_setup_road(struct tileset *t,
3581 struct extra_type *pextra)
3582 {
3583 char full_tag_name[MAX_LEN_NAME + strlen("_isolated")];
3584 char full_alt_name[MAX_LEN_NAME + strlen("_isolated")];
3585 const int id = extra_index(pextra);
3586 int i;
3587 enum extrastyle_id extrastyle = t->sprites.extras[id].extrastyle;
3588
3589 /* Isolated road graphics are used by ESTYLE_ROAD_ALL_SEPARATE and
3590 ESTYLE_ROAD_PARITY_COMBINED. */
3591 if (extrastyle == ESTYLE_ROAD_ALL_SEPARATE
3592 || extrastyle == ESTYLE_ROAD_PARITY_COMBINED) {
3593 fc_snprintf(full_tag_name, sizeof(full_tag_name),
3594 "%s_isolated", pextra->graphic_str);
3595 fc_snprintf(full_alt_name, sizeof(full_alt_name),
3596 "%s_isolated", pextra->graphic_alt);
3597
3598 SET_SPRITE_ALT(extras[id].u.road.isolated, full_tag_name, full_alt_name);
3599 }
3600
3601 if (extrastyle == ESTYLE_ROAD_ALL_SEPARATE) {
3602 /* ESTYLE_ROAD_ALL_SEPARATE has just 8 additional sprites for each road type:
3603 * one going off in each direction. */
3604 for (i = 0; i < t->num_valid_tileset_dirs; i++) {
3605 enum direction8 dir = t->valid_tileset_dirs[i];
3606 const char *dir_name = dir_get_tileset_name(dir);
3607
3608 fc_snprintf(full_tag_name, sizeof(full_tag_name),
3609 "%s_%s", pextra->graphic_str, dir_name);
3610 fc_snprintf(full_alt_name, sizeof(full_alt_name),
3611 "%s_%s", pextra->graphic_alt, dir_name);
3612
3613 SET_SPRITE_ALT(extras[id].u.road.ru.dir[i], full_tag_name, full_alt_name);
3614 }
3615 } else if (extrastyle == ESTYLE_ROAD_PARITY_COMBINED) {
3616 int num_index = 1 << (t->num_valid_tileset_dirs / 2), j;
3617
3618 /* ESTYLE_ROAD_PARITY_COMBINED has 32 additional sprites for each road type:
3619 * 16 each for cardinal and diagonal directions. Each set
3620 * of 16 provides a NSEW-indexed sprite to provide connectors for
3621 * all rails in the cardinal/diagonal directions. The 0 entry is
3622 * unused (the "isolated" sprite is used instead). */
3623
3624 for (i = 1; i < num_index; i++) {
3625 char c[64] = "", d[64] = "";
3626
3627 for (j = 0; j < t->num_valid_tileset_dirs / 2; j++) {
3628 int value = (i >> j) & 1;
3629
3630 cat_snprintf(c, sizeof(c), "%s%d",
3631 dir_get_tileset_name(t->valid_tileset_dirs[2 * j]),
3632 value);
3633 cat_snprintf(d, sizeof(d), "%s%d",
3634 dir_get_tileset_name(t->valid_tileset_dirs[2 * j + 1]),
3635 value);
3636 }
3637
3638 fc_snprintf(full_tag_name, sizeof(full_tag_name),
3639 "%s_c_%s", pextra->graphic_str, c);
3640 fc_snprintf(full_alt_name, sizeof(full_alt_name),
3641 "%s_c_%s", pextra->graphic_alt, c);
3642
3643 SET_SPRITE_ALT(extras[id].u.road.ru.combo.even[i], full_tag_name, full_alt_name);
3644
3645 fc_snprintf(full_tag_name, sizeof(full_tag_name),
3646 "%s_d_%s", pextra->graphic_str, d);
3647 fc_snprintf(full_alt_name, sizeof(full_alt_name),
3648 "%s_d_%s", pextra->graphic_alt, d);
3649
3650 SET_SPRITE_ALT(extras[id].u.road.ru.combo.odd[i], full_tag_name, full_alt_name);
3651 }
3652 } else if (extrastyle == ESTYLE_ROAD_ALL_COMBINED) {
3653 /* ESTYLE_ROAD_ALL_COMBINED includes 256 sprites, one for every possibility.
3654 * Just go around clockwise, with all combinations. */
3655 for (i = 0; i < t->num_index_valid; i++) {
3656 char *idx_str = valid_index_str(t, i);
3657
3658 fc_snprintf(full_tag_name, sizeof(full_tag_name),
3659 "%s_%s", pextra->graphic_str, idx_str);
3660 fc_snprintf(full_alt_name, sizeof(full_alt_name),
3661 "%s_%s", pextra->graphic_alt, idx_str);
3662
3663 SET_SPRITE_ALT(extras[id].u.road.ru.total[i], full_tag_name, full_alt_name);
3664 }
3665 } else if (extrastyle == ESTYLE_RIVER) {
3666 if (!load_river_sprites(t, &t->sprites.extras[id].u.road.ru.rivers,
3667 pextra->graphic_str)) {
3668 if (!load_river_sprites(t, &t->sprites.extras[id].u.road.ru.rivers,
3669 pextra->graphic_alt)) {
3670 tileset_error(LOG_FATAL, _("Cannot load river \"%s\" or \"%s\""),
3671 pextra->graphic_str, pextra->graphic_alt);
3672 }
3673 }
3674 } else {
3675 fc_assert(FALSE);
3676 }
3677
3678 /* Corner road graphics are used by ESTYLE_ROAD_ALL_SEPARATE and
3679 * ESTYLE_ROAD_PARITY_COMBINED. */
3680 if (extrastyle == ESTYLE_ROAD_ALL_SEPARATE
3681 || extrastyle == ESTYLE_ROAD_PARITY_COMBINED) {
3682 for (i = 0; i < t->num_valid_tileset_dirs; i++) {
3683 enum direction8 dir = t->valid_tileset_dirs[i];
3684
3685 if (!is_cardinal_tileset_dir(t, dir)) {
3686 const char *dtn = dir_get_tileset_name(dir);
3687
3688 fc_snprintf(full_tag_name, sizeof(full_tag_name),
3689 "%s_c_%s", pextra->graphic_str, dtn);
3690 fc_snprintf(full_alt_name, sizeof(full_alt_name),
3691 "%s_c_%s", pextra->graphic_alt, dtn);
3692
3693 SET_SPRITE_ALT_OPT(extras[id].u.road.corner[dir], full_tag_name, full_alt_name);
3694 }
3695 }
3696 }
3697 }
3698
3699 /****************************************************************************
3700 Set base sprite values; should only happen after
3701 tilespec_load_tiles().
3702 ****************************************************************************/
tileset_setup_base(struct tileset * t,const struct extra_type * pextra)3703 static void tileset_setup_base(struct tileset *t,
3704 const struct extra_type *pextra)
3705 {
3706 char full_tag_name[MAX_LEN_NAME + strlen("_fg")];
3707 const int id = extra_index(pextra);
3708
3709 fc_assert_ret(id >= 0 && id < extra_count());
3710
3711 sz_strlcpy(full_tag_name, pextra->graphic_str);
3712 strcat(full_tag_name, "_bg");
3713 t->sprites.extras[id].u.bmf.background = load_sprite(t, full_tag_name,
3714 TRUE, TRUE);
3715
3716 sz_strlcpy(full_tag_name, pextra->graphic_str);
3717 strcat(full_tag_name, "_mg");
3718 t->sprites.extras[id].u.bmf.middleground = load_sprite(t, full_tag_name,
3719 TRUE, TRUE);
3720
3721 sz_strlcpy(full_tag_name, pextra->graphic_str);
3722 strcat(full_tag_name, "_fg");
3723 t->sprites.extras[id].u.bmf.foreground = load_sprite(t, full_tag_name,
3724 TRUE, TRUE);
3725
3726 if (t->sprites.extras[id].u.bmf.background == NULL
3727 && t->sprites.extras[id].u.bmf.middleground == NULL
3728 && t->sprites.extras[id].u.bmf.foreground == NULL) {
3729 /* No primary graphics at all. Try alternative */
3730 log_verbose("Using alternate graphic \"%s\" "
3731 "(instead of \"%s\") for extra \"%s\".",
3732 pextra->graphic_alt, pextra->graphic_str,
3733 extra_rule_name(pextra));
3734
3735 sz_strlcpy(full_tag_name, pextra->graphic_alt);
3736 strcat(full_tag_name, "_bg");
3737 t->sprites.extras[id].u.bmf.background = load_sprite(t, full_tag_name,
3738 TRUE, TRUE);
3739
3740 sz_strlcpy(full_tag_name, pextra->graphic_alt);
3741 strcat(full_tag_name, "_mg");
3742 t->sprites.extras[id].u.bmf.middleground = load_sprite(t, full_tag_name,
3743 TRUE, TRUE);
3744
3745 sz_strlcpy(full_tag_name, pextra->graphic_alt);
3746 strcat(full_tag_name, "_fg");
3747 t->sprites.extras[id].u.bmf.foreground = load_sprite(t, full_tag_name,
3748 TRUE, TRUE);
3749
3750 if (t->sprites.extras[id].u.bmf.background == NULL
3751 && t->sprites.extras[id].u.bmf.middleground == NULL
3752 && t->sprites.extras[id].u.bmf.foreground == NULL) {
3753 /* Cannot find alternative graphics either */
3754 tileset_error(LOG_FATAL, _("No graphics for extra \"%s\" at all!"),
3755 extra_rule_name(pextra));
3756 }
3757 }
3758 }
3759
3760 /**********************************************************************
3761 Set tile_type sprite values; should only happen after
3762 tilespec_load_tiles().
3763 ***********************************************************************/
tileset_setup_tile_type(struct tileset * t,const struct terrain * pterrain)3764 void tileset_setup_tile_type(struct tileset *t,
3765 const struct terrain *pterrain)
3766 {
3767 struct drawing_data *draw;
3768 struct sprite *sprite;
3769 char buffer[MAX_LEN_NAME + 20];
3770 int i, l;
3771
3772 if (!drawing_hash_lookup(t->tile_hash, pterrain->graphic_str, &draw)
3773 && !drawing_hash_lookup(t->tile_hash, pterrain->graphic_alt, &draw)) {
3774 tileset_error(LOG_FATAL, _("Terrain \"%s\": no graphic tile \"%s\" or \"%s\"."),
3775 terrain_rule_name(pterrain), pterrain->graphic_str,
3776 pterrain->graphic_alt);
3777 }
3778
3779 if (draw->init) {
3780 t->sprites.drawing[terrain_index(pterrain)] = draw;
3781 return;
3782 }
3783
3784 /* Set up each layer of the drawing. */
3785 for (l = 0; l < draw->num_layers; l++) {
3786 struct drawing_layer *dlp = &draw->layer[l];
3787 struct tileset_layer *tslp = &t->layers[l];
3788 sprite_vector_init(&dlp->base);
3789 sprite_vector_init(&dlp->allocated);
3790
3791 switch (dlp->sprite_type) {
3792 case CELL_WHOLE:
3793 switch (dlp->match_style) {
3794 case MATCH_NONE:
3795 /* Load whole sprites for this tile. */
3796 for (i = 0; ; i++) {
3797 fc_snprintf(buffer, sizeof(buffer), "t.l%d.%s%d",
3798 l, draw->name, i + 1);
3799 sprite = load_sprite(t, buffer, TRUE, FALSE);
3800 if (!sprite) {
3801 break;
3802 }
3803 sprite_vector_reserve(&dlp->base, i + 1);
3804 dlp->base.p[i] = sprite;
3805 }
3806 /* check for base sprite, allowing missing sprites above base */
3807 if (0 == i && 0 == l) {
3808 /* TRANS: 'base' means 'base of terrain gfx', not 'military base' */
3809 tileset_error(LOG_FATAL, _("Missing base sprite for tag \"%s\"."), buffer);
3810 }
3811 break;
3812 case MATCH_SAME:
3813 /* Load 16 cardinally-matched sprites. */
3814 for (i = 0; i < t->num_index_cardinal; i++) {
3815 fc_snprintf(buffer, sizeof(buffer), "t.l%d.%s_%s",
3816 l, draw->name, cardinal_index_str(t, i));
3817 dlp->match[i] =
3818 tiles_lookup_sprite_tag_alt(t, LOG_FATAL, buffer, "",
3819 "matched terrain",
3820 terrain_rule_name(pterrain), TRUE);
3821 }
3822 break;
3823 case MATCH_PAIR:
3824 case MATCH_FULL:
3825 fc_assert(FALSE); /* not yet defined */
3826 break;
3827 };
3828 break;
3829 case CELL_CORNER:
3830 {
3831 const int count = dlp->match_indices;
3832 int number = NUM_CORNER_DIRS;
3833
3834 switch (dlp->match_style) {
3835 case MATCH_NONE:
3836 /* do nothing */
3837 break;
3838 case MATCH_PAIR:
3839 case MATCH_SAME:
3840 /* N directions (NSEW) * 3 dimensions of matching */
3841 fc_assert(count == 2);
3842 number = NUM_CORNER_DIRS * 2 * 2 * 2;
3843 break;
3844 case MATCH_FULL:
3845 default:
3846 /* N directions (NSEW) * 3 dimensions of matching */
3847 /* could use exp() or expi() here? */
3848 number = NUM_CORNER_DIRS * count * count * count;
3849 break;
3850 };
3851
3852 dlp->cells
3853 = fc_calloc(number, sizeof(*dlp->cells));
3854
3855 for (i = 0; i < number; i++) {
3856 enum direction4 dir = i % NUM_CORNER_DIRS;
3857 int value = i / NUM_CORNER_DIRS;
3858
3859 switch (dlp->match_style) {
3860 case MATCH_NONE:
3861 fc_snprintf(buffer, sizeof(buffer), "t.l%d.%s_cell_%c",
3862 l, draw->name, direction4letters[dir]);
3863 dlp->cells[i] =
3864 tiles_lookup_sprite_tag_alt(t, LOG_FATAL, buffer, "",
3865 "cell terrain",
3866 terrain_rule_name(pterrain), TRUE);
3867 break;
3868 case MATCH_SAME:
3869 fc_snprintf(buffer, sizeof(buffer), "t.l%d.%s_cell_%c%d%d%d",
3870 l, draw->name, direction4letters[dir],
3871 (value) & 1, (value >> 1) & 1, (value >> 2) & 1);
3872 dlp->cells[i] =
3873 tiles_lookup_sprite_tag_alt(t, LOG_FATAL, buffer, "",
3874 "same cell terrain",
3875 terrain_rule_name(pterrain), TRUE);
3876 break;
3877 case MATCH_PAIR:
3878 fc_snprintf(buffer, sizeof(buffer), "t.l%d.%s_cell_%c_%c_%c_%c",
3879 l, draw->name, direction4letters[dir],
3880 tslp->match_types[dlp->match_index[(value) & 1]][0],
3881 tslp->match_types[dlp->match_index[(value >> 1) & 1]][0],
3882 tslp->match_types[dlp->match_index[(value >> 2) & 1]][0]);
3883 dlp->cells[i] =
3884 tiles_lookup_sprite_tag_alt(t, LOG_FATAL, buffer, "",
3885 "cell pair terrain",
3886 terrain_rule_name(pterrain), TRUE);
3887 break;
3888 case MATCH_FULL:
3889 {
3890 int this = dlp->match_index[0];
3891 int n, s, e, w;
3892 int v1, v2, v3;
3893
3894 v1 = dlp->match_index[value % count];
3895 value /= count;
3896 v2 = dlp->match_index[value % count];
3897 value /= count;
3898 v3 = dlp->match_index[value % count];
3899
3900 fc_assert(v1 < count && v2 < count && v3 < count);
3901
3902 /* Assume merged cells. This should be a separate option. */
3903 switch (dir) {
3904 case DIR4_NORTH:
3905 s = this;
3906 w = v1;
3907 n = v2;
3908 e = v3;
3909 break;
3910 case DIR4_EAST:
3911 w = this;
3912 n = v1;
3913 e = v2;
3914 s = v3;
3915 break;
3916 case DIR4_SOUTH:
3917 n = this;
3918 e = v1;
3919 s = v2;
3920 w = v3;
3921 break;
3922 case DIR4_WEST:
3923 default: /* avoid warnings */
3924 e = this;
3925 s = v1;
3926 w = v2;
3927 n = v3;
3928 break;
3929 };
3930
3931 /* Use first character of match_types,
3932 * already checked for uniqueness. */
3933 fc_snprintf(buffer, sizeof(buffer),
3934 "t.l%d.cellgroup_%c_%c_%c_%c", l,
3935 tslp->match_types[n][0], tslp->match_types[e][0],
3936 tslp->match_types[s][0], tslp->match_types[w][0]);
3937 sprite = load_sprite(t, buffer, TRUE, FALSE);
3938
3939 if (sprite) {
3940 /* Crop the sprite to separate this cell. */
3941 int vec_size = sprite_vector_size(&dlp->allocated);
3942
3943 const int W = t->normal_tile_width;
3944 const int H = t->normal_tile_height;
3945 int x[4] = {W / 4, W / 4, 0, W / 2};
3946 int y[4] = {H / 2, 0, H / 4, H / 4};
3947 int xo[4] = {0, 0, -W / 2, W / 2};
3948 int yo[4] = {H / 2, -H / 2, 0, 0};
3949
3950 sprite = crop_sprite(sprite, x[dir], y[dir], W / 2, H / 2,
3951 t->sprites.mask.tile, xo[dir], yo[dir], 1.0f,
3952 FALSE);
3953 /* We allocated new sprite with crop_sprite. Store its
3954 * address so we can free it. */
3955 sprite_vector_reserve(&dlp->allocated, vec_size + 1);
3956 dlp->allocated.p[vec_size] = sprite;
3957 } else {
3958 log_error("Terrain graphics sprite for tag \"%s\" missing.", buffer);
3959 }
3960
3961 dlp->cells[i] = sprite;
3962 }
3963 break;
3964 };
3965 }
3966 }
3967 break;
3968 };
3969 }
3970
3971 /* try an optional special name */
3972 fc_snprintf(buffer, sizeof(buffer), "t.blend.%s", draw->name);
3973 draw->blender =
3974 tiles_lookup_sprite_tag_alt(t, LOG_VERBOSE, buffer, "",
3975 "blend terrain",
3976 terrain_rule_name(pterrain), TRUE);
3977
3978 if (draw->blending > 0) {
3979 const int bl = draw->blending - 1;
3980
3981 if (NULL == draw->blender) {
3982 int li = 0;
3983
3984 /* try an already loaded base */
3985 while (NULL == draw->blender
3986 && li < draw->blending
3987 && 0 < draw->layer[li].base.size) {
3988 draw->blender = draw->layer[li++].base.p[0];
3989 }
3990 }
3991
3992 if (NULL == draw->blender) {
3993 /* try an unloaded base name */
3994 fc_snprintf(buffer, sizeof(buffer), "t.l%d.%s1", bl, draw->name);
3995 draw->blender =
3996 tiles_lookup_sprite_tag_alt(t, LOG_FATAL, buffer, "",
3997 "base (blend) terrain",
3998 terrain_rule_name(pterrain), TRUE);
3999 }
4000 }
4001
4002 if (NULL != draw->blender) {
4003 /* Set up blending sprites. This only works in iso-view! */
4004 const int W = t->normal_tile_width;
4005 const int H = t->normal_tile_height;
4006 const int offsets[4][2] = {
4007 {W / 2, 0}, {0, H / 2}, {W / 2, H / 2}, {0, 0}
4008 };
4009 enum direction4 dir = 0;
4010
4011 for (; dir < 4; dir++) {
4012 draw->blend[dir] = crop_sprite(draw->blender, offsets[dir][0],
4013 offsets[dir][1], W / 2, H / 2,
4014 t->sprites.dither_tile, 0, 0, 1.0f,
4015 FALSE);
4016 }
4017 }
4018
4019 draw->init = TRUE;
4020 t->sprites.drawing[terrain_index(pterrain)] = draw;
4021 }
4022
4023 /**********************************************************************
4024 Set government sprite value; should only happen after
4025 tilespec_load_tiles().
4026 ***********************************************************************/
tileset_setup_government(struct tileset * t,struct government * gov)4027 void tileset_setup_government(struct tileset *t,
4028 struct government *gov)
4029 {
4030 t->sprites.government[government_index(gov)] =
4031 tiles_lookup_sprite_tag_alt(t, LOG_FATAL, gov->graphic_str,
4032 gov->graphic_alt, "government",
4033 government_rule_name(gov), FALSE);
4034
4035 /* should probably do something if NULL, eg generic default? */
4036 }
4037
4038 /**********************************************************************
4039 Set nation flag sprite value; should only happen after
4040 tilespec_load_tiles().
4041 ***********************************************************************/
tileset_setup_nation_flag(struct tileset * t,struct nation_type * nation)4042 void tileset_setup_nation_flag(struct tileset *t,
4043 struct nation_type *nation)
4044 {
4045 char *tags[] = {nation->flag_graphic_str,
4046 nation->flag_graphic_alt,
4047 "unknown", NULL};
4048 int i;
4049 struct sprite *flag = NULL, *shield = NULL;
4050 char buf[1024];
4051
4052 for (i = 0; tags[i] && !flag; i++) {
4053 fc_snprintf(buf, sizeof(buf), "f.%s", tags[i]);
4054 flag = load_sprite(t, buf, TRUE, TRUE);
4055 }
4056 for (i = 0; tags[i] && !shield; i++) {
4057 fc_snprintf(buf, sizeof(buf), "f.shield.%s", tags[i]);
4058 shield = load_sprite(t, buf, TRUE, TRUE);
4059 }
4060 if (!flag || !shield) {
4061 /* Should never get here because of the f.unknown fallback. */
4062 tileset_error(LOG_FATAL, _("Nation %s: no national flag."), nation_rule_name(nation));
4063 }
4064
4065 sprite_vector_reserve(&t->sprites.nation_flag, nation_count());
4066 t->sprites.nation_flag.p[nation_index(nation)] = flag;
4067
4068 sprite_vector_reserve(&t->sprites.nation_shield, nation_count());
4069 t->sprites.nation_shield.p[nation_index(nation)] = shield;
4070 }
4071
4072 /**********************************************************************
4073 Return the flag graphic to be used by the city.
4074 ***********************************************************************/
get_city_flag_sprite(const struct tileset * t,const struct city * pcity)4075 struct sprite *get_city_flag_sprite(const struct tileset *t,
4076 const struct city *pcity)
4077 {
4078 return get_nation_flag_sprite(t, nation_of_city(pcity));
4079 }
4080
4081 /**********************************************************************
4082 Return a sprite for the national flag for this unit.
4083 ***********************************************************************/
get_unit_nation_flag_sprite(const struct tileset * t,const struct unit * punit)4084 static struct sprite *get_unit_nation_flag_sprite(const struct tileset *t,
4085 const struct unit *punit)
4086 {
4087 struct nation_type *pnation = nation_of_unit(punit);
4088
4089 if (gui_options.draw_unit_shields) {
4090 return t->sprites.nation_shield.p[nation_index(pnation)];
4091 } else {
4092 return t->sprites.nation_flag.p[nation_index(pnation)];
4093 }
4094 }
4095
4096 #define FULL_TILE_X_OFFSET ((t->normal_tile_width - t->full_tile_width) / 2)
4097 #define FULL_TILE_Y_OFFSET (t->normal_tile_height - t->full_tile_height)
4098
4099 #define ADD_SPRITE(s, draw_fog, x_offset, y_offset) \
4100 (fc_assert(s != NULL), \
4101 sprs->sprite = s, \
4102 sprs->foggable = (draw_fog && t->fogstyle == FOG_AUTO), \
4103 sprs->offset_x = x_offset, \
4104 sprs->offset_y = y_offset, \
4105 sprs++)
4106 #define ADD_SPRITE_SIMPLE(s) ADD_SPRITE(s, TRUE, 0, 0)
4107 #define ADD_SPRITE_FULL(s) \
4108 ADD_SPRITE(s, TRUE, FULL_TILE_X_OFFSET, FULL_TILE_Y_OFFSET)
4109
4110 /**************************************************************************
4111 Assemble some data that is used in building the tile sprite arrays.
4112 (map_x, map_y) : the (normalized) map position
4113 The values we fill in:
4114 tterrain_near : terrain types of all adjacent terrain
4115 tspecial_near : specials of all adjacent terrain
4116 **************************************************************************/
build_tile_data(const struct tile * ptile,struct terrain * pterrain,struct terrain ** tterrain_near,bv_extras * textras_near)4117 static void build_tile_data(const struct tile *ptile,
4118 struct terrain *pterrain,
4119 struct terrain **tterrain_near,
4120 bv_extras *textras_near)
4121 {
4122 enum direction8 dir;
4123
4124 /* Loop over all adjacent tiles. We should have an iterator for this. */
4125 for (dir = 0; dir < 8; dir++) {
4126 struct tile *tile1 = mapstep(ptile, dir);
4127
4128 if (tile1 && client_tile_get_known(tile1) != TILE_UNKNOWN) {
4129 struct terrain *terrain1 = tile_terrain(tile1);
4130
4131 if (NULL != terrain1) {
4132 tterrain_near[dir] = terrain1;
4133 textras_near[dir] = *tile_extras(tile1);
4134 continue;
4135 }
4136 log_error("build_tile_data() tile (%d,%d) has no terrain!",
4137 TILE_XY(tile1));
4138 }
4139 /* At the edges of the (known) map, pretend the same terrain continued
4140 * past the edge of the map. */
4141 tterrain_near[dir] = pterrain;
4142 BV_CLR_ALL(textras_near[dir]);
4143 }
4144 }
4145
4146 /**********************************************************************
4147 Fill in the sprite array for the unit type.
4148 ***********************************************************************/
fill_unit_type_sprite_array(const struct tileset * t,struct drawn_sprite * sprs,const struct unit_type * putype,enum direction8 facing)4149 static int fill_unit_type_sprite_array(const struct tileset *t,
4150 struct drawn_sprite *sprs,
4151 const struct unit_type *putype,
4152 enum direction8 facing)
4153 {
4154 struct drawn_sprite *save_sprs = sprs;
4155 struct sprite *uspr = get_unittype_sprite(t, putype, facing, FALSE);
4156
4157 ADD_SPRITE(uspr, TRUE,
4158 FULL_TILE_X_OFFSET + t->unit_offset_x,
4159 FULL_TILE_Y_OFFSET + t->unit_offset_y);
4160
4161 return sprs - save_sprs;
4162 }
4163
4164 /**********************************************************************
4165 Fill in the sprite array for the unit.
4166 ***********************************************************************/
fill_unit_sprite_array(const struct tileset * t,struct drawn_sprite * sprs,const struct unit * punit,bool stack,bool backdrop)4167 static int fill_unit_sprite_array(const struct tileset *t,
4168 struct drawn_sprite *sprs,
4169 const struct unit *punit,
4170 bool stack, bool backdrop)
4171 {
4172 struct drawn_sprite *save_sprs = sprs;
4173 int ihp;
4174 struct unit_type *ptype = unit_type_get(punit);
4175
4176 if (backdrop) {
4177 if (!gui_options.solid_color_behind_units) {
4178 ADD_SPRITE(get_unit_nation_flag_sprite(t, punit), TRUE,
4179 FULL_TILE_X_OFFSET + t->unit_flag_offset_x,
4180 FULL_TILE_Y_OFFSET + t->unit_flag_offset_y);
4181 } else {
4182 /* Taken care of in the LAYER_BACKGROUND. */
4183 }
4184 }
4185
4186 /* Add the sprite for the unit type. */
4187 sprs += fill_unit_type_sprite_array(t, sprs, ptype,
4188 punit->facing);
4189
4190 if (t->sprites.unit.loaded && unit_transported(punit)) {
4191 ADD_SPRITE_FULL(t->sprites.unit.loaded);
4192 }
4193
4194 if (punit->activity != ACTIVITY_IDLE) {
4195 struct sprite *s = NULL;
4196
4197 switch (punit->activity) {
4198 case ACTIVITY_MINE:
4199 if (punit->activity_target == NULL) {
4200 s = t->sprites.unit.plant;
4201 } else {
4202 s = t->sprites.extras[extra_index(punit->activity_target)].activity;
4203 }
4204 break;
4205 case ACTIVITY_IRRIGATE:
4206 if (punit->activity_target == NULL) {
4207 s = t->sprites.unit.irrigate;
4208 } else {
4209 s = t->sprites.extras[extra_index(punit->activity_target)].activity;
4210 }
4211 break;
4212 case ACTIVITY_POLLUTION:
4213 case ACTIVITY_FALLOUT:
4214 s = t->sprites.extras[extra_index(punit->activity_target)].rmact;
4215 break;
4216 case ACTIVITY_PILLAGE:
4217 s = t->sprites.unit.pillage;
4218 break;
4219 case ACTIVITY_EXPLORE:
4220 s = t->sprites.unit.auto_explore;
4221 break;
4222 case ACTIVITY_FORTIFIED:
4223 s = t->sprites.unit.fortified;
4224 break;
4225 case ACTIVITY_FORTIFYING:
4226 s = t->sprites.unit.fortifying;
4227 break;
4228 case ACTIVITY_SENTRY:
4229 s = t->sprites.unit.sentry;
4230 break;
4231 case ACTIVITY_GOTO:
4232 s = t->sprites.unit.go_to;
4233 break;
4234 case ACTIVITY_TRANSFORM:
4235 s = t->sprites.unit.transform;
4236 break;
4237 case ACTIVITY_BASE:
4238 case ACTIVITY_GEN_ROAD:
4239 s = t->sprites.extras[extra_index(punit->activity_target)].activity;
4240 break;
4241 case ACTIVITY_CONVERT:
4242 s = t->sprites.unit.convert;
4243 break;
4244 default:
4245 break;
4246 }
4247
4248 if (s != NULL) {
4249 ADD_SPRITE(s, TRUE, FULL_TILE_X_OFFSET + t->activity_offset_x,
4250 FULL_TILE_Y_OFFSET + t->activity_offset_y);
4251 }
4252 }
4253
4254 if (punit->ai_controlled && punit->activity != ACTIVITY_EXPLORE) {
4255 if (is_military_unit(punit)) {
4256 ADD_SPRITE_FULL(t->sprites.unit.auto_attack);
4257 } else {
4258 ADD_SPRITE_FULL(t->sprites.unit.auto_settler);
4259 }
4260 }
4261
4262 if (unit_has_orders(punit)) {
4263 if (punit->orders.repeat) {
4264 ADD_SPRITE_FULL(t->sprites.unit.patrol);
4265 } else if (punit->activity != ACTIVITY_IDLE) {
4266 ADD_SPRITE_SIMPLE(t->sprites.unit.connect);
4267 } else {
4268 ADD_SPRITE(t->sprites.unit.go_to, TRUE, FULL_TILE_X_OFFSET + t->activity_offset_x,
4269 FULL_TILE_Y_OFFSET + t->activity_offset_y);
4270 }
4271 }
4272
4273 if (punit->battlegroup != BATTLEGROUP_NONE) {
4274 ADD_SPRITE_FULL(t->sprites.unit.battlegroup[punit->battlegroup]);
4275 }
4276
4277 if (t->sprites.unit.lowfuel
4278 && utype_fuel(ptype)
4279 && punit->fuel == 1
4280 && punit->moves_left <= 2 * SINGLE_MOVE) {
4281 /* Show a low-fuel graphic if the plane has 2 or fewer moves left. */
4282 ADD_SPRITE_FULL(t->sprites.unit.lowfuel);
4283 }
4284 if (t->sprites.unit.tired
4285 && punit->moves_left < SINGLE_MOVE
4286 && ptype->move_rate > 0) {
4287 /* Show a "tired" graphic if the unit has fewer than one move
4288 * remaining, except for units for which it's full movement. */
4289 ADD_SPRITE_FULL(t->sprites.unit.tired);
4290 }
4291
4292 if (stack || punit->client.occupied) {
4293 ADD_SPRITE_FULL(t->sprites.unit.stack);
4294 }
4295
4296 if (t->sprites.unit.vet_lev[punit->veteran]) {
4297 ADD_SPRITE_FULL(t->sprites.unit.vet_lev[punit->veteran]);
4298 }
4299
4300 ihp = ((NUM_TILES_HP_BAR-1)*punit->hp) / ptype->hp;
4301 ihp = CLIP(0, ihp, NUM_TILES_HP_BAR-1);
4302 ADD_SPRITE_FULL(t->sprites.unit.hp_bar[ihp]);
4303
4304 return sprs - save_sprs;
4305 }
4306
4307 /**************************************************************************
4308 Add any corner road sprites to the sprite array.
4309 **************************************************************************/
fill_road_corner_sprites(const struct tileset * t,const struct extra_type * pextra,struct drawn_sprite * sprs,bool road,bool * road_near,bool hider,bool * hider_near)4310 static int fill_road_corner_sprites(const struct tileset *t,
4311 const struct extra_type *pextra,
4312 struct drawn_sprite *sprs,
4313 bool road, bool *road_near,
4314 bool hider, bool *hider_near)
4315 {
4316 struct drawn_sprite *saved_sprs = sprs;
4317 int i;
4318 int extra_idx = extra_index(pextra);
4319
4320 if (is_cardinal_only_road(pextra)) {
4321 return 0;
4322 }
4323
4324 /* Roads going diagonally adjacent to this tile need to be
4325 * partly drawn on this tile. */
4326
4327 /* Draw the corner sprite if:
4328 * - There is a diagonal road (not rail!) between two adjacent tiles.
4329 * - There is no diagonal road (not rail!) that intersects this road.
4330 * The logic is simple: roads are drawn underneath railrods, but are
4331 * not always covered by them (even in the corners!). But if a railroad
4332 * connects two tiles, only the railroad (no road) is drawn between
4333 * those tiles.
4334 */
4335 for (i = 0; i < t->num_valid_tileset_dirs; i++) {
4336 enum direction8 dir = t->valid_tileset_dirs[i];
4337
4338 if (!is_cardinal_tileset_dir(t, dir)) {
4339 /* Draw corner sprites for this non-cardinal direction. */
4340 int cw = (i + 1) % t->num_valid_tileset_dirs;
4341 int ccw
4342 = (i + t->num_valid_tileset_dirs - 1) % t->num_valid_tileset_dirs;
4343 enum direction8 cwdir = t->valid_tileset_dirs[cw];
4344 enum direction8 ccwdir = t->valid_tileset_dirs[ccw];
4345
4346 if (t->sprites.extras[extra_idx].u.road.corner[dir]
4347 && (road_near[cwdir] && road_near[ccwdir]
4348 && !(hider_near[cwdir] && hider_near[ccwdir]))
4349 && !(road && road_near[dir] && !(hider && hider_near[dir]))) {
4350 ADD_SPRITE_SIMPLE(t->sprites.extras[extra_idx].u.road.corner[dir]);
4351 }
4352 }
4353 }
4354
4355 return sprs - saved_sprs;
4356 }
4357
4358 /**************************************************************************
4359 Fill all road and rail sprites into the sprite array.
4360 **************************************************************************/
fill_road_sprite_array(const struct tileset * t,const struct extra_type * pextra,struct drawn_sprite * sprs,bv_extras textras,bv_extras * textras_near,struct terrain * tterrain_near[8],const struct city * pcity)4361 static int fill_road_sprite_array(const struct tileset *t,
4362 const struct extra_type *pextra,
4363 struct drawn_sprite *sprs,
4364 bv_extras textras,
4365 bv_extras *textras_near,
4366 struct terrain *tterrain_near[8],
4367 const struct city *pcity)
4368 {
4369 struct drawn_sprite *saved_sprs = sprs;
4370 bool road, road_near[8], hider, hider_near[8];
4371 bool land_near[8], hland_near[8];
4372 bool draw_road[8], draw_single_road;
4373 enum direction8 dir;
4374 int extra_idx = -1;
4375 bool cl = FALSE;
4376 enum extrastyle_id extrastyle;
4377 const struct road_type *proad = extra_road_get(pextra);
4378
4379 extra_idx = extra_index(pextra);
4380
4381 extrastyle = t->sprites.extras[extra_idx].extrastyle;
4382
4383 if (extra_has_flag(pextra, EF_CONNECT_LAND)) {
4384 cl = TRUE;
4385 } else {
4386 int i;
4387
4388 for (i = 0; i < 8; i++) {
4389 land_near[i] = FALSE;
4390 }
4391 }
4392
4393 /* Fill some data arrays. rail_near and road_near store whether road/rail
4394 * is present in the given direction. draw_rail and draw_road store
4395 * whether road/rail is to be drawn in that direction. draw_single_road
4396 * and draw_single_rail store whether we need an isolated road/rail to be
4397 * drawn. */
4398 road = BV_ISSET(textras, extra_idx);
4399
4400 hider = FALSE;
4401 extra_type_list_iterate(pextra->hiders, phider) {
4402 if (BV_ISSET(textras, extra_index(phider))) {
4403 hider = TRUE;
4404 break;
4405 }
4406 } extra_type_list_iterate_end;
4407
4408 if (road && (!pcity || !gui_options.draw_cities) && !hider) {
4409 draw_single_road = TRUE;
4410 } else {
4411 draw_single_road = FALSE;
4412 }
4413
4414 for (dir = 0; dir < 8; dir++) {
4415 bool roads_exist;
4416
4417 /* Check if there is adjacent road/rail. */
4418 if (!is_cardinal_only_road(pextra)
4419 || is_cardinal_tileset_dir(t, dir)) {
4420 road_near[dir] = FALSE;
4421 extra_type_list_iterate(proad->integrators, iextra) {
4422 if (BV_ISSET(textras_near[dir], extra_index(iextra))) {
4423 road_near[dir] = TRUE;
4424 break;
4425 }
4426 } extra_type_list_iterate_end;
4427 if (cl) {
4428 land_near[dir] = (tterrain_near[dir] != T_UNKNOWN
4429 && terrain_type_terrain_class(tterrain_near[dir]) != TC_OCEAN);
4430 }
4431 } else {
4432 road_near[dir] = FALSE;
4433 land_near[dir] = FALSE;
4434 }
4435
4436 /* Draw rail/road if there is a connection from this tile to the
4437 * adjacent tile. But don't draw road if there is also a rail
4438 * connection. */
4439 roads_exist = road && (road_near[dir] || land_near[dir]);
4440 draw_road[dir] = roads_exist;
4441 hider_near[dir] = FALSE;
4442 hland_near[dir] = tterrain_near[dir] != T_UNKNOWN
4443 && terrain_type_terrain_class(tterrain_near[dir]) != TC_OCEAN;
4444 extra_type_list_iterate(pextra->hiders, phider) {
4445 bool hider_dir = FALSE;
4446 bool land_dir = FALSE;
4447
4448 if (!is_cardinal_only_road(phider)
4449 || is_cardinal_tileset_dir(t, dir)) {
4450 if (BV_ISSET(textras_near[dir], extra_index(phider))) {
4451 hider_near[dir] = TRUE;
4452 hider_dir = TRUE;
4453 }
4454 if (hland_near[dir]
4455 && is_extra_caused_by(phider, EC_ROAD)
4456 && extra_has_flag(phider, EF_CONNECT_LAND)) {
4457 land_dir = TRUE;
4458 }
4459 if (hider_dir || land_dir) {
4460 if (BV_ISSET(textras, extra_index(phider))) {
4461 draw_road[dir] = FALSE;
4462 }
4463 }
4464 }
4465 } extra_type_list_iterate_end;
4466
4467 /* Don't draw an isolated road/rail if there's any connection.
4468 * draw_single_road would be true in the first place only if start tile has road,
4469 * so it will have road connection with any adjacent road tile. We check from real
4470 * existence of road (road_near[dir]) and not from whether road gets drawn (draw_road[dir])
4471 * as latter can be FALSE when road is simply hidden by another one, and we don't want to
4472 * draw single road in that case either. */
4473 if (draw_single_road && road_near[dir]) {
4474 draw_single_road = FALSE;
4475 }
4476 }
4477
4478 /* Draw road corners */
4479 sprs
4480 += fill_road_corner_sprites(t, pextra, sprs, road, road_near, hider, hider_near);
4481
4482 if (extrastyle == ESTYLE_ROAD_ALL_SEPARATE) {
4483 /* With ESTYLE_ROAD_ALL_SEPARATE, we simply draw one road for every connection.
4484 * This means we only need a few sprites, but a lot of drawing is
4485 * necessary and it generally doesn't look very good. */
4486 int i;
4487
4488 /* First draw roads under rails. */
4489 if (road) {
4490 for (i = 0; i < t->num_valid_tileset_dirs; i++) {
4491 if (draw_road[t->valid_tileset_dirs[i]]) {
4492 ADD_SPRITE_SIMPLE(t->sprites.extras[extra_idx].u.road.ru.dir[i]);
4493 }
4494 }
4495 }
4496 } else if (extrastyle == ESTYLE_ROAD_PARITY_COMBINED) {
4497 /* With ESTYLE_ROAD_PARITY_COMBINED, we draw one sprite for cardinal
4498 * road connections, one sprite for diagonal road connections.
4499 * This means we need about 4x more sprites than in style 0, but up to
4500 * 4x less drawing is needed. The drawing quality may also be
4501 * improved. */
4502
4503 /* First draw roads under rails. */
4504 if (road) {
4505 int road_even_tileno = 0, road_odd_tileno = 0, i;
4506
4507 for (i = 0; i < t->num_valid_tileset_dirs / 2; i++) {
4508 enum direction8 even = t->valid_tileset_dirs[2 * i];
4509 enum direction8 odd = t->valid_tileset_dirs[2 * i + 1];
4510
4511 if (draw_road[even]) {
4512 road_even_tileno |= 1 << i;
4513 }
4514 if (draw_road[odd]) {
4515 road_odd_tileno |= 1 << i;
4516 }
4517 }
4518
4519 /* Draw the cardinal/even roads first. */
4520 if (road_even_tileno != 0) {
4521 ADD_SPRITE_SIMPLE(t->sprites.extras[extra_idx].u.road.ru.combo.even[road_even_tileno]);
4522 }
4523 if (road_odd_tileno != 0) {
4524 ADD_SPRITE_SIMPLE(t->sprites.extras[extra_idx].u.road.ru.combo.odd[road_odd_tileno]);
4525 }
4526 }
4527 } else if (extrastyle == ESTYLE_ROAD_ALL_COMBINED) {
4528 /* RSTYLE_ALL_COMBINED is a very simple method that lets us simply retrieve
4529 * entire finished tiles, with a bitwise index of the presence of
4530 * roads in each direction. */
4531
4532 /* Draw roads first */
4533 if (road) {
4534 int road_tileno = 0, i;
4535
4536 for (i = 0; i < t->num_valid_tileset_dirs; i++) {
4537 enum direction8 vdir = t->valid_tileset_dirs[i];
4538
4539 if (draw_road[vdir]) {
4540 road_tileno |= 1 << i;
4541 }
4542 }
4543
4544 if (road_tileno != 0 || draw_single_road) {
4545 ADD_SPRITE_SIMPLE(t->sprites.extras[extra_idx].u.road.ru.total[road_tileno]);
4546 }
4547 }
4548 } else {
4549 fc_assert(FALSE);
4550 }
4551
4552 /* Draw isolated rail/road separately (ESTYLE_ROAD_ALL_SEPARATE and
4553 ESTYLE_ROAD_PARITY_COMBINED only). */
4554 if (extrastyle == ESTYLE_ROAD_ALL_SEPARATE
4555 || extrastyle == ESTYLE_ROAD_PARITY_COMBINED) {
4556 if (draw_single_road) {
4557 ADD_SPRITE_SIMPLE(t->sprites.extras[extra_idx].u.road.isolated);
4558 }
4559 }
4560
4561 return sprs - saved_sprs;
4562 }
4563
4564 /**************************************************************************
4565 Return the index of the sprite to be used for irrigation or farmland in
4566 this tile.
4567
4568 We assume that the current tile has farmland or irrigation. We then
4569 choose a sprite (index) based upon which cardinally adjacent tiles have
4570 either farmland or irrigation (the two are considered interchangable for
4571 this).
4572 **************************************************************************/
get_irrigation_index(const struct tileset * t,struct extra_type * pextra,bv_extras * textras_near)4573 static int get_irrigation_index(const struct tileset *t,
4574 struct extra_type *pextra,
4575 bv_extras *textras_near)
4576 {
4577 int tileno = 0, i;
4578
4579 for (i = 0; i < t->num_cardinal_tileset_dirs; i++) {
4580 enum direction8 dir = t->cardinal_tileset_dirs[i];
4581
4582 if (BV_ISSET(textras_near[dir], extra_index(pextra))) {
4583 tileno |= 1 << i;
4584 }
4585 }
4586
4587 return tileno;
4588 }
4589
4590 /**************************************************************************
4591 Fill in the farmland/irrigation sprite for the tile.
4592 **************************************************************************/
fill_irrigation_sprite_array(const struct tileset * t,struct drawn_sprite * sprs,bv_extras textras,bv_extras * textras_near,const struct city * pcity)4593 static int fill_irrigation_sprite_array(const struct tileset *t,
4594 struct drawn_sprite *sprs,
4595 bv_extras textras,
4596 bv_extras *textras_near,
4597 const struct city *pcity)
4598 {
4599 struct drawn_sprite *saved_sprs = sprs;
4600
4601 /* We don't draw the irrigation if there's a city (it just gets overdrawn
4602 * anyway, and ends up looking bad). */
4603 if (!(pcity && gui_options.draw_cities)) {
4604 extra_type_list_iterate(t->style_lists[ESTYLE_CARDINALS], pextra) {
4605 if (is_extra_drawing_enabled(pextra)) {
4606 int eidx = extra_index(pextra);
4607
4608 if (BV_ISSET(textras, eidx)) {
4609 bool hidden = FALSE;
4610
4611 extra_type_list_iterate(pextra->hiders, phider) {
4612 if (BV_ISSET(textras, extra_index(phider))) {
4613 hidden = TRUE;
4614 break;
4615 }
4616 } extra_type_list_iterate_end;
4617
4618 if (!hidden) {
4619 int idx = get_irrigation_index(t, pextra, textras_near);
4620
4621 ADD_SPRITE_SIMPLE(t->sprites.extras[eidx].u.cardinals[idx]);
4622 }
4623 }
4624 }
4625 } extra_type_list_iterate_end;
4626 }
4627
4628 return sprs - saved_sprs;
4629 }
4630
4631 /**************************************************************************
4632 Fill in the city overlays for the tile. This includes the citymap
4633 overlays on the mapview as well as the tile output sprites.
4634 **************************************************************************/
fill_city_overlays_sprite_array(const struct tileset * t,struct drawn_sprite * sprs,const struct tile * ptile,const struct city * citymode)4635 static int fill_city_overlays_sprite_array(const struct tileset *t,
4636 struct drawn_sprite *sprs,
4637 const struct tile *ptile,
4638 const struct city *citymode)
4639 {
4640 const struct city *pcity;
4641 const struct city *pwork;
4642 struct unit *psettler;
4643 struct drawn_sprite *saved_sprs = sprs;
4644 int city_x, city_y;
4645 const int NUM_CITY_COLORS = t->sprites.city.worked_tile_overlay.size;
4646
4647 if (NULL == ptile || TILE_UNKNOWN == client_tile_get_known(ptile)) {
4648 return 0;
4649 }
4650 pwork = tile_worked(ptile);
4651
4652 if (citymode) {
4653 pcity = citymode;
4654 } else {
4655 pcity = find_city_or_settler_near_tile(ptile, &psettler);
4656 }
4657
4658 /* Below code does not work if pcity is invisible.
4659 * Make sure it is not. */
4660 fc_assert_ret_val(pcity == NULL || pcity->tile != NULL, 0);
4661 if (pcity && !pcity->tile) {
4662 pcity = NULL;
4663 }
4664
4665 if (pcity && city_base_to_city_map(&city_x, &city_y, pcity, ptile)) {
4666 /* FIXME: check elsewhere for valid tile (instead of above) */
4667
4668 if (!citymode && pcity->client.colored) {
4669 /* Add citymap overlay for a city. */
4670 int idx = pcity->client.color_index % NUM_CITY_COLORS;
4671
4672 if (NULL != pwork && pwork == pcity) {
4673 ADD_SPRITE_SIMPLE(t->sprites.city.worked_tile_overlay.p[idx]);
4674 } else if (city_can_work_tile(pcity, ptile)) {
4675 ADD_SPRITE_SIMPLE(t->sprites.city.unworked_tile_overlay.p[idx]);
4676 }
4677 } else if (NULL != pwork && pwork == pcity
4678 && (citymode || gui_options.draw_city_output)) {
4679
4680 /* Add on the tile output sprites.
4681 * NOTE: To show correct output on end of turn
4682 * base_city_celebrating() must be used instead of city_celebrating()
4683 * mirroring the behavior of the server that does so in
4684 * city_tile_cache_update(). */
4685 bool celebrating = base_city_celebrating(pcity);
4686 int food = city_tile_output(pcity, ptile, celebrating, O_FOOD);
4687 int shields = city_tile_output(pcity, ptile, celebrating, O_SHIELD);
4688 int trade = city_tile_output(pcity, ptile, celebrating, O_TRADE);
4689
4690 const int ox = t->type == TS_ISOMETRIC ? t->normal_tile_width / 3 : 0;
4691 const int oy = t->type == TS_ISOMETRIC ? -t->normal_tile_height / 3 : 0;
4692
4693 food = CLIP(0, food, NUM_TILES_DIGITS - 1);
4694 shields = CLIP(0, shields, NUM_TILES_DIGITS - 1);
4695 trade = CLIP(0, trade, NUM_TILES_DIGITS - 1);
4696
4697 ADD_SPRITE(t->sprites.city.tile_foodnum[food], TRUE, ox, oy);
4698 ADD_SPRITE(t->sprites.city.tile_shieldnum[shields], TRUE, ox, oy);
4699 ADD_SPRITE(t->sprites.city.tile_tradenum[trade], TRUE, ox, oy);
4700 }
4701 } else if (psettler && psettler->client.colored) {
4702 /* Add citymap overlay for a unit. */
4703 int idx = psettler->client.color_index % NUM_CITY_COLORS;
4704
4705 ADD_SPRITE_SIMPLE(t->sprites.city.unworked_tile_overlay.p[idx]);
4706 }
4707
4708 return sprs - saved_sprs;
4709 }
4710
4711 /****************************************************************************
4712 Helper function for fill_terrain_sprite_layer.
4713 Fill in the sprite array for blended terrain.
4714 ****************************************************************************/
fill_terrain_sprite_blending(const struct tileset * t,struct drawn_sprite * sprs,const struct tile * ptile,const struct terrain * pterrain,struct terrain ** tterrain_near)4715 static int fill_terrain_sprite_blending(const struct tileset *t,
4716 struct drawn_sprite *sprs,
4717 const struct tile *ptile,
4718 const struct terrain *pterrain,
4719 struct terrain **tterrain_near)
4720 {
4721 struct drawn_sprite *saved_sprs = sprs;
4722 const int W = t->normal_tile_width, H = t->normal_tile_height;
4723 const int offsets[4][2] = {
4724 {W/2, 0}, {0, H / 2}, {W / 2, H / 2}, {0, 0}
4725 };
4726 enum direction4 dir = 0;
4727
4728 /*
4729 * We want to mark unknown tiles so that an unreal tile will be
4730 * given the same marking as our current tile - that way we won't
4731 * get the "unknown" dither along the edge of the map.
4732 */
4733 for (; dir < 4; dir++) {
4734 struct tile *tile1 = mapstep(ptile, DIR4_TO_DIR8[dir]);
4735 struct terrain *other;
4736
4737 if (!tile1
4738 || client_tile_get_known(tile1) == TILE_UNKNOWN
4739 || pterrain == (other = tterrain_near[DIR4_TO_DIR8[dir]])
4740 || (0 == t->sprites.drawing[terrain_index(other)]->blending
4741 && NULL == t->sprites.drawing[terrain_index(other)]->blender)) {
4742 continue;
4743 }
4744
4745 ADD_SPRITE(t->sprites.drawing[terrain_index(other)]->blend[dir], TRUE,
4746 offsets[dir][0], offsets[dir][1]);
4747 }
4748
4749 return sprs - saved_sprs;
4750 }
4751
4752 /****************************************************************************
4753 Add sprites for fog (and some forms of darkness).
4754 ****************************************************************************/
fill_fog_sprite_array(const struct tileset * t,struct drawn_sprite * sprs,const struct tile * ptile,const struct tile_edge * pedge,const struct tile_corner * pcorner)4755 static int fill_fog_sprite_array(const struct tileset *t,
4756 struct drawn_sprite *sprs,
4757 const struct tile *ptile,
4758 const struct tile_edge *pedge,
4759 const struct tile_corner *pcorner)
4760 {
4761 struct drawn_sprite *saved_sprs = sprs;
4762
4763 if (t->fogstyle == FOG_SPRITE && gui_options.draw_fog_of_war
4764 && NULL != ptile
4765 && TILE_KNOWN_UNSEEN == client_tile_get_known(ptile)) {
4766 /* With FOG_AUTO, fog is done this way. */
4767 ADD_SPRITE_SIMPLE(t->sprites.tx.fog);
4768 }
4769
4770 if (t->darkness_style == DARKNESS_CORNER && pcorner
4771 && gui_options.draw_fog_of_war) {
4772 int i, tileno = 0;
4773
4774 for (i = 3; i >= 0; i--) {
4775 const int unknown = 0, fogged = 1, known = 2;
4776 int value = -1;
4777
4778 if (!pcorner->tile[i]) {
4779 value = fogged;
4780 } else {
4781 switch (client_tile_get_known(pcorner->tile[i])) {
4782 case TILE_KNOWN_SEEN:
4783 value = known;
4784 break;
4785 case TILE_KNOWN_UNSEEN:
4786 value = fogged;
4787 break;
4788 case TILE_UNKNOWN:
4789 value = unknown;
4790 break;
4791 }
4792 }
4793 fc_assert(value >= 0 && value < 3);
4794
4795 tileno = tileno * 3 + value;
4796 }
4797
4798 if (t->sprites.tx.fullfog[tileno]) {
4799 ADD_SPRITE_SIMPLE(t->sprites.tx.fullfog[tileno]);
4800 }
4801 }
4802
4803 return sprs - saved_sprs;
4804 }
4805
4806 /****************************************************************************
4807 Helper function for fill_terrain_sprite_layer.
4808 ****************************************************************************/
fill_terrain_sprite_array(struct tileset * t,struct drawn_sprite * sprs,int l,const struct tile * ptile,const struct terrain * pterrain,struct terrain ** tterrain_near,struct drawing_data * draw)4809 static int fill_terrain_sprite_array(struct tileset *t,
4810 struct drawn_sprite *sprs,
4811 int l, /* layer_num */
4812 const struct tile *ptile,
4813 const struct terrain *pterrain,
4814 struct terrain **tterrain_near,
4815 struct drawing_data *draw)
4816 {
4817 struct drawn_sprite *saved_sprs = sprs;
4818 struct drawing_layer *dlp = &draw->layer[l];
4819 int this = dlp->match_index[0];
4820 int that = dlp->match_index[1];
4821 int ox = dlp->offset_x;
4822 int oy = dlp->offset_y;
4823 int i;
4824
4825 #define MATCH(dir) \
4826 (t->sprites.drawing[terrain_index(tterrain_near[(dir)])]->num_layers > l \
4827 ? t->sprites.drawing[terrain_index(tterrain_near[(dir)])]->layer[l].match_index[0] \
4828 : -1)
4829
4830 switch (dlp->sprite_type) {
4831 case CELL_WHOLE:
4832 {
4833 switch (dlp->match_style) {
4834 case MATCH_NONE:
4835 {
4836 int count = sprite_vector_size(&dlp->base);
4837
4838 if (count > 0) {
4839 /* Pseudo-random reproducable algorithm to pick a sprite. Use modulo
4840 * to limit the number to a handleable size [0..32000). */
4841 count = fc_randomly(tile_index(ptile) % 32000, count);
4842
4843 if (dlp->is_tall) {
4844 ox += FULL_TILE_X_OFFSET;
4845 oy += FULL_TILE_Y_OFFSET;
4846 }
4847 ADD_SPRITE(dlp->base.p[count], TRUE, ox, oy);
4848 }
4849 break;
4850 }
4851 case MATCH_SAME:
4852 {
4853 int tileno = 0;
4854
4855 for (i = 0; i < t->num_cardinal_tileset_dirs; i++) {
4856 enum direction8 dir = t->cardinal_tileset_dirs[i];
4857
4858 if (MATCH(dir) == this) {
4859 tileno |= 1 << i;
4860 }
4861 }
4862
4863 if (dlp->is_tall) {
4864 ox += FULL_TILE_X_OFFSET;
4865 oy += FULL_TILE_Y_OFFSET;
4866 }
4867 ADD_SPRITE(dlp->match[tileno], TRUE, ox, oy);
4868 break;
4869 }
4870 case MATCH_PAIR:
4871 case MATCH_FULL:
4872 fc_assert(FALSE); /* not yet defined */
4873 break;
4874 };
4875 break;
4876 }
4877 case CELL_CORNER:
4878 {
4879 /* Divide the tile up into four rectangular cells. Each of these
4880 * cells covers one corner, and each is adjacent to 3 different
4881 * tiles. For each cell we pick a sprite based upon the adjacent
4882 * terrains at each of those tiles. Thus, we have 8 different sprites
4883 * for each of the 4 cells (32 sprites total).
4884 *
4885 * These arrays correspond to the direction4 ordering. */
4886 const int W = t->normal_tile_width;
4887 const int H = t->normal_tile_height;
4888 const int iso_offsets[4][2] = {
4889 {W / 4, 0}, {W / 4, H / 2}, {W / 2, H / 4}, {0, H / 4}
4890 };
4891 const int noniso_offsets[4][2] = {
4892 {0, 0}, {W / 2, H / 2}, {W / 2, 0}, {0, H / 2}
4893 };
4894
4895 /* put corner cells */
4896 for (i = 0; i < NUM_CORNER_DIRS; i++) {
4897 const int count = dlp->match_indices;
4898 int array_index = 0;
4899 enum direction8 dir = dir_ccw(DIR4_TO_DIR8[i]);
4900 int x = (t->type == TS_ISOMETRIC ? iso_offsets[i][0] : noniso_offsets[i][0]);
4901 int y = (t->type == TS_ISOMETRIC ? iso_offsets[i][1] : noniso_offsets[i][1]);
4902 int m[3] = {MATCH(dir_ccw(dir)), MATCH(dir), MATCH(dir_cw(dir))};
4903 struct sprite *s;
4904
4905 /* synthesize 4 dimensional array? */
4906 switch (dlp->match_style) {
4907 case MATCH_NONE:
4908 /* We have no need for matching, just plug the piece in place. */
4909 break;
4910 case MATCH_SAME:
4911 array_index = array_index * 2 + (m[2] != this);
4912 array_index = array_index * 2 + (m[1] != this);
4913 array_index = array_index * 2 + (m[0] != this);
4914 break;
4915 case MATCH_PAIR:
4916 array_index = array_index * 2 + (m[2] == that);
4917 array_index = array_index * 2 + (m[1] == that);
4918 array_index = array_index * 2 + (m[0] == that);
4919 break;
4920 case MATCH_FULL:
4921 default:
4922 {
4923 int n[3];
4924 int j = 0;
4925 for (; j < 3; j++) {
4926 int k = 0;
4927 for (; k < count; k++) {
4928 n[j] = k; /* default to last entry */
4929 if (m[j] == dlp->match_index[k])
4930 {
4931 break;
4932 }
4933 }
4934 }
4935 array_index = array_index * count + n[2];
4936 array_index = array_index * count + n[1];
4937 array_index = array_index * count + n[0];
4938 }
4939 break;
4940 };
4941 array_index = array_index * NUM_CORNER_DIRS + i;
4942
4943 s = dlp->cells[array_index];
4944 if (s) {
4945 ADD_SPRITE(s, TRUE, x, y);
4946 }
4947 }
4948 break;
4949 }
4950 };
4951 #undef MATCH
4952
4953 return sprs - saved_sprs;
4954 }
4955
4956 /****************************************************************************
4957 Helper function for fill_terrain_sprite_layer.
4958 Fill in the sprite array of darkness.
4959 ****************************************************************************/
fill_terrain_sprite_darkness(struct tileset * t,struct drawn_sprite * sprs,const struct tile * ptile,struct terrain ** tterrain_near)4960 static int fill_terrain_sprite_darkness(struct tileset *t,
4961 struct drawn_sprite *sprs,
4962 const struct tile *ptile,
4963 struct terrain **tterrain_near)
4964 {
4965 struct drawn_sprite *saved_sprs = sprs;
4966 int i, tileno;
4967 struct tile *adjc_tile;
4968
4969 #define UNKNOWN(dir) \
4970 ((adjc_tile = mapstep(ptile, (dir))) \
4971 && client_tile_get_known(adjc_tile) == TILE_UNKNOWN)
4972
4973 switch (t->darkness_style) {
4974 case DARKNESS_NONE:
4975 break;
4976 case DARKNESS_ISORECT:
4977 for (i = 0; i < 4; i++) {
4978 const int W = t->normal_tile_width, H = t->normal_tile_height;
4979 int offsets[4][2] = {{W / 2, 0}, {0, H / 2}, {W / 2, H / 2}, {0, 0}};
4980
4981 if (UNKNOWN(DIR4_TO_DIR8[i])) {
4982 ADD_SPRITE(t->sprites.tx.darkness[i], TRUE,
4983 offsets[i][0], offsets[i][1]);
4984 }
4985 }
4986 break;
4987 case DARKNESS_CARD_SINGLE:
4988 for (i = 0; i < t->num_cardinal_tileset_dirs; i++) {
4989 if (UNKNOWN(t->cardinal_tileset_dirs[i])) {
4990 ADD_SPRITE_SIMPLE(t->sprites.tx.darkness[i]);
4991 }
4992 }
4993 break;
4994 case DARKNESS_CARD_FULL:
4995 /* We're looking to find the INDEX_NSEW for the directions that
4996 * are unknown. We want to mark unknown tiles so that an unreal
4997 * tile will be given the same marking as our current tile - that
4998 * way we won't get the "unknown" dither along the edge of the
4999 * map. */
5000 tileno = 0;
5001 for (i = 0; i < t->num_cardinal_tileset_dirs; i++) {
5002 if (UNKNOWN(t->cardinal_tileset_dirs[i])) {
5003 tileno |= 1 << i;
5004 }
5005 }
5006
5007 if (tileno != 0) {
5008 ADD_SPRITE_SIMPLE(t->sprites.tx.darkness[tileno]);
5009 }
5010 break;
5011 case DARKNESS_CORNER:
5012 /* Handled separately. */
5013 break;
5014 };
5015 #undef UNKNOWN
5016
5017 return sprs - saved_sprs;
5018 }
5019
5020 /****************************************************************************
5021 Add sprites for the base tile to the sprite list. This doesn't
5022 include specials or rivers.
5023 ****************************************************************************/
fill_terrain_sprite_layer(struct tileset * t,struct drawn_sprite * sprs,int layer_num,const struct tile * ptile,const struct terrain * pterrain,struct terrain ** tterrain_near)5024 static int fill_terrain_sprite_layer(struct tileset *t,
5025 struct drawn_sprite *sprs,
5026 int layer_num,
5027 const struct tile *ptile,
5028 const struct terrain *pterrain,
5029 struct terrain **tterrain_near)
5030 {
5031 struct sprite *sprite;
5032 struct drawn_sprite *saved_sprs = sprs;
5033 struct drawing_data *draw = t->sprites.drawing[terrain_index(pterrain)];
5034 const int l = (draw->is_reversed
5035 ? (draw->num_layers - layer_num - 1) : layer_num);
5036
5037 fc_assert(layer_num < TERRAIN_LAYER_COUNT);
5038
5039 /* Skip the normal drawing process. */
5040 /* FIXME: this should avoid calling load_sprite since it's slow and
5041 * increases the refcount without limit. */
5042 if (ptile->spec_sprite && (sprite = load_sprite(t, ptile->spec_sprite,
5043 TRUE, FALSE))) {
5044 if (l == 0) {
5045 ADD_SPRITE_SIMPLE(sprite);
5046 return 1;
5047 } else {
5048 return 0;
5049 }
5050 }
5051
5052 if (l < draw->num_layers) {
5053 sprs += fill_terrain_sprite_array(t, sprs, l, ptile, pterrain, tterrain_near, draw);
5054
5055 if ((l + 1) == draw->blending) {
5056 sprs += fill_terrain_sprite_blending(t, sprs, ptile, pterrain, tterrain_near);
5057 }
5058 }
5059
5060 /* Add darkness on top of the designed terrain layer. Note that darkness is always
5061 * drawn, even in citymode, etc. */
5062 if (layer_num == t->darkness_layer) {
5063 sprs += fill_terrain_sprite_darkness(t, sprs, ptile, tterrain_near);
5064 }
5065
5066 return sprs - saved_sprs;
5067 }
5068
5069 /****************************************************************************
5070 Indicate whether a unit is to be drawn with a surrounding city outline
5071 under current conditions.
5072 (This includes being in focus, but if the caller has already checked that,
5073 they can bypass this slightly expensive check with check_focus == FALSE.)
5074 ****************************************************************************/
unit_drawn_with_city_outline(const struct unit * punit,bool check_focus)5075 bool unit_drawn_with_city_outline(const struct unit *punit, bool check_focus)
5076 {
5077 /* Display an outline for city-builder type units if they are selected,
5078 * and on a tile where a city can be built.
5079 * But suppress the outline if the unit has orders (likely it is in
5080 * transit to somewhere else and this will just slow down redraws). */
5081 return gui_options.draw_city_outlines
5082 && unit_is_cityfounder(punit)
5083 && !unit_has_orders(punit)
5084 && (client_tile_get_known(unit_tile(punit)) != TILE_UNKNOWN
5085 && city_can_be_built_here(unit_tile(punit), punit))
5086 && (!check_focus || unit_is_in_focus(punit));
5087 }
5088
5089 /****************************************************************************
5090 Fill in the grid sprites for the given tile, city, and unit.
5091 ****************************************************************************/
fill_grid_sprite_array(const struct tileset * t,struct drawn_sprite * sprs,const struct tile * ptile,const struct tile_edge * pedge,const struct tile_corner * pcorner,const struct unit * punit,const struct city * pcity,const struct city * citymode)5092 static int fill_grid_sprite_array(const struct tileset *t,
5093 struct drawn_sprite *sprs,
5094 const struct tile *ptile,
5095 const struct tile_edge *pedge,
5096 const struct tile_corner *pcorner,
5097 const struct unit *punit,
5098 const struct city *pcity,
5099 const struct city *citymode)
5100 {
5101 struct drawn_sprite *saved_sprs = sprs;
5102
5103 if (pedge) {
5104 bool known[NUM_EDGE_TILES], city[NUM_EDGE_TILES];
5105 bool unit[NUM_EDGE_TILES], worked[NUM_EDGE_TILES];
5106 int i;
5107 struct unit_list *pfocus_units = get_units_in_focus();
5108
5109 for (i = 0; i < NUM_EDGE_TILES; i++) {
5110 int dummy_x, dummy_y;
5111 const struct tile *tile = pedge->tile[i];
5112 struct player *powner = tile ? tile_owner(tile) : NULL;
5113
5114 known[i] = tile && client_tile_get_known(tile) != TILE_UNKNOWN;
5115 unit[i] = FALSE;
5116 if (tile && !citymode) {
5117 unit_list_iterate(pfocus_units, pfocus_unit) {
5118 if (unit_drawn_with_city_outline(pfocus_unit, FALSE)) {
5119 struct tile *utile = unit_tile(pfocus_unit);
5120 int radius = game.info.init_city_radius_sq
5121 + get_target_bonus_effects(NULL, unit_owner(pfocus_unit), NULL,
5122 NULL, NULL, utile, NULL, NULL,
5123 NULL, NULL,
5124 EFT_CITY_RADIUS_SQ);
5125
5126 if (city_tile_to_city_map(&dummy_x, &dummy_y, radius,
5127 utile, tile)) {
5128 unit[i] = TRUE;
5129 break;
5130 }
5131 }
5132 } unit_list_iterate_end;
5133 }
5134 worked[i] = FALSE;
5135
5136 city[i] = (tile
5137 && (NULL == powner || NULL == client.conn.playing
5138 || powner == client.conn.playing)
5139 && player_in_city_map(client.conn.playing, tile));
5140 if (city[i]) {
5141 if (citymode) {
5142 /* In citymode, we only draw worked tiles for this city - other
5143 * tiles may be marked as unavailable. */
5144 worked[i] = (tile_worked(tile) == citymode);
5145 } else {
5146 worked[i] = (NULL != tile_worked(tile));
5147 }
5148 }
5149 }
5150
5151 if (mapdeco_is_highlight_set(pedge->tile[0])
5152 || mapdeco_is_highlight_set(pedge->tile[1])) {
5153 ADD_SPRITE_SIMPLE(t->sprites.grid.selected[pedge->type]);
5154 } else if (!gui_options.draw_terrain && gui_options.draw_coastline
5155 && pedge->tile[0] && pedge->tile[1]
5156 && known[0] && known[1]
5157 && (is_ocean_tile(pedge->tile[0])
5158 ^ is_ocean_tile(pedge->tile[1]))) {
5159 ADD_SPRITE_SIMPLE(t->sprites.grid.coastline[pedge->type]);
5160 } else {
5161 if (gui_options.draw_map_grid) {
5162 if (worked[0] || worked[1]) {
5163 ADD_SPRITE_SIMPLE(t->sprites.grid.worked[pedge->type]);
5164 } else if (city[0] || city[1]) {
5165 ADD_SPRITE_SIMPLE(t->sprites.grid.city[pedge->type]);
5166 } else if (known[0] || known[1]) {
5167 ADD_SPRITE_SIMPLE(t->sprites.grid.main[pedge->type]);
5168 }
5169 }
5170 if (gui_options.draw_city_outlines) {
5171 if (XOR(city[0], city[1])) {
5172 ADD_SPRITE_SIMPLE(t->sprites.grid.city[pedge->type]);
5173 }
5174 if (XOR(unit[0], unit[1])) {
5175 ADD_SPRITE_SIMPLE(t->sprites.grid.worked[pedge->type]);
5176 }
5177 }
5178 }
5179
5180 if (gui_options.draw_borders
5181 && BORDERS_DISABLED != game.info.borders
5182 && known[0]
5183 && known[1]) {
5184 struct player *owner0 = tile_owner(pedge->tile[0]);
5185 struct player *owner1 = tile_owner(pedge->tile[1]);
5186
5187 if (owner0 != owner1) {
5188 if (owner0) {
5189 int plrid = player_index(owner0);
5190 ADD_SPRITE_SIMPLE(t->sprites.player[plrid].grid_borders
5191 [pedge->type][0]);
5192 }
5193 if (owner1) {
5194 int plrid = player_index(owner1);
5195 ADD_SPRITE_SIMPLE(t->sprites.player[plrid].grid_borders
5196 [pedge->type][1]);
5197 }
5198 }
5199 }
5200 } else if (NULL != ptile && TILE_UNKNOWN != client_tile_get_known(ptile)) {
5201 int cx, cy;
5202
5203 if (citymode
5204 /* test to ensure valid coordinates? */
5205 && city_base_to_city_map(&cx, &cy, citymode, ptile)
5206 && !client_city_can_work_tile(citymode, ptile)) {
5207 ADD_SPRITE_SIMPLE(t->sprites.grid.unavailable);
5208 }
5209
5210 if (gui_options.draw_native && citymode == NULL) {
5211 bool native = TRUE;
5212 struct unit_list *pfocus_units = get_units_in_focus();
5213
5214 unit_list_iterate(pfocus_units, pfocus) {
5215 if (!is_native_tile(unit_type_get(pfocus), ptile)) {
5216 native = FALSE;
5217 break;
5218 }
5219 } unit_list_iterate_end;
5220
5221 if (!native) {
5222 if (t->sprites.grid.nonnative != NULL) {
5223 ADD_SPRITE_SIMPLE(t->sprites.grid.nonnative);
5224 } else {
5225 ADD_SPRITE_SIMPLE(t->sprites.grid.unavailable);
5226 }
5227 }
5228 }
5229 }
5230
5231 return sprs - saved_sprs;
5232 }
5233
5234 /****************************************************************************
5235 Fill in the given sprite array with any needed goto sprites.
5236 ****************************************************************************/
fill_goto_sprite_array(const struct tileset * t,struct drawn_sprite * sprs,const struct tile * ptile,const struct tile_edge * pedge,const struct tile_corner * pcorner)5237 static int fill_goto_sprite_array(const struct tileset *t,
5238 struct drawn_sprite *sprs,
5239 const struct tile *ptile,
5240 const struct tile_edge *pedge,
5241 const struct tile_corner *pcorner)
5242 {
5243 struct drawn_sprite *saved_sprs = sprs;
5244 struct sprite *sprite;
5245 bool warn = FALSE;
5246 enum goto_tile_state state;
5247 int length;
5248 bool waypoint;
5249
5250 if (goto_tile_state(ptile, &state, &length, &waypoint)) {
5251 if (length >= 0) {
5252 fc_assert(state >= 0);
5253 fc_assert(state < ARRAY_SIZE(t->sprites.path.s));
5254
5255 sprite = t->sprites.path.s[state].specific;
5256 if (sprite != NULL) {
5257 ADD_SPRITE(sprite, FALSE, 0, 0);
5258 }
5259
5260 sprite = t->sprites.path.s[state].turns[length % 10];
5261 ADD_SPRITE_SIMPLE(sprite);
5262 if (length >= 10) {
5263 sprite = t->sprites.path.s[state].turns_tens[(length / 10) % 10];
5264 ADD_SPRITE_SIMPLE(sprite);
5265 if (length >= 100) {
5266 sprite = t->sprites.path.s[state].turns_hundreds[(length / 100)
5267 % 10];
5268
5269 if (sprite != NULL) {
5270 ADD_SPRITE_SIMPLE(sprite);
5271 if (length >= 1000) {
5272 warn = TRUE;
5273 }
5274 } else {
5275 warn = TRUE;
5276 }
5277 }
5278 }
5279 }
5280
5281 if (waypoint) {
5282 ADD_SPRITE(t->sprites.path.waypoint, FALSE, 0, 0);
5283 }
5284
5285 if (warn) {
5286 /* Warn only once by tileset. */
5287 static char last_reported[256] = "";
5288
5289 if (0 != strcmp(last_reported, t->name)) {
5290 log_normal(_("Tileset \"%s\" doesn't support long goto paths, "
5291 "such as %d. Path not displayed as expected."),
5292 t->name, length);
5293 sz_strlcpy(last_reported, t->name);
5294 }
5295 }
5296 }
5297
5298 return sprs - saved_sprs;
5299 }
5300
5301 /****************************************************************************
5302 Should the given extra be drawn
5303 ****************************************************************************/
is_extra_drawing_enabled(struct extra_type * pextra)5304 static bool is_extra_drawing_enabled(struct extra_type *pextra)
5305 {
5306 bool no_disable = TRUE; /* Draw if matches no cause */
5307
5308 if (is_extra_caused_by(pextra, EC_IRRIGATION)) {
5309 if (gui_options.draw_irrigation) {
5310 return TRUE;
5311 }
5312 no_disable = FALSE;
5313 }
5314 if (is_extra_caused_by(pextra, EC_POLLUTION)
5315 || is_extra_caused_by(pextra, EC_FALLOUT)) {
5316 if (gui_options.draw_pollution) {
5317 return TRUE;
5318 }
5319 no_disable = FALSE;
5320 }
5321 if (is_extra_caused_by(pextra, EC_MINE)) {
5322 if (gui_options.draw_mines) {
5323 return TRUE;
5324 }
5325 no_disable = FALSE;
5326 }
5327 if (is_extra_caused_by(pextra, EC_HUT)) {
5328 if (gui_options.draw_huts) {
5329 return TRUE;
5330 }
5331 no_disable = FALSE;
5332 }
5333 if (is_extra_caused_by(pextra, EC_BASE)) {
5334 if (gui_options.draw_fortress_airbase) {
5335 return TRUE;
5336 }
5337 no_disable = FALSE;
5338 }
5339 if (is_extra_caused_by(pextra, EC_ROAD)) {
5340 if (gui_options.draw_roads_rails) {
5341 return TRUE;
5342 }
5343 no_disable = FALSE;
5344 }
5345
5346 return no_disable;
5347 }
5348
5349 /****************************************************************************
5350 Fill in the sprite array for the given tile, city, and unit.
5351
5352 ptile, if specified, gives the tile. If specified the terrain and specials
5353 will be drawn for this tile. In this case (map_x,map_y) should give the
5354 location of the tile.
5355
5356 punit, if specified, gives the unit. For tile drawing this should
5357 generally be get_drawable_unit(); otherwise it can be any unit.
5358
5359 pcity, if specified, gives the city. For tile drawing this should
5360 generally be tile_city(ptile); otherwise it can be any city.
5361
5362 citymode specifies whether this is part of a citydlg. If so some drawing
5363 is done differently.
5364 ****************************************************************************/
fill_sprite_array(struct tileset * t,struct drawn_sprite * sprs,enum mapview_layer layer,const struct tile * ptile,const struct tile_edge * pedge,const struct tile_corner * pcorner,const struct unit * punit,const struct city * pcity,const struct city * citymode,const struct unit_type * putype)5365 int fill_sprite_array(struct tileset *t,
5366 struct drawn_sprite *sprs, enum mapview_layer layer,
5367 const struct tile *ptile,
5368 const struct tile_edge *pedge,
5369 const struct tile_corner *pcorner,
5370 const struct unit *punit, const struct city *pcity,
5371 const struct city *citymode,
5372 const struct unit_type *putype)
5373 {
5374 int tileno, dir;
5375 bv_extras textras_near[8];
5376 bv_extras textras;
5377 struct terrain *tterrain_near[8];
5378 struct terrain *pterrain = NULL;
5379 struct drawn_sprite *save_sprs = sprs;
5380 struct player *owner = NULL;
5381 /* Unit drawing is disabled when the view options are turned off,
5382 * but only where we're drawing on the mapview. */
5383 bool do_draw_unit = (punit && (gui_options.draw_units || !ptile
5384 || (gui_options.draw_focus_unit
5385 && unit_is_in_focus(punit))));
5386 bool solid_bg = (gui_options.solid_color_behind_units
5387 && (do_draw_unit
5388 || (pcity && gui_options.draw_cities)
5389 || (ptile && !gui_options.draw_terrain)));
5390
5391 if (citymode) {
5392 int count = 0, i, cx, cy;
5393 const struct tile *const *tiles = NULL;
5394 bool valid = FALSE;
5395
5396 if (ptile) {
5397 tiles = &ptile;
5398 count = 1;
5399 } else if (pcorner) {
5400 tiles = pcorner->tile;
5401 count = NUM_CORNER_TILES;
5402 } else if (pedge) {
5403 tiles = pedge->tile;
5404 count = NUM_EDGE_TILES;
5405 }
5406
5407 for (i = 0; i < count; i++) {
5408 if (tiles[i] && city_base_to_city_map(&cx, &cy, citymode, tiles[i])) {
5409 valid = TRUE;
5410 break;
5411 }
5412 }
5413 if (!valid) {
5414 return 0;
5415 }
5416 }
5417
5418 if (ptile && client_tile_get_known(ptile) != TILE_UNKNOWN) {
5419 textras = *tile_extras(ptile);
5420 pterrain = tile_terrain(ptile);
5421
5422 if (NULL != pterrain) {
5423 if (layer == LAYER_TERRAIN1
5424 || layer == LAYER_TERRAIN2
5425 || layer == LAYER_TERRAIN3
5426 || layer == LAYER_WATER
5427 || layer == LAYER_ROADS) {
5428 build_tile_data(ptile, pterrain, tterrain_near, textras_near);
5429 }
5430 } else {
5431 log_error("fill_sprite_array() tile (%d,%d) has no terrain!",
5432 TILE_XY(ptile));
5433 }
5434 } else {
5435 BV_CLR_ALL(textras);
5436 }
5437
5438 switch (layer) {
5439 case LAYER_BACKGROUND:
5440 /* Set up background color. */
5441 if (gui_options.solid_color_behind_units) {
5442 if (do_draw_unit) {
5443 owner = unit_owner(punit);
5444 } else if (pcity && gui_options.draw_cities) {
5445 owner = city_owner(pcity);
5446 }
5447 }
5448 if (owner) {
5449 ADD_SPRITE_SIMPLE(t->sprites.player[player_index(owner)].background);
5450 } else if (ptile && !gui_options.draw_terrain) {
5451 ADD_SPRITE_SIMPLE(t->sprites.background.graphic);
5452 }
5453 break;
5454
5455 case LAYER_TERRAIN1:
5456 if (NULL != pterrain && gui_options.draw_terrain && !solid_bg) {
5457 sprs += fill_terrain_sprite_layer(t, sprs, 0, ptile, pterrain, tterrain_near);
5458 }
5459 break;
5460
5461 case LAYER_TERRAIN2:
5462 if (NULL != pterrain && gui_options.draw_terrain && !solid_bg) {
5463 sprs += fill_terrain_sprite_layer(t, sprs, 1, ptile, pterrain, tterrain_near);
5464 }
5465 break;
5466
5467 case LAYER_TERRAIN3:
5468 if (NULL != pterrain && gui_options.draw_terrain && !solid_bg) {
5469 fc_assert(MAX_NUM_LAYERS == 3);
5470 sprs += fill_terrain_sprite_layer(t, sprs, 2, ptile, pterrain, tterrain_near);
5471 }
5472 break;
5473
5474 case LAYER_WATER:
5475 if (NULL != pterrain) {
5476 if (gui_options.draw_terrain && !solid_bg
5477 && terrain_type_terrain_class(pterrain) == TC_OCEAN) {
5478 for (dir = 0; dir < t->num_cardinal_tileset_dirs; dir++) {
5479 int didx = t->cardinal_tileset_dirs[dir];
5480
5481 extra_type_list_iterate(t->style_lists[ESTYLE_RIVER], priver) {
5482 int idx = extra_index(priver);
5483
5484 if (BV_ISSET(textras_near[didx], idx)) {
5485 if (t->sprites.extras[idx].u.road.ru.rivers.outlet[dir] != NULL) {
5486 ADD_SPRITE_SIMPLE(t->sprites.extras[idx].u.road.ru.rivers.outlet[dir]);
5487 }
5488 break;
5489 }
5490 } extra_type_list_iterate_end;
5491 }
5492 }
5493
5494 sprs += fill_irrigation_sprite_array(t, sprs, textras, textras_near,
5495 pcity);
5496
5497 if (gui_options.draw_terrain && !solid_bg) {
5498 extra_type_list_iterate(t->style_lists[ESTYLE_RIVER], priver) {
5499 int idx = extra_index(priver);
5500
5501 if (BV_ISSET(textras, idx)) {
5502 int i;
5503
5504 /* Draw rivers on top of irrigation. */
5505 tileno = 0;
5506 for (i = 0; i < t->num_cardinal_tileset_dirs; i++) {
5507 enum direction8 cdir = t->cardinal_tileset_dirs[i];
5508
5509 if (terrain_type_terrain_class(tterrain_near[cdir]) == TC_OCEAN
5510 || BV_ISSET(textras_near[cdir], idx)) {
5511 tileno |= 1 << i;
5512 }
5513 }
5514
5515 ADD_SPRITE_SIMPLE(t->sprites.extras[idx].u.road.ru.rivers.spec[tileno]);
5516 }
5517 } extra_type_list_iterate_end;
5518 }
5519 }
5520 break;
5521
5522 case LAYER_ROADS:
5523 if (NULL != pterrain) {
5524 extra_type_list_iterate(t->style_lists[ESTYLE_ROAD_ALL_SEPARATE], pextra) {
5525 if (is_extra_drawing_enabled(pextra)) {
5526 sprs += fill_road_sprite_array(t, pextra, sprs,
5527 textras, textras_near,
5528 tterrain_near, pcity);
5529 }
5530 } extra_type_list_iterate_end;
5531 extra_type_list_iterate(t->style_lists[ESTYLE_ROAD_PARITY_COMBINED], pextra) {
5532 if (is_extra_drawing_enabled(pextra)) {
5533 sprs += fill_road_sprite_array(t, pextra, sprs,
5534 textras, textras_near,
5535 tterrain_near, pcity);
5536 }
5537 } extra_type_list_iterate_end;
5538 extra_type_list_iterate(t->style_lists[ESTYLE_ROAD_ALL_COMBINED], pextra) {
5539 if (is_extra_drawing_enabled(pextra)) {
5540 sprs += fill_road_sprite_array(t, pextra, sprs,
5541 textras, textras_near,
5542 tterrain_near, pcity);
5543 }
5544 } extra_type_list_iterate_end;
5545 }
5546 break;
5547
5548 case LAYER_SPECIAL1:
5549 if (NULL != pterrain) {
5550 if (gui_options.draw_specials) {
5551 if (tile_resource_is_valid(ptile)) {
5552 ADD_SPRITE_SIMPLE(t->sprites.resource[resource_index(tile_resource(ptile))]);
5553 }
5554 }
5555
5556 if (ptile) {
5557 extra_type_list_iterate(t->style_lists[ESTYLE_3LAYER], pextra) {
5558 if (tile_has_extra(ptile, pextra)
5559 && is_extra_drawing_enabled(pextra)
5560 && t->sprites.extras[extra_index(pextra)].u.bmf.background) {
5561 bool hidden = FALSE;
5562
5563 extra_type_list_iterate(pextra->hiders, phider) {
5564 if (BV_ISSET(textras, extra_index(phider))) {
5565 hidden = TRUE;
5566 break;
5567 }
5568 } extra_type_list_iterate_end;
5569
5570 if (!hidden) {
5571 ADD_SPRITE_FULL(t->sprites.extras[extra_index(pextra)].u.bmf.background);
5572 }
5573 }
5574 } extra_type_list_iterate_end;
5575 }
5576
5577 extra_type_list_iterate(t->style_lists[ESTYLE_SINGLE1], pextra) {
5578 if (BV_ISSET(textras, extra_index(pextra))
5579 && is_extra_drawing_enabled(pextra)) {
5580 bool hidden = FALSE;
5581
5582 extra_type_list_iterate(pextra->hiders, phider) {
5583 if (BV_ISSET(textras, extra_index(phider))) {
5584 hidden = TRUE;
5585 break;
5586 }
5587 } extra_type_list_iterate_end;
5588
5589 if (!hidden) {
5590 ADD_SPRITE_SIMPLE(t->sprites.extras[extra_index(pextra)].u.single);
5591 }
5592 }
5593 } extra_type_list_iterate_end;
5594 }
5595 break;
5596
5597 case LAYER_GRID1:
5598 if (t->type == TS_ISOMETRIC) {
5599 sprs += fill_grid_sprite_array(t, sprs, ptile, pedge, pcorner,
5600 punit, pcity, citymode);
5601 }
5602 break;
5603
5604 case LAYER_CITY1:
5605 /* City. Some city sprites are drawn later. */
5606 if (pcity && gui_options.draw_cities) {
5607 if (!gui_options.draw_full_citybar && !gui_options.solid_color_behind_units) {
5608 ADD_SPRITE(get_city_flag_sprite(t, pcity), TRUE,
5609 FULL_TILE_X_OFFSET + t->city_flag_offset_x,
5610 FULL_TILE_Y_OFFSET + t->city_flag_offset_y);
5611 }
5612 /* For iso-view the city.wall graphics include the full city, whereas
5613 * for non-iso view they are an overlay on top of the base city
5614 * graphic. */
5615 if (t->type == TS_OVERHEAD || pcity->client.walls <= 0) {
5616 ADD_SPRITE(get_city_sprite(t->sprites.city.tile, pcity), TRUE,
5617 FULL_TILE_X_OFFSET + t->city_offset_x,
5618 FULL_TILE_Y_OFFSET + t->city_offset_y);
5619 }
5620 if (t->type == TS_ISOMETRIC && pcity->client.walls > 0) {
5621 struct city_sprite *cspr = t->sprites.city.wall[pcity->client.walls - 1];
5622 struct sprite *spr = NULL;
5623
5624 if (cspr != NULL) {
5625 spr = get_city_sprite(cspr, pcity);
5626 }
5627 if (spr == NULL) {
5628 cspr = t->sprites.city.single_wall;
5629 if (cspr != NULL) {
5630 spr = get_city_sprite(cspr, pcity);
5631 }
5632 }
5633
5634 if (spr != NULL) {
5635 ADD_SPRITE(spr, TRUE,
5636 FULL_TILE_X_OFFSET + t->city_offset_x,
5637 FULL_TILE_Y_OFFSET + t->city_offset_y);
5638 }
5639 }
5640 if (!gui_options.draw_full_citybar && pcity->client.occupied) {
5641 ADD_SPRITE(get_city_sprite(t->sprites.city.occupied, pcity), TRUE,
5642 FULL_TILE_X_OFFSET + t->occupied_offset_x,
5643 FULL_TILE_Y_OFFSET + t->occupied_offset_y);
5644 }
5645 if (t->type == TS_OVERHEAD && pcity->client.walls > 0) {
5646 struct city_sprite *cspr = t->sprites.city.wall[pcity->client.walls - 1];
5647 struct sprite *spr = NULL;
5648
5649 if (cspr != NULL) {
5650 spr = get_city_sprite(cspr, pcity);
5651 }
5652 if (spr == NULL) {
5653 cspr = t->sprites.city.single_wall;
5654 if (cspr != NULL) {
5655 spr = get_city_sprite(cspr, pcity);
5656 }
5657 }
5658
5659 if (spr != NULL) {
5660 ADD_SPRITE_FULL(spr);
5661 }
5662 }
5663 if (pcity->client.unhappy) {
5664 ADD_SPRITE_FULL(t->sprites.city.disorder);
5665 }
5666 }
5667 break;
5668
5669 case LAYER_SPECIAL2:
5670 if (NULL != pterrain) {
5671 if (ptile) {
5672 extra_type_list_iterate(t->style_lists[ESTYLE_3LAYER], pextra) {
5673 if (tile_has_extra(ptile, pextra)
5674 && is_extra_drawing_enabled(pextra)
5675 && t->sprites.extras[extra_index(pextra)].u.bmf.middleground) {
5676 bool hidden = FALSE;
5677
5678 extra_type_list_iterate(pextra->hiders, phider) {
5679 if (BV_ISSET(textras, extra_index(phider))) {
5680 hidden = TRUE;
5681 break;
5682 }
5683 } extra_type_list_iterate_end;
5684
5685 if (!hidden) {
5686 ADD_SPRITE_FULL(t->sprites.extras[extra_index(pextra)].u.bmf.middleground);
5687 }
5688 }
5689 } extra_type_list_iterate_end;
5690 }
5691
5692 extra_type_list_iterate(t->style_lists[ESTYLE_SINGLE2], pextra) {
5693 if (BV_ISSET(textras, extra_index(pextra))
5694 && is_extra_drawing_enabled(pextra)) {
5695 bool hidden = FALSE;
5696
5697 extra_type_list_iterate(pextra->hiders, phider) {
5698 if (BV_ISSET(textras, extra_index(phider))) {
5699 hidden = TRUE;
5700 break;
5701 }
5702 } extra_type_list_iterate_end;
5703
5704 if (!hidden) {
5705 ADD_SPRITE_SIMPLE(t->sprites.extras[extra_index(pextra)].u.single);
5706 }
5707 }
5708 } extra_type_list_iterate_end;
5709 }
5710 break;
5711
5712 case LAYER_UNIT:
5713 case LAYER_FOCUS_UNIT:
5714 if (do_draw_unit && XOR(layer == LAYER_UNIT, unit_is_in_focus(punit))) {
5715 bool stacked = ptile && (unit_list_size(ptile->units) > 1);
5716 bool backdrop = !pcity;
5717
5718 if (ptile && unit_is_in_focus(punit)
5719 && t->sprites.unit.select[0]) {
5720 /* Special case for drawing the selection rectangle. The blinking
5721 * unit is handled separately, inside get_drawable_unit(). */
5722 ADD_SPRITE_SIMPLE(t->sprites.unit.select[focus_unit_state]);
5723 }
5724
5725 sprs += fill_unit_sprite_array(t, sprs, punit, stacked, backdrop);
5726 } else if (putype != NULL && layer == LAYER_UNIT) {
5727 /* Only the sprite for the unit type. */
5728 sprs += fill_unit_type_sprite_array(t, sprs, putype,
5729 direction8_invalid());
5730 }
5731 break;
5732
5733 case LAYER_SPECIAL3:
5734 if (NULL != pterrain) {
5735 if (ptile) {
5736 bool show_flag = FALSE;
5737 struct player *eowner = extra_owner(ptile);
5738
5739 extra_type_list_iterate(t->style_lists[ESTYLE_3LAYER], pextra) {
5740 if (is_extra_drawing_enabled(pextra)
5741 && tile_has_extra(ptile, pextra)
5742 && t->sprites.extras[extra_index(pextra)].u.bmf.foreground) {
5743 bool hidden = FALSE;
5744
5745 extra_type_list_iterate(pextra->hiders, phider) {
5746 if (BV_ISSET(textras, extra_index(phider))) {
5747 hidden = TRUE;
5748 break;
5749 }
5750 } extra_type_list_iterate_end;
5751
5752 if (!hidden) {
5753 if (t->sprites.extras[extra_index(pextra)].u.bmf.foreground) {
5754 ADD_SPRITE_FULL(t->sprites.extras[extra_index(pextra)].u.bmf.foreground);
5755 }
5756 }
5757 }
5758 } extra_type_list_iterate_end;
5759
5760 /* Show base flag. Not part of previous iteration as
5761 * "extras of ESTYLE_3_LAYER" != "bases" */
5762 if (eowner != NULL) {
5763 extra_type_list_iterate(t->flagged_bases_list, pextra) {
5764 if (tile_has_extra(ptile, pextra)) {
5765 bool hidden = FALSE;
5766
5767 extra_type_list_iterate(pextra->hiders, phider) {
5768 if (BV_ISSET(textras, extra_index(phider))) {
5769 hidden = TRUE;
5770 break;
5771 }
5772 } extra_type_list_iterate_end;
5773
5774 if (!hidden) {
5775 show_flag = TRUE;
5776 }
5777 }
5778 } extra_type_list_iterate_end;
5779
5780 if (show_flag) {
5781 ADD_SPRITE(get_nation_flag_sprite(t, nation_of_player(eowner)), TRUE,
5782 FULL_TILE_X_OFFSET + t->city_flag_offset_x,
5783 FULL_TILE_Y_OFFSET + t->city_flag_offset_y);
5784 }
5785 }
5786 }
5787 }
5788 break;
5789
5790 case LAYER_FOG:
5791 sprs += fill_fog_sprite_array(t, sprs, ptile, pedge, pcorner);
5792 break;
5793
5794 case LAYER_CITY2:
5795 /* City size. Drawing this under fog makes it hard to read. */
5796 if (pcity && gui_options.draw_cities && !gui_options.draw_full_citybar) {
5797 bool warn = FALSE;
5798 unsigned int size = city_size_get(pcity);
5799
5800 ADD_SPRITE(t->sprites.city.size[size % 10],
5801 FALSE, FULL_TILE_X_OFFSET, FULL_TILE_Y_OFFSET);
5802 if (10 <= size) {
5803 ADD_SPRITE(t->sprites.city.size_tens[(size / 10)
5804 % 10], FALSE, FULL_TILE_X_OFFSET, FULL_TILE_Y_OFFSET);
5805 if (100 <= size) {
5806 struct sprite *sprite =
5807 t->sprites.city.size_hundreds[(size / 100) % 10];
5808
5809 if (NULL != sprite) {
5810 ADD_SPRITE(sprite, FALSE,
5811 FULL_TILE_X_OFFSET, FULL_TILE_Y_OFFSET);
5812 } else {
5813 warn = TRUE;
5814 }
5815 if (1000 <= size) {
5816 warn = TRUE;
5817 }
5818 }
5819 }
5820
5821 if (warn) {
5822 /* Warn only once by tileset. */
5823 static char last_reported[256] = "";
5824
5825 if (0 != strcmp(last_reported, t->name)) {
5826 log_normal(_("Tileset \"%s\" doesn't support big cities size, "
5827 "such as %d. Size not displayed as expected."),
5828 t->name, size);
5829 sz_strlcpy(last_reported, t->name);
5830 }
5831 }
5832 }
5833 break;
5834
5835 case LAYER_GRID2:
5836 if (t->type == TS_OVERHEAD) {
5837 sprs += fill_grid_sprite_array(t, sprs, ptile, pedge, pcorner,
5838 punit, pcity, citymode);
5839 }
5840 break;
5841
5842 case LAYER_OVERLAYS:
5843 sprs += fill_city_overlays_sprite_array(t, sprs, ptile, citymode);
5844 if (mapdeco_is_crosshair_set(ptile)) {
5845 ADD_SPRITE_SIMPLE(t->sprites.user.attention);
5846 }
5847 break;
5848
5849 case LAYER_CITYBAR:
5850 case LAYER_TILELABEL:
5851 /* Nothing. This is just a placeholder. */
5852 break;
5853
5854 case LAYER_GOTO:
5855 if (ptile && goto_is_active()) {
5856 sprs += fill_goto_sprite_array(t, sprs, ptile, pedge, pcorner);
5857 }
5858 break;
5859
5860 case LAYER_WORKERTASK:
5861 if (citymode != NULL && ptile != NULL) {
5862 worker_task_list_iterate(citymode->task_reqs, ptask) {
5863 if (ptask->ptile == ptile) {
5864 switch (ptask->act) {
5865 case ACTIVITY_MINE:
5866 if (ptask->tgt == NULL) {
5867 ADD_SPRITE(t->sprites.unit.plant,
5868 TRUE, FULL_TILE_X_OFFSET + t->activity_offset_x,
5869 FULL_TILE_Y_OFFSET + t->activity_offset_y);
5870 } else {
5871 ADD_SPRITE(t->sprites.extras[extra_index(ptask->tgt)].activity,
5872 TRUE, FULL_TILE_X_OFFSET + t->activity_offset_x,
5873 FULL_TILE_Y_OFFSET + t->activity_offset_y);
5874 }
5875 break;
5876 case ACTIVITY_IRRIGATE:
5877 if (ptask->tgt == NULL) {
5878 ADD_SPRITE(t->sprites.unit.irrigate,
5879 TRUE, FULL_TILE_X_OFFSET + t->activity_offset_x,
5880 FULL_TILE_Y_OFFSET + t->activity_offset_y);
5881 } else {
5882 ADD_SPRITE(t->sprites.extras[extra_index(ptask->tgt)].activity,
5883 TRUE, FULL_TILE_X_OFFSET + t->activity_offset_x,
5884 FULL_TILE_Y_OFFSET + t->activity_offset_y);
5885 }
5886 break;
5887 case ACTIVITY_GEN_ROAD:
5888 if (ptask->tgt != NULL) {
5889 ADD_SPRITE(t->sprites.extras[extra_index(ptask->tgt)].activity,
5890 TRUE, FULL_TILE_X_OFFSET + t->activity_offset_x,
5891 FULL_TILE_Y_OFFSET + t->activity_offset_y);
5892 }
5893 break;
5894 case ACTIVITY_TRANSFORM:
5895 ADD_SPRITE(t->sprites.unit.transform,
5896 TRUE, FULL_TILE_X_OFFSET + t->activity_offset_x,
5897 FULL_TILE_Y_OFFSET + t->activity_offset_y);
5898 break;
5899 case ACTIVITY_POLLUTION:
5900 case ACTIVITY_FALLOUT:
5901 if (ptask->tgt != NULL) {
5902 ADD_SPRITE(t->sprites.extras[extra_index(ptask->tgt)].rmact,
5903 TRUE, FULL_TILE_X_OFFSET + t->activity_offset_x,
5904 FULL_TILE_Y_OFFSET + t->activity_offset_y);
5905 }
5906 break;
5907 default:
5908 break;
5909 }
5910 }
5911 } worker_task_list_iterate_end;
5912 }
5913 break;
5914
5915 case LAYER_EDITOR:
5916 if (ptile && editor_is_active()) {
5917 if (editor_tile_is_selected(ptile)) {
5918 int color = 2 % tileset_num_city_colors(tileset);
5919 ADD_SPRITE_SIMPLE(t->sprites.city.unworked_tile_overlay.p[color]);
5920 }
5921
5922 if (NULL != map_startpos_get(ptile)) {
5923 /* FIXME: Use a more representative sprite. */
5924 ADD_SPRITE_SIMPLE(t->sprites.user.attention);
5925 }
5926 }
5927 break;
5928
5929 case LAYER_COUNT:
5930 fc_assert(FALSE);
5931 break;
5932 }
5933
5934 return sprs - save_sprs;
5935 }
5936
5937 /**********************************************************************
5938 Set city tiles sprite values; should only happen after
5939 tilespec_load_tiles().
5940 ***********************************************************************/
tileset_setup_city_tiles(struct tileset * t,int style)5941 void tileset_setup_city_tiles(struct tileset *t, int style)
5942 {
5943 if (style == game.control.styles_count - 1) {
5944 int i;
5945
5946 /* Free old sprites */
5947 free_city_sprite(t->sprites.city.tile);
5948
5949 for (i = 0; i < NUM_WALL_TYPES; i++) {
5950 free_city_sprite(t->sprites.city.wall[i]);
5951 t->sprites.city.wall[i] = NULL;
5952 }
5953 free_city_sprite(t->sprites.city.single_wall);
5954 t->sprites.city.single_wall = NULL;
5955
5956 free_city_sprite(t->sprites.city.occupied);
5957
5958 t->sprites.city.tile = load_city_sprite(t, "city");
5959
5960 for (i = 0; i < NUM_WALL_TYPES; i++) {
5961 char buffer[256];
5962
5963 fc_snprintf(buffer, sizeof(buffer), "bldg_%d", i);
5964 t->sprites.city.wall[i] = load_city_sprite(t, buffer);
5965 }
5966 t->sprites.city.single_wall = load_city_sprite(t, "wall");
5967
5968 t->sprites.city.occupied = load_city_sprite(t, "occupied");
5969
5970 for (style = 0; style < game.control.styles_count; style++) {
5971 if (t->sprites.city.tile->styles[style].land_num_thresholds == 0) {
5972 tileset_error(LOG_FATAL, _("City style \"%s\": no city graphics."),
5973 city_style_rule_name(style));
5974 }
5975 if (t->sprites.city.occupied->styles[style].land_num_thresholds == 0) {
5976 tileset_error(LOG_FATAL, _("City style \"%s\": no occupied graphics."),
5977 city_style_rule_name(style));
5978 }
5979 }
5980 }
5981 }
5982
5983 /****************************************************************************
5984 Return the amount of time between calls to toggle_focus_unit_state.
5985 The main loop needs to call toggle_focus_unit_state about this often
5986 to do the active-unit animation.
5987 ****************************************************************************/
get_focus_unit_toggle_timeout(const struct tileset * t)5988 double get_focus_unit_toggle_timeout(const struct tileset *t)
5989 {
5990 if (t->sprites.unit.select[0]) {
5991 return 0.1;
5992 } else {
5993 return 0.5;
5994 }
5995 }
5996
5997 /****************************************************************************
5998 Reset the focus unit state. This should be called when changing
5999 focus units.
6000 ****************************************************************************/
reset_focus_unit_state(struct tileset * t)6001 void reset_focus_unit_state(struct tileset *t)
6002 {
6003 focus_unit_state = 0;
6004 }
6005
6006 /****************************************************************************
6007 Setup tileset for showing combat where focus unit participates.
6008 ****************************************************************************/
focus_unit_in_combat(struct tileset * t)6009 void focus_unit_in_combat(struct tileset *t)
6010 {
6011 if (!t->sprites.unit.select[0]) {
6012 reset_focus_unit_state(t);
6013 }
6014 }
6015
6016 /****************************************************************************
6017 Toggle/increment the focus unit state. This should be called once
6018 every get_focus_unit_toggle_timeout() seconds.
6019 ****************************************************************************/
toggle_focus_unit_state(struct tileset * t)6020 void toggle_focus_unit_state(struct tileset *t)
6021 {
6022 focus_unit_state++;
6023 if (t->sprites.unit.select[0]) {
6024 focus_unit_state %= NUM_TILES_SELECT;
6025 } else {
6026 focus_unit_state %= 2;
6027 }
6028 }
6029
6030 /**********************************************************************
6031 Find unit that we can display from given tile.
6032 ***********************************************************************/
get_drawable_unit(const struct tileset * t,struct tile * ptile,const struct city * citymode)6033 struct unit *get_drawable_unit(const struct tileset *t,
6034 struct tile *ptile,
6035 const struct city *citymode)
6036 {
6037 struct unit *punit = find_visible_unit(ptile);
6038
6039 if (punit == NULL) {
6040 return NULL;
6041 }
6042
6043 if (citymode && unit_owner(punit) == city_owner(citymode)) {
6044 return NULL;
6045 }
6046
6047 if (!unit_is_in_focus(punit)
6048 || t->sprites.unit.select[0] || focus_unit_state == 0) {
6049 return punit;
6050 } else {
6051 return NULL;
6052 }
6053 }
6054
6055 /****************************************************************************
6056 This patch unloads all sprites from the sprite hash (the hash itself
6057 is left intact).
6058 ****************************************************************************/
unload_all_sprites(struct tileset * t)6059 static void unload_all_sprites(struct tileset *t)
6060 {
6061 if (t->sprite_hash) {
6062 sprite_hash_iterate(t->sprite_hash, tag_name, ss) {
6063 while (ss->ref_count > 0) {
6064 unload_sprite(t, tag_name);
6065 }
6066 } sprite_hash_iterate_end;
6067 }
6068 }
6069
6070 /**********************************************************************
6071 Free all sprites from tileset.
6072 ***********************************************************************/
tileset_free_tiles(struct tileset * t)6073 void tileset_free_tiles(struct tileset *t)
6074 {
6075 int i;
6076
6077 log_debug("tileset_free_tiles()");
6078
6079 unload_all_sprites(t);
6080
6081 free_city_sprite(t->sprites.city.tile);
6082 t->sprites.city.tile = NULL;
6083
6084 for (i = 0; i < NUM_WALL_TYPES; i++) {
6085 free_city_sprite(t->sprites.city.wall[i]);
6086 t->sprites.city.wall[i] = NULL;
6087 }
6088 free_city_sprite(t->sprites.city.single_wall);
6089 t->sprites.city.single_wall = NULL;
6090
6091 free_city_sprite(t->sprites.city.occupied);
6092 t->sprites.city.occupied = NULL;
6093
6094 if (t->sprite_hash) {
6095 sprite_hash_destroy(t->sprite_hash);
6096 t->sprite_hash = NULL;
6097 }
6098
6099 small_sprite_list_iterate(t->small_sprites, ss) {
6100 small_sprite_list_remove(t->small_sprites, ss);
6101 if (ss->file) {
6102 free(ss->file);
6103 }
6104 fc_assert(ss->sprite == NULL);
6105 free(ss);
6106 } small_sprite_list_iterate_end;
6107
6108 specfile_list_iterate(t->specfiles, sf) {
6109 specfile_list_remove(t->specfiles, sf);
6110 free(sf->file_name);
6111 if (sf->big_sprite) {
6112 free_sprite(sf->big_sprite);
6113 sf->big_sprite = NULL;
6114 }
6115 free(sf);
6116 } specfile_list_iterate_end;
6117
6118 sprite_vector_iterate(&t->sprites.city.worked_tile_overlay, psprite) {
6119 free_sprite(*psprite);
6120 } sprite_vector_iterate_end;
6121 sprite_vector_free(&t->sprites.city.worked_tile_overlay);
6122
6123 sprite_vector_iterate(&t->sprites.city.unworked_tile_overlay, psprite) {
6124 free_sprite(*psprite);
6125 } sprite_vector_iterate_end;
6126 sprite_vector_free(&t->sprites.city.unworked_tile_overlay);
6127
6128 if (t->sprites.tx.fullfog) {
6129 free(t->sprites.tx.fullfog);
6130 t->sprites.tx.fullfog = NULL;
6131 }
6132
6133 sprite_vector_free(&t->sprites.colors.overlays);
6134 sprite_vector_free(&t->sprites.explode.unit);
6135 sprite_vector_free(&t->sprites.nation_flag);
6136 sprite_vector_free(&t->sprites.nation_shield);
6137 sprite_vector_free(&t->sprites.citybar.occupancy);
6138
6139 tileset_background_free(t);
6140 }
6141
6142 /**************************************************************************
6143 Return the sprite for drawing the given spaceship part.
6144 **************************************************************************/
get_spaceship_sprite(const struct tileset * t,enum spaceship_part part)6145 struct sprite *get_spaceship_sprite(const struct tileset *t,
6146 enum spaceship_part part)
6147 {
6148 return t->sprites.spaceship[part];
6149 }
6150
6151 /**************************************************************************
6152 Return a sprite for the given citizen. The citizen's type is given,
6153 as well as their index (in the range [0..city_size_get(pcity))). The
6154 citizen's city can be used to determine which sprite to use (a NULL
6155 value indicates there is no city; i.e., the sprite is just being
6156 used as a picture).
6157 **************************************************************************/
get_citizen_sprite(const struct tileset * t,enum citizen_category type,int citizen_index,const struct city * pcity)6158 struct sprite *get_citizen_sprite(const struct tileset *t,
6159 enum citizen_category type,
6160 int citizen_index,
6161 const struct city *pcity)
6162 {
6163 const struct citizen_graphic *graphic;
6164 int gfx_index = citizen_index;
6165
6166 if (pcity != NULL) {
6167 gfx_index += pcity->client.first_citizen_index;
6168 }
6169
6170 if (type < CITIZEN_SPECIALIST) {
6171 fc_assert(type >= 0);
6172 graphic = &t->sprites.citizen[type];
6173 } else {
6174 fc_assert(type < (CITIZEN_SPECIALIST + SP_MAX));
6175 graphic = &t->sprites.specialist[type - CITIZEN_SPECIALIST];
6176 }
6177
6178 if (graphic->count == 0) {
6179 return NULL;
6180 }
6181
6182 return graphic->sprite[gfx_index % graphic->count];
6183 }
6184
6185 /**************************************************************************
6186 Return the sprite for the nation.
6187 **************************************************************************/
get_nation_flag_sprite(const struct tileset * t,const struct nation_type * pnation)6188 struct sprite *get_nation_flag_sprite(const struct tileset *t,
6189 const struct nation_type *pnation)
6190 {
6191 return t->sprites.nation_flag.p[nation_index(pnation)];
6192 }
6193
6194 /**************************************************************************
6195 Return the shield sprite for the nation.
6196 **************************************************************************/
get_nation_shield_sprite(const struct tileset * t,const struct nation_type * pnation)6197 struct sprite *get_nation_shield_sprite(const struct tileset *t,
6198 const struct nation_type *pnation)
6199 {
6200 return t->sprites.nation_shield.p[nation_index(pnation)];
6201 }
6202
6203 /**************************************************************************
6204 Return the sprite for the technology/advance.
6205 **************************************************************************/
get_tech_sprite(const struct tileset * t,Tech_type_id tech)6206 struct sprite *get_tech_sprite(const struct tileset *t, Tech_type_id tech)
6207 {
6208 fc_assert_ret_val(0 <= tech && tech < advance_count(), NULL);
6209 return t->sprites.tech[tech];
6210 }
6211
6212 /**************************************************************************
6213 Return the sprite for the building/improvement.
6214 **************************************************************************/
get_building_sprite(const struct tileset * t,struct impr_type * pimprove)6215 struct sprite *get_building_sprite(const struct tileset *t,
6216 struct impr_type *pimprove)
6217 {
6218 fc_assert_ret_val(NULL != pimprove, NULL);
6219 return t->sprites.building[improvement_index(pimprove)];
6220 }
6221
6222 /****************************************************************************
6223 Return the sprite for the government.
6224 ****************************************************************************/
get_government_sprite(const struct tileset * t,const struct government * gov)6225 struct sprite *get_government_sprite(const struct tileset *t,
6226 const struct government *gov)
6227 {
6228 fc_assert_ret_val(NULL != gov, NULL);
6229 return t->sprites.government[government_index(gov)];
6230 }
6231
6232 /****************************************************************************
6233 Return the sprite for the unit type (the base "unit" sprite).
6234 ****************************************************************************/
get_unittype_sprite(const struct tileset * t,const struct unit_type * punittype,enum direction8 facing,bool icon)6235 struct sprite *get_unittype_sprite(const struct tileset *t,
6236 const struct unit_type *punittype,
6237 enum direction8 facing,
6238 bool icon)
6239 {
6240 int uidx = utype_index(punittype);
6241
6242 fc_assert_ret_val(NULL != punittype, NULL);
6243
6244 if (!direction8_is_valid(facing) || !is_valid_dir(facing)) {
6245 /* Fallback to random orientation sprite.
6246 * The randomness was fixed at tileset load time for stability
6247 * (in tileset_setup_unit_type_from_tag()); here we need to adapt
6248 * that to the map topology (which is now known).
6249 * default_dir_seed was set to give uniform distribution for either
6250 * 6 or 8 valid directions.
6251 * Thus this direction is stable for a given unit type unless the
6252 * map topology changes. */
6253 unsigned int dir_index;
6254
6255 fc_assert_ret_val(game.map.num_valid_dirs > 0, NULL);
6256 dir_index
6257 = t->sprites.units.default_dir_seed[uidx] % game.map.num_valid_dirs;
6258 facing = game.map.valid_dirs[dir_index];
6259 fc_assert_ret_val(is_valid_dir(facing), NULL);
6260 }
6261
6262 if (t->sprites.units.icon[uidx]
6263 && (icon || t->sprites.units.facing[uidx][facing] == NULL)) {
6264 /* Has icon sprite */
6265 return t->sprites.units.icon[uidx];
6266 } else {
6267 return t->sprites.units.facing[uidx][facing];
6268 }
6269 }
6270
6271 /**************************************************************************
6272 Return a "sample" sprite for this city style.
6273 **************************************************************************/
get_sample_city_sprite(const struct tileset * t,int style_idx)6274 struct sprite *get_sample_city_sprite(const struct tileset *t,
6275 int style_idx)
6276 {
6277 int num_thresholds =
6278 t->sprites.city.tile->styles[style_idx].land_num_thresholds;
6279
6280 if (num_thresholds == 0) {
6281 return NULL;
6282 } else {
6283 return (t->sprites.city.tile->styles[style_idx]
6284 .land_thresholds[num_thresholds - 1].sprite);
6285 }
6286 }
6287
6288 /**************************************************************************
6289 Return a sprite with an "arrow" theme graphic.
6290 **************************************************************************/
get_arrow_sprite(const struct tileset * t,enum arrow_type arrow)6291 struct sprite *get_arrow_sprite(const struct tileset *t,
6292 enum arrow_type arrow)
6293 {
6294 fc_assert_ret_val(arrow >= 0 && arrow < ARROW_LAST, NULL);
6295
6296 return t->sprites.arrow[arrow];
6297 }
6298
6299 /**************************************************************************
6300 Return a tax sprite for the given output type (usually gold/lux/sci).
6301 **************************************************************************/
get_tax_sprite(const struct tileset * t,Output_type_id otype)6302 struct sprite *get_tax_sprite(const struct tileset *t, Output_type_id otype)
6303 {
6304 switch (otype) {
6305 case O_SCIENCE:
6306 return t->sprites.tax_science;
6307 case O_GOLD:
6308 return t->sprites.tax_gold;
6309 case O_LUXURY:
6310 return t->sprites.tax_luxury;
6311 case O_TRADE:
6312 case O_FOOD:
6313 case O_SHIELD:
6314 case O_LAST:
6315 break;
6316 }
6317 return NULL;
6318 }
6319
6320 /**************************************************************************
6321 Return event icon sprite
6322 **************************************************************************/
get_event_sprite(const struct tileset * t,enum event_type event)6323 struct sprite *get_event_sprite(const struct tileset *t, enum event_type event)
6324 {
6325 return t->sprites.events[event];
6326 }
6327
6328 /**************************************************************************
6329 Return a thumbs-up/thumbs-down sprite to show treaty approval or
6330 disapproval.
6331 **************************************************************************/
get_treaty_thumb_sprite(const struct tileset * t,bool on_off)6332 struct sprite *get_treaty_thumb_sprite(const struct tileset *t, bool on_off)
6333 {
6334 return t->sprites.treaty_thumb[on_off ? 1 : 0];
6335 }
6336
6337 /**************************************************************************
6338 Return a sprite_vector containing the animation sprites for a unit
6339 explosion.
6340 **************************************************************************/
get_unit_explode_animation(const struct tileset * t)6341 const struct sprite_vector *get_unit_explode_animation(const struct
6342 tileset *t)
6343 {
6344 return &t->sprites.explode.unit;
6345 }
6346
6347 /****************************************************************************
6348 Return a sprite contining the single nuke graphic.
6349
6350 TODO: This should be an animation like the unit explode animation.
6351 ****************************************************************************/
get_nuke_explode_sprite(const struct tileset * t)6352 struct sprite *get_nuke_explode_sprite(const struct tileset *t)
6353 {
6354 return t->sprites.explode.nuke;
6355 }
6356
6357 /**************************************************************************
6358 Return all the sprites used for city bar drawing.
6359 **************************************************************************/
get_citybar_sprites(const struct tileset * t)6360 const struct citybar_sprites *get_citybar_sprites(const struct tileset *t)
6361 {
6362 if (gui_options.draw_full_citybar) {
6363 return &t->sprites.citybar;
6364 } else {
6365 return NULL;
6366 }
6367 }
6368
6369 /**************************************************************************
6370 Return all the sprites used for editor icons, images, etc.
6371 **************************************************************************/
get_editor_sprites(const struct tileset * t)6372 const struct editor_sprites *get_editor_sprites(const struct tileset *t)
6373 {
6374 return &t->sprites.editor;
6375 }
6376
6377 /**************************************************************************
6378 Returns a sprite for the given cursor. The "hot" coordinates (the
6379 active coordinates of the mouse relative to the sprite) are placed int
6380 (*hot_x, *hot_y).
6381 A cursor can consist of several frames to be used for animation.
6382 **************************************************************************/
get_cursor_sprite(const struct tileset * t,enum cursor_type cursor,int * hot_x,int * hot_y,int frame)6383 struct sprite *get_cursor_sprite(const struct tileset *t,
6384 enum cursor_type cursor,
6385 int *hot_x, int *hot_y, int frame)
6386 {
6387 *hot_x = t->sprites.cursor[cursor].hot_x;
6388 *hot_y = t->sprites.cursor[cursor].hot_y;
6389 return t->sprites.cursor[cursor].frame[frame];
6390 }
6391
6392 /****************************************************************************
6393 Return a sprite for the given icon. Icons are used by the operating
6394 system/window manager. Usually freeciv has to tell the OS what icon to
6395 use.
6396
6397 Note that this function will return NULL before the sprites are loaded.
6398 The GUI code must be sure to call tileset_load_tiles before setting the
6399 top-level icon.
6400 ****************************************************************************/
get_icon_sprite(const struct tileset * t,enum icon_type icon)6401 struct sprite *get_icon_sprite(const struct tileset *t, enum icon_type icon)
6402 {
6403 return t->sprites.icon[icon];
6404 }
6405
6406 /****************************************************************************
6407 Returns a sprite with the "user-attention" crosshair graphic.
6408
6409 FIXME: This function shouldn't be needed if the attention graphics are
6410 drawn natively by the tileset code.
6411 ****************************************************************************/
get_attention_crosshair_sprite(const struct tileset * t)6412 struct sprite *get_attention_crosshair_sprite(const struct tileset *t)
6413 {
6414 return t->sprites.user.attention;
6415 }
6416
6417 /****************************************************************************
6418 Returns a sprite for the given indicator with the given index. The
6419 index should be in [0, NUM_TILES_PROGRESS).
6420 ****************************************************************************/
get_indicator_sprite(const struct tileset * t,enum indicator_type indicator,int idx)6421 struct sprite *get_indicator_sprite(const struct tileset *t,
6422 enum indicator_type indicator,
6423 int idx)
6424 {
6425 idx = CLIP(0, idx, NUM_TILES_PROGRESS - 1);
6426
6427 fc_assert_ret_val(indicator >= 0 && indicator < INDICATOR_COUNT, NULL);
6428
6429 return t->sprites.indicator[indicator][idx];
6430 }
6431
6432 /****************************************************************************
6433 Return a sprite for the unhappiness of the unit - to be shown as an
6434 overlay on the unit in the city support dialog, for instance.
6435
6436 May return NULL if there's no unhappiness.
6437 ****************************************************************************/
get_unit_unhappy_sprite(const struct tileset * t,const struct unit * punit,int happy_cost)6438 struct sprite *get_unit_unhappy_sprite(const struct tileset *t,
6439 const struct unit *punit,
6440 int happy_cost)
6441 {
6442 const int unhappy = CLIP(0, happy_cost, MAX_NUM_UPKEEP_SPRITES+1);
6443
6444 if (unhappy > 0) {
6445 return t->sprites.upkeep.unhappy[unhappy - 1];
6446 } else {
6447 return NULL;
6448 }
6449 }
6450
6451 /****************************************************************************
6452 Return a sprite for the upkeep of the unit - to be shown as an overlay
6453 on the unit in the city support dialog, for instance.
6454
6455 May return NULL if there's no upkeep of the kind.
6456 ****************************************************************************/
get_unit_upkeep_sprite(const struct tileset * t,Output_type_id otype,const struct unit * punit,const int * upkeep_cost)6457 struct sprite *get_unit_upkeep_sprite(const struct tileset *t,
6458 Output_type_id otype,
6459 const struct unit *punit,
6460 const int *upkeep_cost)
6461 {
6462 const int upkeep = CLIP(0, upkeep_cost[otype], MAX_NUM_UPKEEP_SPRITES + 1);
6463
6464 if (upkeep > 0) {
6465 return t->sprites.upkeep.output[otype][upkeep - 1];
6466 } else {
6467 return NULL;
6468 }
6469 }
6470
6471 /****************************************************************************
6472 Return a rectangular sprite containing a fog "color". This can be used
6473 for drawing fog onto arbitrary areas (like the overview).
6474 ****************************************************************************/
get_basic_fog_sprite(const struct tileset * t)6475 struct sprite *get_basic_fog_sprite(const struct tileset *t)
6476 {
6477 return t->sprites.tx.fog;
6478 }
6479
6480 /****************************************************************************
6481 Return the tileset's color system.
6482 ****************************************************************************/
get_color_system(const struct tileset * t)6483 struct color_system *get_color_system(const struct tileset *t)
6484 {
6485 return t->color_system;
6486 }
6487
6488 /****************************************************************************
6489 Loads preferred theme if there's any.
6490 ****************************************************************************/
tileset_use_preferred_theme(const struct tileset * t)6491 void tileset_use_preferred_theme(const struct tileset *t)
6492 {
6493 char *default_theme_name = NULL;
6494 size_t default_theme_name_sz = 0;
6495 int i;
6496
6497 switch (get_gui_type()) {
6498 case GUI_GTK2:
6499 default_theme_name = gui_options.gui_gtk2_default_theme_name;
6500 default_theme_name_sz = sizeof(gui_options.gui_gtk2_default_theme_name);
6501 break;
6502 case GUI_GTK3:
6503 default_theme_name = gui_options.gui_gtk3_default_theme_name;
6504 default_theme_name_sz = sizeof(gui_options.gui_gtk3_default_theme_name);
6505 break;
6506 case GUI_GTK3_22:
6507 default_theme_name = gui_options.gui_gtk3_22_default_theme_name;
6508 default_theme_name_sz = sizeof(gui_options.gui_gtk3_22_default_theme_name);
6509 break;
6510 case GUI_SDL:
6511 default_theme_name = gui_options.gui_sdl_default_theme_name;
6512 default_theme_name_sz = sizeof(gui_options.gui_sdl_default_theme_name);
6513 break;
6514 case GUI_SDL2:
6515 default_theme_name = gui_options.gui_sdl2_default_theme_name;
6516 default_theme_name_sz = sizeof(gui_options.gui_sdl2_default_theme_name);
6517 break;
6518 case GUI_STUB:
6519 case GUI_XAW:
6520 case GUI_QT:
6521 case GUI_WEB:
6522 break;
6523 }
6524
6525 if (NULL == default_theme_name || 0 == default_theme_name_sz) {
6526 /* Theme is not supported by this client. */
6527 return;
6528 }
6529
6530 for (i = 0; i < t->num_preferred_themes; i++) {
6531 if (strcmp(t->preferred_themes[i], default_theme_name)) {
6532 if (popup_theme_suggestion_dialog(t->preferred_themes[i])) {
6533 log_debug("trying theme \"%s\".", t->preferred_themes[i]);
6534 if (load_theme(t->preferred_themes[i])) {
6535 (void) fc_strlcpy(default_theme_name, t->preferred_themes[i],
6536 default_theme_name_sz);
6537 return;
6538 }
6539 }
6540 }
6541 }
6542 log_verbose("The tileset doesn't specify preferred themes or none of its "
6543 "preferred themes can be used. Using system default.");
6544 gui_clear_theme();
6545 }
6546
6547 /****************************************************************************
6548 Initialize tileset structure
6549 ****************************************************************************/
tileset_init(struct tileset * t)6550 void tileset_init(struct tileset *t)
6551 {
6552 int wi;
6553
6554 /* We currently have no city sprites loaded. */
6555 t->sprites.city.tile = NULL;
6556
6557 for (wi = 0; wi < NUM_WALL_TYPES; wi++) {
6558 t->sprites.city.wall[wi] = NULL;
6559 }
6560 t->sprites.city.single_wall = NULL;
6561
6562 t->sprites.city.occupied = NULL;
6563
6564 t->sprites.background.color = NULL;
6565 t->sprites.background.graphic = NULL;
6566
6567 player_slots_iterate(pslot) {
6568 int edge, j, id = player_slot_index(pslot);
6569
6570 for (edge = 0; edge < EDGE_COUNT; edge++) {
6571 for (j = 0; j < 2; j++) {
6572 t->sprites.player[id].grid_borders[edge][j] = NULL;
6573 }
6574 }
6575
6576 t->sprites.player[id].color = NULL;
6577 t->sprites.player[id].background = NULL;
6578 } player_slots_iterate_end;
6579
6580 t->max_upkeep_height = 0;
6581 }
6582
6583 /****************************************************************************
6584 Fill the sprite array with sprites that together make a representative
6585 image of the given terrain type. Suitable for use as an icon and in list
6586 views.
6587
6588 NB: The 'layer' argument is NOT a LAYER_* value, but rather one of 0, 1, 2.
6589 Using other values for 'layer' here will result in undefined behaviour. ;)
6590 ****************************************************************************/
fill_basic_terrain_layer_sprite_array(struct tileset * t,struct drawn_sprite * sprs,int layer,struct terrain * pterrain)6591 int fill_basic_terrain_layer_sprite_array(struct tileset *t,
6592 struct drawn_sprite *sprs,
6593 int layer,
6594 struct terrain *pterrain)
6595 {
6596 struct drawn_sprite *save_sprs = sprs;
6597 struct drawing_data *draw = t->sprites.drawing[terrain_index(pterrain)];
6598
6599 struct terrain *tterrain_near[8];
6600 bv_special tspecial_near[8];
6601
6602 struct tile dummy_tile; /* :( */
6603
6604 int i;
6605
6606
6607 memset(&dummy_tile, 0, sizeof(struct tile));
6608
6609 for (i = 0; i < 8; i++) {
6610 tterrain_near[i] = pterrain;
6611 BV_CLR_ALL(tspecial_near[i]);
6612 }
6613
6614 i = draw->is_reversed ? draw->num_layers - layer - 1 : layer;
6615 sprs += fill_terrain_sprite_array(t, sprs, i, &dummy_tile,
6616 pterrain, tterrain_near, draw);
6617
6618 return sprs - save_sprs;
6619 }
6620
6621 /****************************************************************************
6622 Return the sprite for the given resource type.
6623 ****************************************************************************/
get_resource_sprite(const struct tileset * t,const struct resource * presource)6624 struct sprite *get_resource_sprite(const struct tileset *t,
6625 const struct resource *presource)
6626 {
6627 if (presource == NULL) {
6628 return NULL;
6629 }
6630
6631 return t->sprites.resource[resource_index(presource)];
6632 }
6633
6634 /****************************************************************************
6635 Return a representative sprite for the given extra type.
6636 ****************************************************************************/
fill_basic_extra_sprite_array(const struct tileset * t,struct drawn_sprite * sprs,const struct extra_type * pextra)6637 int fill_basic_extra_sprite_array(const struct tileset *t,
6638 struct drawn_sprite *sprs,
6639 const struct extra_type *pextra)
6640 {
6641 int idx = extra_index(pextra);
6642 struct drawn_sprite *saved_sprs = sprs;
6643
6644 switch (t->sprites.extras[idx].extrastyle) {
6645 case ESTYLE_SINGLE1:
6646 case ESTYLE_SINGLE2:
6647 ADD_SPRITE_SIMPLE(t->sprites.extras[idx].u.single);
6648 break;
6649 case ESTYLE_CARDINALS:
6650 ADD_SPRITE_SIMPLE(t->sprites.extras[idx].u.cardinals[0]);
6651 break;
6652 case ESTYLE_ROAD_ALL_SEPARATE:
6653 case ESTYLE_ROAD_PARITY_COMBINED:
6654 case ESTYLE_ROAD_ALL_COMBINED:
6655 case ESTYLE_RIVER:
6656 return fill_basic_road_sprite_array(t, sprs, pextra);
6657 case ESTYLE_3LAYER:
6658 return fill_basic_base_sprite_array(t, sprs, pextra);
6659 case ESTYLE_COUNT:
6660 fc_assert(t->sprites.extras[idx].extrastyle != ESTYLE_COUNT);
6661 break;
6662 }
6663
6664 return sprs - saved_sprs;
6665 }
6666
6667 /****************************************************************************
6668 Fills the sprite array with sprites that together make a representative
6669 image of the given road type. The image is suitable for use as an icon
6670 for the road type, for example.
6671 ****************************************************************************/
fill_basic_road_sprite_array(const struct tileset * t,struct drawn_sprite * sprs,const struct extra_type * pextra)6672 int fill_basic_road_sprite_array(const struct tileset *t,
6673 struct drawn_sprite *sprs,
6674 const struct extra_type *pextra)
6675 {
6676 struct drawn_sprite *saved_sprs = sprs;
6677 int idx;
6678 int i;
6679 enum extrastyle_id extrastyle;
6680
6681 if (!t || !sprs || !pextra) {
6682 return 0;
6683 }
6684
6685 idx = extra_index(pextra);
6686
6687 if (!(0 <= idx && idx < game.control.num_extra_types)) {
6688 return 0;
6689 }
6690
6691 extrastyle = t->sprites.extras[idx].extrastyle;
6692
6693 if (extrastyle == ESTYLE_RIVER) {
6694 ADD_SPRITE_SIMPLE(t->sprites.extras[idx].u.road.ru.rivers.spec[0]);
6695 } else {
6696 for (i = 0; i < t->num_valid_tileset_dirs; i++) {
6697 if (!t->valid_tileset_dirs[i]) {
6698 continue;
6699 }
6700 if (extrastyle == ESTYLE_ROAD_ALL_SEPARATE) {
6701 ADD_SPRITE_SIMPLE(t->sprites.extras[idx].u.road.ru.dir[i]);
6702 } else if (extrastyle == ESTYLE_ROAD_PARITY_COMBINED) {
6703 if ((i % 2) == 0) {
6704 ADD_SPRITE_SIMPLE(t->sprites.extras[idx].u.road.ru.combo.even[1 << (i / 2)]);
6705 }
6706 } else if (extrastyle == ESTYLE_ROAD_ALL_COMBINED) {
6707 ADD_SPRITE_SIMPLE(t->sprites.extras[idx].u.road.ru.total[1 << i]);
6708 }
6709 }
6710 }
6711
6712 return sprs - saved_sprs;
6713 }
6714
6715 /****************************************************************************
6716 Fills the sprite array with sprites that together make a representative
6717 image of the given base type. The image is suitable for use as an icon
6718 for the base type, for example.
6719 ****************************************************************************/
fill_basic_base_sprite_array(const struct tileset * t,struct drawn_sprite * sprs,const struct extra_type * pextra)6720 int fill_basic_base_sprite_array(const struct tileset *t,
6721 struct drawn_sprite *sprs,
6722 const struct extra_type *pextra)
6723 {
6724 struct drawn_sprite *saved_sprs = sprs;
6725 int idx;
6726
6727 if (!t || !sprs || !pextra) {
6728 return 0;
6729 }
6730
6731 idx = extra_index(pextra);
6732
6733 if (!(0 <= idx && idx < game.control.num_extra_types)) {
6734 return 0;
6735 }
6736
6737 #define ADD_SPRITE_IF_NOT_NULL(x) do {\
6738 if ((x) != NULL) {\
6739 ADD_SPRITE_FULL(x);\
6740 }\
6741 } while (0)
6742
6743 /* Corresponds to LAYER_SPECIAL{1,2,3} order. */
6744 ADD_SPRITE_IF_NOT_NULL(t->sprites.extras[idx].u.bmf.background);
6745 ADD_SPRITE_IF_NOT_NULL(t->sprites.extras[idx].u.bmf.middleground);
6746 ADD_SPRITE_IF_NOT_NULL(t->sprites.extras[idx].u.bmf.foreground);
6747
6748 #undef ADD_SPRITE_IF_NOT_NULL
6749
6750 return sprs - saved_sprs;
6751 }
6752
6753 /****************************************************************************
6754 Setup tiles for one player using the player color.
6755 ****************************************************************************/
tileset_player_init(struct tileset * t,struct player * pplayer)6756 void tileset_player_init(struct tileset *t, struct player *pplayer)
6757 {
6758 int plrid, i, j;
6759 struct sprite *color;
6760
6761 fc_assert_ret(pplayer != NULL);
6762
6763 plrid = player_index(pplayer);
6764 fc_assert_ret(plrid >= 0);
6765 fc_assert_ret(plrid < ARRAY_SIZE(t->sprites.player));
6766
6767 /* Free all data before recreating it. */
6768 tileset_player_free(t, plrid);
6769
6770 if (player_has_color(t, pplayer)) {
6771 t->sprites.player[plrid].color = color
6772 = create_plr_sprite(get_player_color(t, pplayer));
6773 } else {
6774 /* XXX: if player hasn't been assigned a color, perhaps there's no
6775 * point proceeding with an arbitrary color; this should only happen
6776 * in pregame. Probably blank sprites would be better. */
6777
6778 fc_assert_ret(t->sprites.background.color != NULL);
6779
6780 color = t->sprites.background.color;
6781 }
6782
6783 t->sprites.player[plrid].background
6784 = crop_sprite(color, 0, 0,
6785 t->normal_tile_width, t->normal_tile_height,
6786 t->sprites.mask.tile, 0, 0, t->scale, FALSE);
6787
6788 for (i = 0; i < EDGE_COUNT; i++) {
6789 for (j = 0; j < 2; j++) {
6790 struct sprite *s;
6791
6792 if (color && t->sprites.grid.borders[i][j]) {
6793 s = crop_sprite(color, 0, 0,
6794 t->normal_tile_width, t->normal_tile_height,
6795 t->sprites.grid.borders[i][j], 0, 0, 1.0f, FALSE);
6796 } else {
6797 s = t->sprites.grid.borders[i][j];
6798 }
6799 t->sprites.player[plrid].grid_borders[i][j] = s;
6800 }
6801 }
6802 }
6803
6804 /****************************************************************************
6805 Free tiles for one player using the player color.
6806 ****************************************************************************/
tileset_player_free(struct tileset * t,int plrid)6807 static void tileset_player_free(struct tileset *t, int plrid)
6808 {
6809 int i, j;
6810
6811 fc_assert_ret(plrid >= 0);
6812 fc_assert_ret(plrid < ARRAY_SIZE(t->sprites.player));
6813
6814 if (t->sprites.player[plrid].color) {
6815 free_sprite(t->sprites.player[plrid].color);
6816 t->sprites.player[plrid].color = NULL;
6817 }
6818 if (t->sprites.player[plrid].background) {
6819 free_sprite(t->sprites.player[plrid].background);
6820 t->sprites.player[plrid].background = NULL;
6821 }
6822
6823 for (i = 0; i < EDGE_COUNT; i++) {
6824 for (j = 0; j < 2; j++) {
6825 if (t->sprites.player[plrid].grid_borders[i][j]) {
6826 free_sprite(t->sprites.player[plrid].grid_borders[i][j]);
6827 t->sprites.player[plrid].grid_borders[i][j] = NULL;
6828 }
6829 }
6830 }
6831 }
6832
6833 /****************************************************************************
6834 Setup tiles for the background.
6835 ****************************************************************************/
tileset_background_init(struct tileset * t)6836 void tileset_background_init(struct tileset *t)
6837 {
6838 /* Free all data before recreating it. */
6839 tileset_background_free(t);
6840
6841 /* generate background color */
6842 t->sprites.background.color
6843 = create_plr_sprite(ensure_color(game.plr_bg_color));
6844
6845 /* Chop up and build the background graphics. */
6846 t->sprites.background.graphic
6847 = crop_sprite(t->sprites.background.color, 0, 0,
6848 t->normal_tile_width, t->normal_tile_height,
6849 t->sprites.mask.tile, 0, 0, t->scale, FALSE);
6850 }
6851
6852 /****************************************************************************
6853 Free tiles for the background.
6854 ****************************************************************************/
tileset_background_free(struct tileset * t)6855 void tileset_background_free(struct tileset *t)
6856 {
6857 if (t->sprites.background.color) {
6858 free_sprite(t->sprites.background.color);
6859 t->sprites.background.color = NULL;
6860 }
6861
6862 if (t->sprites.background.graphic) {
6863 free_sprite(t->sprites.background.graphic);
6864 t->sprites.background.graphic = NULL;
6865 }
6866 }
6867
6868 /****************************************************************************
6869 Reset tileset data specific to ruleset.
6870 ****************************************************************************/
tileset_ruleset_reset(struct tileset * t)6871 void tileset_ruleset_reset(struct tileset *t)
6872 {
6873 int i;
6874
6875 for (i = 0; i < ESTYLE_COUNT; i++) {
6876 if (t->style_lists[i] != NULL) {
6877 extra_type_list_destroy(t->style_lists[i]);
6878 t->style_lists[i] = extra_type_list_new();
6879 }
6880 }
6881
6882 if (t->flagged_bases_list != NULL) {
6883 extra_type_list_destroy(t->flagged_bases_list);
6884 t->flagged_bases_list = extra_type_list_new();
6885 }
6886 }
6887
6888 /****************************************************************************
6889 Is tileset in sane state?
6890 ****************************************************************************/
tileset_is_fully_loaded(void)6891 bool tileset_is_fully_loaded(void)
6892 {
6893 return !tileset_update;
6894 }
6895
6896 /****************************************************************************
6897 Return tileset name
6898 ****************************************************************************/
tileset_name_get(struct tileset * t)6899 const char *tileset_name_get(struct tileset *t)
6900 {
6901 return t->given_name;
6902 }
6903
6904 /****************************************************************************
6905 Return tileset version
6906 ****************************************************************************/
tileset_version(struct tileset * t)6907 const char *tileset_version(struct tileset *t)
6908 {
6909 return t->version;
6910 }
6911
6912 /****************************************************************************
6913 Return tileset description summary
6914 ****************************************************************************/
tileset_summary(struct tileset * t)6915 const char *tileset_summary(struct tileset *t)
6916 {
6917 return t->summary;
6918 }
6919
6920 /****************************************************************************
6921 Return tileset description body
6922 ****************************************************************************/
tileset_description(struct tileset * t)6923 const char *tileset_description(struct tileset *t)
6924 {
6925 return t->description;
6926 }
6927
6928 /****************************************************************************
6929 Return tileset topology index
6930 ****************************************************************************/
tileset_topo_index(struct tileset * t)6931 int tileset_topo_index(struct tileset *t)
6932 {
6933 return t->ts_topo_idx;
6934 }
6935