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)
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 ***********************************************************************/
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 ***********************************************************************/
21 #include <fc_config.h>
25 #include <stdlib.h> /* exit */
31 #include "bitvector.h"
32 #include "capability.h"
39 #include "string_vector.h"
45 #include "game.h" /* game.control.styles_count */
46 #include "government.h"
52 #include "specialist.h"
57 #include "dialogs_g.h"
58 #include "graphics_g.h"
59 #include "gui_main_g.h"
60 #include "mapview_g.h" /* for update_map_canvas_visible */
65 #include "citydlg_common.h" /* for generate_citydlg_dimensions() */
66 #include "client_main.h"
67 #include "climap.h" /* for client_tile_get_known() */
68 #include "colors_common.h"
69 #include "control.h" /* for fill_xxx */
72 #include "options.h" /* for fill_xxx */
73 #include "themes_common.h"
77 #define TILESPEC_CAPSTR "+Freeciv-2.5-tilespec duplicates_ok"
79 * Tilespec capabilities acceptable to this program:
81 * +Freeciv-2.4-tilespec
82 * - basic format for Freeciv versions 2.4.x; required
84 * +Freeciv-tilespec-Devel-YYYY.MMM.DD
85 * - tilespec of the development version at the given data
88 * - we can handle existence of duplicate tags (lattermost tag which
89 * appears is used; tilesets which have duplicates should specify
93 #define SPEC_CAPSTR "+Freeciv-2.5-spec"
95 * Individual spec file capabilities acceptable to this program:
98 * - basic format for Freeciv versions 2.3.x; required
101 #define TILESPEC_SUFFIX ".tilespec"
102 #define TILE_SECTION_PREFIX "tile_"
104 /* This the way directional indices are now encoded: */
105 #define MAX_INDEX_CARDINAL 64
106 #define MAX_INDEX_HALF 16
107 #define MAX_INDEX_VALID 256
109 #define NUM_TILES_HP_BAR 11
110 #define NUM_TILES_DIGITS 10
111 #define NUM_TILES_SELECT 4
112 #define MAX_NUM_CITIZEN_SPRITES 6
113 #define MAX_NUM_UPKEEP_SPRITES 10
115 #define SPECENUM_NAME roadstyle_id
116 #define SPECENUM_VALUE0 RSTYLE_ALL_SEPARATE
117 #define SPECENUM_VALUE0NAME "AllSeparate"
118 #define SPECENUM_VALUE1 RSTYLE_PARITY_COMBINED
119 #define SPECENUM_VALUE1NAME "ParityCombined"
120 #define SPECENUM_VALUE2 RSTYLE_ALL_COMBINED
121 #define SPECENUM_VALUE2NAME "AllCombined"
122 #define SPECENUM_VALUE3 RSTYLE_RIVER
123 #define SPECENUM_VALUE3NAME "River"
124 #include "specenum_gen.h"
126 /* This could be moved to common/map.h if there's more use for it. */
128 DIR4_NORTH
= 0, DIR4_SOUTH
, DIR4_EAST
, DIR4_WEST
130 static const char direction4letters
[4] = "udrl";
131 /* This must correspond to enum edge_type. */
132 static const char edge_name
[EDGE_COUNT
][3] = {"ns", "we", "ud", "lr"};
134 static const int DIR4_TO_DIR8
[4] =
135 { DIR8_NORTH
, DIR8_SOUTH
, DIR8_EAST
, DIR8_WEST
};
139 MATCH_SAME
, /* "boolean" match */
145 CELL_WHOLE
, /* entire tile */
146 CELL_CORNER
/* corner of tile */
149 struct drawing_data
{
153 int num_layers
; /* 1 thru MAX_NUM_LAYERS. */
154 #define MAX_NUM_LAYERS 3
156 struct drawing_layer
{
158 int offset_x
, offset_y
;
160 #define MAX_NUM_MATCH_WITH 8
161 enum match_style match_style
;
162 int match_index
[1 + MAX_NUM_MATCH_WITH
];
163 int match_indices
; /* 0 = no match_type, 1 = no match_with */
165 enum sprite_type sprite_type
;
167 struct sprite_vector base
;
168 struct sprite
*match
[MAX_INDEX_CARDINAL
];
169 struct sprite
**cells
;
171 /* List of those sprites in 'cells' that are allocated by some other
172 * means than load_sprite() and thus are not freed by unload_all_sprites(). */
173 struct sprite_vector allocated
;
174 } layer
[MAX_NUM_LAYERS
];
178 int blending
; /* layer, 0 = none */
179 struct sprite
*blender
;
180 struct sprite
*blend
[4]; /* indexed by a direction4 */
185 struct city_style_threshold
{
186 struct sprite
*sprite
;
191 int land_num_thresholds
;
192 struct city_style_threshold
*land_thresholds
;
193 int oceanic_num_thresholds
;
194 struct city_style_threshold
*oceanic_thresholds
;
199 struct river_sprites
{
201 *spec
[MAX_INDEX_CARDINAL
],
202 *outlet
[4]; /* indexed by enum direction4 */
205 struct named_sprites
{
207 *indicator
[INDICATOR_COUNT
][NUM_TILES_PROGRESS
],
208 *treaty_thumb
[2], /* 0=disagree, 1=agree */
209 *arrow
[ARROW_LAST
], /* 0=right arrow, 1=plus, 2=minus */
213 /* The panel sprites for showing tax % allocations. */
214 *tax_luxury
, *tax_science
, *tax_gold
,
215 *dither_tile
; /* only used for isometric view */
224 struct sprite
*tech
[A_LAST
];
225 struct sprite
*building
[B_LAST
];
226 struct sprite
*government
[G_MAGIC
];
229 struct sprite
*icon
[U_LAST
];
230 struct sprite
*facing
[U_LAST
][DIR8_MAGIC_MAX
];
233 struct sprite
*resource
[MAX_NUM_RESOURCES
];
235 struct sprite_vector nation_flag
;
236 struct sprite_vector nation_shield
;
238 struct citizen_graphic
{
239 /* Each citizen type has up to MAX_NUM_CITIZEN_SPRITES different
240 * sprites, as defined by the tileset. */
242 struct sprite
*sprite
[MAX_NUM_CITIZEN_SPRITES
];
243 } citizen
[CITIZEN_LAST
], specialist
[SP_MAX
];
244 struct sprite
*spaceship
[SPACESHIP_COUNT
];
247 struct sprite
*frame
[NUM_CURSOR_FRAMES
];
248 } cursor
[CURSOR_LAST
];
250 enum roadstyle_id roadstyle
;
253 /* for roadstyles RSTYLE_ALL_SEPARATE and RSTYLE_PARITY_COMBINED */
255 *corner
[8]; /* Indexed by direction; only non-cardinal dirs used. */
257 /* for RSTYLE_ALL_SEPARATE */
258 struct sprite
*dir
[8]; /* all entries used */
259 /* RSTYLE_PARITY_COMBINED */
262 *even
[MAX_INDEX_HALF
], /* first unused */
263 *odd
[MAX_INDEX_HALF
]; /* first unused */
265 /* RSTYLE_ALL_SEPARATE */
266 struct sprite
*total
[MAX_INDEX_VALID
];
267 struct river_sprites rivers
;
269 } roads
[MAX_ROAD_TYPES
];
271 struct sprite_vector unit
;
276 *hp_bar
[NUM_TILES_HP_BAR
],
277 *vet_lev
[MAX_VET_LEVELS
],
278 *select
[NUM_TILES_SELECT
],
285 *go_to
, /* goto is a C keyword :-) */
297 *battlegroup
[MAX_NUM_BATTLEGROUPS
],
303 *unhappy
[MAX_NUM_UPKEEP_SPRITES
],
304 *output
[O_LAST
][MAX_NUM_UPKEEP_SPRITES
];
309 *size
[NUM_TILES_DIGITS
],
310 *size_tens
[NUM_TILES_DIGITS
],
311 *size_hundreds
[NUM_TILES_DIGITS
],
312 *tile_foodnum
[NUM_TILES_DIGITS
],
313 *tile_shieldnum
[NUM_TILES_DIGITS
],
314 *tile_tradenum
[NUM_TILES_DIGITS
];
319 struct sprite_vector worked_tile_overlay
;
320 struct sprite_vector unworked_tile_overlay
;
322 struct citybar_sprites citybar
;
323 struct editor_sprites editor
;
326 *turns
[NUM_TILES_DIGITS
],
327 *turns_tens
[NUM_TILES_DIGITS
],
328 *turns_hundreds
[NUM_TILES_DIGITS
];
331 struct sprite
*attention
;
335 *farmland
[MAX_INDEX_CARDINAL
],
336 *irrigation
[MAX_INDEX_CARDINAL
],
342 *darkness
[MAX_INDEX_CARDINAL
]; /* first unused */
343 } tx
; /* terrain extra */
350 } bases
[MAX_BASE_TYPES
];
358 *selected
[EDGE_COUNT
],
359 *coastline
[EDGE_COUNT
],
360 *borders
[EDGE_COUNT
][2];
363 struct sprite_vector overlays
;
366 struct sprite
*color
; /* Generic background color */
367 struct sprite
*graphic
; /* Generic background graphic */
370 struct sprite
*grid_borders
[EDGE_COUNT
][2];
371 struct sprite
*color
;
372 struct sprite
*background
;
373 } player
[MAX_NUM_PLAYER_SLOTS
];
375 struct drawing_data
*drawing
[MAX_NUM_ITEMS
];
378 /* Don't reorder this enum since tilesets depend on it. */
380 FOG_AUTO
, /* Fog is automatically appended by the code. */
381 FOG_SPRITE
, /* A single fog sprite is provided by the tileset (tx.fog). */
382 FOG_NONE
/* No fog. */
385 /* Darkness style. Don't reorder this enum since tilesets depend on it. */
386 enum darkness_style
{
387 /* No darkness sprites are drawn. */
390 /* 1 sprite that is split into 4 parts and treated as a darkness4. Only
391 * works in iso-view. */
392 DARKNESS_ISORECT
= 1,
394 /* 4 sprites, one per direction. More than one sprite per tile may be
396 DARKNESS_CARD_SINGLE
= 2,
398 /* 15=2^4-1 sprites. A single sprite is drawn, chosen based on whether
399 * there's darkness in _each_ of the cardinal directions. */
400 DARKNESS_CARD_FULL
= 3,
402 /* Corner darkness & fog. 3^4 = 81 sprites. */
407 struct sprite
*big_sprite
;
411 #define SPECLIST_TAG specfile
412 #define SPECLIST_TYPE struct specfile
413 #include "speclist.h"
415 #define specfile_list_iterate(list, pitem) \
416 TYPED_LIST_ITERATE(struct specfile, list, pitem)
417 #define specfile_list_iterate_end LIST_ITERATE_END
420 * Information about an individual sprite. All fields except 'sprite' are
421 * filled at the time of the scan of the specfile. 'Sprite' is
422 * set/cleared on demand in load_sprite/unload_sprite.
424 struct small_sprite
{
427 /* The sprite is in this file. */
430 /* Or, the sprite is in this file at the location. */
432 int x
, y
, width
, height
;
434 /* A little more (optional) data. */
437 struct sprite
*sprite
;
440 /* 'struct small_sprite_list' and related functions. */
441 #define SPECLIST_TAG small_sprite
442 #define SPECLIST_TYPE struct small_sprite
443 #include "speclist.h"
444 #define small_sprite_list_iterate(list, pitem) \
445 TYPED_LIST_ITERATE(struct small_sprite, list, pitem)
446 #define small_sprite_list_iterate_end LIST_ITERATE_END
448 /* 'struct sprite_hash' and related functions. */
449 #define SPECHASH_TAG sprite
450 #define SPECHASH_KEY_TYPE char *
451 #define SPECHASH_DATA_TYPE struct small_sprite *
452 #define SPECHASH_KEY_VAL genhash_str_val_func
453 #define SPECHASH_KEY_COMP genhash_str_comp_func
454 #define SPECHASH_KEY_COPY genhash_str_copy_func
455 #define SPECHASH_KEY_FREE genhash_str_free_func
456 #include "spechash.h"
457 #define sprite_hash_iterate(hash, tag_name, sprite) \
458 TYPED_HASH_ITERATE(const char *, struct small_sprite *, \
459 hash, tag_name, sprite)
460 #define sprite_hash_iterate_end HASH_ITERATE_END
462 /* 'struct drawing_hash' and related functions. */
463 static void drawing_data_destroy(struct drawing_data
*draw
);
465 #define SPECHASH_TAG drawing
466 #define SPECHASH_KEY_TYPE char *
467 #define SPECHASH_DATA_TYPE struct drawing_data *
468 #define SPECHASH_KEY_VAL genhash_str_val_func
469 #define SPECHASH_KEY_COMP genhash_str_comp_func
470 #define SPECHASH_DATA_FREE drawing_data_destroy
471 #include "spechash.h"
473 #define SPECHASH_TAG rstyle
474 #define SPECHASH_KEY_TYPE char *
475 #define SPECHASH_DATA_TYPE enum roadstyle_id *
476 #define SPECHASH_KEY_VAL genhash_str_val_func
477 #define SPECHASH_KEY_COMP genhash_str_comp_func
478 #include "spechash.h"
480 enum ts_type
{ TS_OVERVIEW
, TS_ISOMETRIC
};
487 int hex_width
, hex_height
;
489 int normal_tile_width
, normal_tile_height
;
490 int full_tile_width
, full_tile_height
;
491 int unit_tile_width
, unit_tile_height
;
492 int small_sprite_width
, small_sprite_height
;
494 char *main_intro_filename
;
495 char *minimap_intro_filename
;
497 int city_names_font_size
, city_productions_font_size
;
499 enum fog_style fogstyle
;
500 enum darkness_style darkness_style
;
503 int unit_flag_offset_x
, unit_flag_offset_y
;
504 int city_flag_offset_x
, city_flag_offset_y
;
505 int unit_offset_x
, unit_offset_y
;
507 int citybar_offset_y
;
508 int tilelabel_offset_y
;
510 #define NUM_CORNER_DIRS 4
511 #define TILES_PER_CORNER 4
512 int num_valid_tileset_dirs
, num_cardinal_tileset_dirs
;
513 int num_index_valid
, num_index_cardinal
;
514 enum direction8 valid_tileset_dirs
[8], cardinal_tileset_dirs
[8];
516 struct tileset_layer
{
519 } layers
[MAX_NUM_LAYERS
];
521 struct specfile_list
*specfiles
;
522 struct small_sprite_list
*small_sprites
;
524 /* This hash table maps tilespec tags to struct small_sprites. */
525 struct sprite_hash
*sprite_hash
;
527 /* This hash table maps terrain graphic strings to drawing data. */
528 struct drawing_hash
*tile_hash
;
530 struct rstyle_hash
*rstyle_hash
;
532 struct named_sprites sprites
;
534 struct color_system
*color_system
;
536 struct road_type_list
*rivers
;
538 int num_prefered_themes
;
539 char** prefered_themes
;
542 struct tileset
*tileset
;
544 int focus_unit_state
= 0;
547 static int fill_unit_type_sprite_array(const struct tileset
*t
,
548 struct drawn_sprite
*sprs
,
549 const struct unit_type
*putype
,
550 enum direction8 facing
);
551 static int fill_unit_sprite_array(const struct tileset
*t
,
552 struct drawn_sprite
*sprs
,
553 const struct unit
*punit
,
554 bool stack
, bool backdrop
);
555 static bool load_river_sprites(struct tileset
*t
,
556 struct river_sprites
*store
, const char *tag_pfx
);
558 /****************************************************************************
559 Called when ever there's problem in ruleset/tileset compatibility
560 ****************************************************************************/
561 static void tileset_error(enum log_level level
, const char *format
, ...)
566 va_start(args
, format
);
567 fc_vsnprintf(buf
, sizeof(buf
), format
, args
);
570 show_tileset_error(buf
);
572 if (level
== LOG_FATAL
) {
577 /****************************************************************************
578 Create a new drawing data.
579 ****************************************************************************/
580 static struct drawing_data
*drawing_data_new(const char *name
)
582 struct drawing_data
*draw
= fc_calloc(1, sizeof(*draw
));
584 draw
->name
= fc_strdup(name
);
588 /****************************************************************************
590 ****************************************************************************/
591 static void drawing_data_destroy(struct drawing_data
*draw
)
595 fc_assert_ret(NULL
!= draw
);
598 if (NULL
!= draw
->mine_tag
) {
599 free(draw
->mine_tag
);
601 for (i
= 0; i
< 4; i
++) {
602 if (draw
->blend
[i
]) {
603 free_sprite(draw
->blend
[i
]);
606 for (i
= 0; i
< draw
->num_layers
; i
++) {
607 int vec_size
= sprite_vector_size(&draw
->layer
[i
].allocated
);
610 for (j
= 0; j
< vec_size
; j
++) {
611 free_sprite(draw
->layer
[i
].allocated
.p
[j
]);
614 sprite_vector_free(&draw
->layer
[i
].base
);
615 sprite_vector_free(&draw
->layer
[i
].allocated
);
620 /****************************************************************************
621 Return the name of the given tileset.
622 ****************************************************************************/
623 const char *tileset_get_name(const struct tileset
*t
)
628 /****************************************************************************
629 Return whether the current tileset is isometric.
630 ****************************************************************************/
631 bool tileset_is_isometric(const struct tileset
*t
)
633 return t
->type
== TS_ISOMETRIC
;
636 /****************************************************************************
637 Return the hex_width of the current tileset. For hex tilesets this value
638 will be > 0 and is_isometric will be set.
639 ****************************************************************************/
640 int tileset_hex_width(const struct tileset
*t
)
645 /****************************************************************************
646 Return the hex_height of the current tileset. For iso-hex tilesets this
647 value will be > 0 and is_isometric will be set.
648 ****************************************************************************/
649 int tileset_hex_height(const struct tileset
*t
)
651 return t
->hex_height
;
654 /****************************************************************************
655 Return the tile width of the current tileset. This is the tesselation
656 width of the tiled plane. This means it's the width of the bounding box
657 of the basic map tile.
660 - The value should be even (or a multiple of 4 in iso-view).
661 - In iso-view, the width should be twice the height (to give a
662 perspective of 30 degrees above the horizon).
663 - In non-iso-view, width and height should be equal (overhead
665 - In hex or iso-hex view, remember this is the tesselation vector.
666 hex_width and hex_height then give the size of the side of the
667 hexagon. Calculating the dimensions of a "regular" hexagon or
668 iso-hexagon may be tricky.
669 However these requirements are not absolute and callers should not
670 depend on them (although some do).
671 ****************************************************************************/
672 int tileset_tile_width(const struct tileset
*t
)
674 return t
->normal_tile_width
;
677 /****************************************************************************
678 Return the tile height of the current tileset. This is the tesselation
679 height of the tiled plane. This means it's the height of the bounding box
680 of the basic map tile.
682 See also tileset_tile_width.
683 ****************************************************************************/
684 int tileset_tile_height(const struct tileset
*t
)
686 return t
->normal_tile_height
;
689 /****************************************************************************
690 Return the full tile width of the current tileset. This is the maximum
691 width that any mapview sprite will have.
693 Note: currently this is always equal to the tile width.
694 ****************************************************************************/
695 int tileset_full_tile_width(const struct tileset
*t
)
697 return t
->full_tile_width
;
700 /****************************************************************************
701 Return the full tile height of the current tileset. This is the maximum
702 height that any mapview sprite will have. This may be greater than the
703 tile width in which case the extra area is above the "normal" tile.
705 Some callers assume the full height is 50% larger than the height in
706 iso-view, and equal in non-iso view.
707 ****************************************************************************/
708 int tileset_full_tile_height(const struct tileset
*t
)
710 return t
->full_tile_height
;
713 /****************************************************************************
714 Return the unit tile width of the current tileset.
715 ****************************************************************************/
716 int tileset_unit_width(const struct tileset
*t
)
718 return t
->unit_tile_width
;
721 /****************************************************************************
722 Return the unit tile height of the current tileset.
723 ****************************************************************************/
724 int tileset_unit_height(const struct tileset
*t
)
726 return t
->unit_tile_height
;
729 /****************************************************************************
730 Return the small sprite width of the current tileset. The small sprites
731 are used for various theme graphics (e.g., citymap citizens/specialists
732 as well as panel indicator icons).
733 ****************************************************************************/
734 int tileset_small_sprite_width(const struct tileset
*t
)
736 return t
->small_sprite_width
;
739 /****************************************************************************
740 Return the offset from the origin of the city tile at which to place the
742 ****************************************************************************/
743 int tileset_citybar_offset_y(const struct tileset
*t
)
745 return t
->citybar_offset_y
;
748 /****************************************************************************
749 Return the offset from the origin of the tile at which to place the
751 ****************************************************************************/
752 int tileset_tilelabel_offset_y(const struct tileset
*t
)
754 return t
->tilelabel_offset_y
;
757 /****************************************************************************
758 Return the small sprite height of the current tileset. The small sprites
759 are used for various theme graphics (e.g., citymap citizens/specialists
760 as well as panel indicator icons).
761 ****************************************************************************/
762 int tileset_small_sprite_height(const struct tileset
*t
)
764 return t
->small_sprite_height
;
767 /****************************************************************************
768 Return the path within the data directories where the main intro graphics
769 file can be found. (It is left up to the GUI code to load and unload this
771 ****************************************************************************/
772 const char *tileset_main_intro_filename(const struct tileset
*t
)
774 return t
->main_intro_filename
;
777 /****************************************************************************
778 Return the path within the data directories where the mini intro graphics
779 file can be found. (It is left up to the GUI code to load and unload this
781 ****************************************************************************/
782 const char *tileset_mini_intro_filename(const struct tileset
*t
)
784 return t
->minimap_intro_filename
;
787 /****************************************************************************
788 Return the number of possible colors for city overlays.
789 ****************************************************************************/
790 int tileset_num_city_colors(const struct tileset
*t
)
792 return t
->sprites
.city
.worked_tile_overlay
.size
;
795 /****************************************************************************
796 Return TRUE if the client will use the code to generate the fog.
797 ****************************************************************************/
798 bool tileset_use_hard_coded_fog(const struct tileset
*t
)
800 return FOG_AUTO
== t
->fogstyle
;
803 /**************************************************************************
805 **************************************************************************/
806 static struct tileset
*tileset_new(void)
808 struct tileset
*t
= fc_calloc(1, sizeof(*t
));
810 t
->specfiles
= specfile_list_new();
811 t
->small_sprites
= small_sprite_list_new();
815 /**************************************************************************
816 Return the tileset name of the direction. This is similar to
817 dir_get_name but you shouldn't change this or all tilesets will break.
818 **************************************************************************/
819 static const char *dir_get_tileset_name(enum direction8 dir
)
839 log_error("Wrong direction8 variant: %d.", dir
);
843 /****************************************************************************
844 Return TRUE iff the dir is valid in this tileset.
845 ****************************************************************************/
846 static bool is_valid_tileset_dir(const struct tileset
*t
,
849 if (t
->hex_width
> 0) {
850 return dir
!= DIR8_NORTHEAST
&& dir
!= DIR8_SOUTHWEST
;
851 } else if (t
->hex_height
> 0) {
852 return dir
!= DIR8_NORTHWEST
&& dir
!= DIR8_SOUTHEAST
;
858 /****************************************************************************
859 Return TRUE iff the dir is cardinal in this tileset.
861 "Cardinal", in this sense, means that a tile will share a border with
862 another tile in the direction rather than sharing just a single vertex.
863 ****************************************************************************/
864 static bool is_cardinal_tileset_dir(const struct tileset
*t
,
867 if (t
->hex_width
> 0 || t
->hex_height
> 0) {
868 return is_valid_tileset_dir(t
, dir
);
870 return (dir
== DIR8_NORTH
|| dir
== DIR8_EAST
871 || dir
== DIR8_SOUTH
|| dir
== DIR8_WEST
);
875 /**********************************************************************
876 Returns a static list of tilesets available on the system by
877 searching all data directories for files matching TILESPEC_SUFFIX.
878 ***********************************************************************/
879 const struct strvec
*get_tileset_list(void)
881 static struct strvec
*tilesets
= NULL
;
884 /* Note: this means you must restart the client after installing a new
886 struct strvec
*list
= fileinfolist(get_data_dirs(), TILESPEC_SUFFIX
);
888 tilesets
= strvec_new();
889 strvec_iterate(list
, file
) {
890 struct tileset
*t
= tileset_read_toplevel(file
, FALSE
);
893 strvec_append(tilesets
, file
);
896 } strvec_iterate_end
;
897 strvec_destroy(list
);
903 /**********************************************************************
904 Gets full filename for tilespec file, based on input name.
905 Returned data is allocated, and freed by user as required.
906 Input name may be null, in which case uses default.
907 Falls back to default if can't find specified name;
908 dies if can't find default.
909 ***********************************************************************/
910 static char *tilespec_fullname(const char *tileset_name
)
913 char fname
[strlen(tileset_name
) + strlen(TILESPEC_SUFFIX
) + 1];
916 fc_snprintf(fname
, sizeof(fname
),
917 "%s%s", tileset_name
, TILESPEC_SUFFIX
);
919 dname
= fileinfoname(get_data_dirs(), fname
);
922 return fc_strdup(dname
);
929 /**********************************************************************
930 Checks options in filename match what we require and support.
932 'which' should be "tilespec" or "spec".
933 ***********************************************************************/
934 static bool check_tilespec_capabilities(struct section_file
*file
,
936 const char *us_capstr
,
937 const char *filename
,
940 enum log_level level
= verbose
? LOG_ERROR
: LOG_DEBUG
;
942 const char *file_capstr
= secfile_lookup_str(file
, "%s.options", which
);
944 if (NULL
== file_capstr
) {
945 log_base(level
, "\"%s\": %s file doesn't have a capability string",
949 if (!has_capabilities(us_capstr
, file_capstr
)) {
950 log_base(level
, "\"%s\": %s file appears incompatible:",
952 log_base(level
, " datafile options: %s", file_capstr
);
953 log_base(level
, " supported options: %s", us_capstr
);
956 if (!has_capabilities(file_capstr
, us_capstr
)) {
957 log_base(level
, "\"%s\": %s file requires option(s) "
958 "that client doesn't support:", filename
, which
);
959 log_base(level
, " datafile options: %s", file_capstr
);
960 log_base(level
, " supported options: %s", us_capstr
);
967 /**********************************************************************
968 Frees the tilespec toplevel data, in preparation for re-reading it.
970 See tilespec_read_toplevel().
971 ***********************************************************************/
972 static void tileset_free_toplevel(struct tileset
*t
)
976 if (t
->main_intro_filename
) {
977 free(t
->main_intro_filename
);
978 t
->main_intro_filename
= NULL
;
980 if (t
->minimap_intro_filename
) {
981 free(t
->minimap_intro_filename
);
982 t
->minimap_intro_filename
= NULL
;
985 if (t
->prefered_themes
) {
986 for (i
= 0; i
< t
->num_prefered_themes
; i
++) {
987 free(t
->prefered_themes
[i
]);
989 free(t
->prefered_themes
);
990 t
->prefered_themes
= NULL
;
992 t
->num_prefered_themes
= 0;
995 drawing_hash_destroy(t
->tile_hash
);
996 t
->tile_hash
= NULL
; /* Helpful for sanity. */
998 if (t
->rstyle_hash
) {
999 rstyle_hash_destroy(t
->rstyle_hash
);
1000 t
->rstyle_hash
= NULL
;
1002 if (t
->rivers
!= NULL
) {
1003 road_type_list_destroy(t
->rivers
);
1007 for (i
= 0; i
< MAX_NUM_LAYERS
; i
++) {
1008 struct tileset_layer
*tslp
= &t
->layers
[i
];
1010 if (tslp
->match_types
) {
1011 for (j
= 0; j
< tslp
->match_count
; j
++) {
1012 free(tslp
->match_types
[j
]);
1014 free(tslp
->match_types
);
1015 tslp
->match_types
= NULL
;
1019 if (t
->color_system
) {
1020 color_system_free(t
->color_system
);
1021 t
->color_system
= NULL
;
1025 /**************************************************************************
1027 **************************************************************************/
1028 void tileset_free(struct tileset
*t
)
1030 tileset_free_tiles(t
);
1031 tileset_free_toplevel(t
);
1032 players_iterate(pplayer
) {
1033 tileset_player_free(t
, pplayer
);
1034 } players_iterate_end
;
1035 specfile_list_destroy(t
->specfiles
);
1036 small_sprite_list_destroy(t
->small_sprites
);
1040 /**********************************************************************
1041 Read a new tilespec in when first starting the game.
1043 Call this function with the (guessed) name of the tileset, when
1044 starting the client.
1045 ***********************************************************************/
1046 void tilespec_try_read(const char *tileset_name
, bool verbose
)
1048 if (!(tileset
= tileset_read_toplevel(tileset_name
, verbose
))) {
1049 struct strvec
*list
= fileinfolist(get_data_dirs(), TILESPEC_SUFFIX
);
1051 strvec_iterate(list
, file
) {
1052 struct tileset
*t
= tileset_read_toplevel(file
, FALSE
);
1057 } else if (t
->priority
> tileset
->priority
) {
1058 tileset_free(tileset
);
1064 } strvec_iterate_end
;
1065 strvec_destroy(list
);
1068 tileset_error(LOG_FATAL
, _("No usable default tileset found, aborting!"));
1071 log_verbose("Trying tileset \"%s\".", tileset
->name
);
1073 sz_strlcpy(default_tileset_name
, tileset_get_name(tileset
));
1076 /**********************************************************************
1077 Read a new tilespec in from scratch.
1079 Unlike the initial reading code, which reads pieces one at a time,
1080 this gets rid of the old data and reads in the new all at once. If the
1081 new tileset fails to load the old tileset may be reloaded; otherwise the
1082 client will exit. If a NULL name is given the current tileset will be
1085 It will also call the necessary functions to redraw the graphics.
1086 ***********************************************************************/
1087 void tilespec_reread(const char *new_tileset_name
, bool game_fully_initialized
)
1090 struct tile
*center_tile
;
1091 enum client_states state
= client_state();
1092 const char *name
= new_tileset_name
? new_tileset_name
: tileset
->name
;
1093 char tileset_name
[strlen(name
) + 1], old_name
[strlen(tileset
->name
) + 1];
1095 /* Make local copies since these values may be freed down below */
1096 sz_strlcpy(tileset_name
, name
);
1097 sz_strlcpy(old_name
, tileset
->name
);
1099 log_normal(_("Loading tileset \"%s\"."), tileset_name
);
1101 /* Step 0: Record old data.
1103 * We record the current mapcanvas center, etc.
1105 center_tile
= get_center_tile_mapcanvas();
1109 * We free all old data in preparation for re-reading it.
1111 tileset_free_tiles(tileset
);
1112 tileset_free_toplevel(tileset
);
1113 players_iterate(pplayer
) {
1114 tileset_player_free(tileset
, pplayer
);
1115 } players_iterate_end
;
1119 * We read in the new tileset. This should be pretty straightforward.
1121 if (!(tileset
= tileset_read_toplevel(tileset_name
, FALSE
))) {
1122 if (!(tileset
= tileset_read_toplevel(old_name
, FALSE
))) {
1124 fc_assert_exit_msg(NULL
!= tileset
,
1125 "Failed to re-read the currently loaded tileset.");
1128 sz_strlcpy(default_tileset_name
, tileset
->name
);
1129 tileset_load_tiles(tileset
);
1130 tileset_use_prefered_theme(tileset
);
1132 if (game_fully_initialized
) {
1133 players_iterate(pplayer
) {
1134 tileset_player_init(tileset
, pplayer
);
1135 } players_iterate_end
;
1136 tileset_background_init(tileset
);
1141 * This is a seriously sticky problem. On startup, we build a hash
1142 * from all the sprite data. Then, when we connect to a server, the
1143 * server sends us ruleset data a piece at a time and we use this data
1144 * to assemble the sprite structures. But if we change while connected
1145 * we have to reassemble all of these. This should just involve
1146 * calling tilespec_setup_*** on everything. But how do we tell what
1149 * The below code just does things straightforwardly, by setting up
1150 * each possible sprite again. Hopefully it catches everything, and
1151 * doesn't mess up too badly if we change tilesets while not connected
1154 if (state
< C_S_RUNNING
) {
1155 /* The ruleset data is not sent until this point. */
1158 terrain_type_iterate(pterrain
) {
1159 tileset_setup_tile_type(tileset
, pterrain
);
1160 } terrain_type_iterate_end
;
1161 resource_type_iterate(presource
) {
1162 tileset_setup_resource(tileset
, presource
);
1163 } resource_type_iterate_end
;
1164 unit_type_iterate(punittype
) {
1165 tileset_setup_unit_type(tileset
, punittype
);
1166 } unit_type_iterate_end
;
1167 governments_iterate(gov
) {
1168 tileset_setup_government(tileset
, gov
);
1169 } governments_iterate_end
;
1170 road_type_iterate(proad
) {
1171 tileset_setup_road(tileset
, proad
);
1172 } road_type_iterate_end
;
1173 base_type_iterate(pbase
) {
1174 tileset_setup_base(tileset
, pbase
);
1175 } base_type_iterate_end
;
1176 nations_iterate(pnation
) {
1177 tileset_setup_nation_flag(tileset
, pnation
);
1178 } nations_iterate_end
;
1179 improvement_iterate(pimprove
) {
1180 tileset_setup_impr_type(tileset
, pimprove
);
1181 } improvement_iterate_end
;
1182 advance_iterate(A_FIRST
, padvance
) {
1183 tileset_setup_tech_type(tileset
, padvance
);
1184 } advance_iterate_end
;
1185 specialist_type_iterate(sp
) {
1186 tileset_setup_specialist_type(tileset
, sp
);
1187 } specialist_type_iterate_end
;
1189 for (id
= 0; id
< game
.control
.styles_count
; id
++) {
1190 tileset_setup_city_tiles(tileset
, id
);
1195 * Do any necessary redraws.
1197 generate_citydlg_dimensions();
1200 center_tile_mapcanvas(center_tile
);
1201 /* update_map_canvas_visible forces a full redraw. Otherwise with fast
1202 * drawing we might not get one. Of course this is slower. */
1203 update_map_canvas_visible();
1207 /**************************************************************************
1208 This is merely a wrapper for tilespec_reread (above) for use in
1209 options.c and the client local options dialog.
1210 **************************************************************************/
1211 void tilespec_reread_callback(struct option
*poption
)
1213 const char *tileset_name
= option_str_get(poption
);
1215 fc_assert_ret(NULL
!= tileset_name
&& tileset_name
[0] != '\0');
1216 tilespec_reread(tileset_name
, TRUE
);
1220 /**************************************************************************
1221 Loads the given graphics file (found in the data path) into a newly
1223 **************************************************************************/
1224 static struct sprite
*load_gfx_file(const char *gfx_filename
)
1226 const char **gfx_fileexts
= gfx_fileextensions(), *gfx_fileext
;
1229 /* Try out all supported file extensions to find one that works. */
1230 while ((gfx_fileext
= *gfx_fileexts
++)) {
1231 const char *real_full_name
;
1232 char full_name
[strlen(gfx_filename
) + strlen(gfx_fileext
) + 2];
1234 sprintf(full_name
, "%s.%s", gfx_filename
, gfx_fileext
);
1235 if ((real_full_name
= fileinfoname(get_data_dirs(), full_name
))) {
1236 log_debug("trying to load gfx file \"%s\".", real_full_name
);
1237 s
= load_gfxfile(real_full_name
);
1244 log_error("Could not load gfx file \"%s\".", gfx_filename
);
1248 /**************************************************************************
1249 Ensure that the big sprite of the given spec file is loaded.
1250 **************************************************************************/
1251 static void ensure_big_sprite(struct specfile
*sf
)
1253 struct section_file
*file
;
1254 const char *gfx_filename
;
1256 if (sf
->big_sprite
) {
1257 /* Looks like it's already loaded. */
1261 /* Otherwise load it. The big sprite will sometimes be freed and will have
1262 * to be reloaded, but most of the time it's just loaded once, the small
1263 * sprites are extracted, and then it's freed. */
1264 if (!(file
= secfile_load(sf
->file_name
, TRUE
))) {
1265 tileset_error(LOG_FATAL
, _("Could not open '%s':\n%s"), sf
->file_name
, secfile_error());
1268 if (!check_tilespec_capabilities(file
, "spec",
1269 SPEC_CAPSTR
, sf
->file_name
, TRUE
)) {
1270 tileset_error(LOG_FATAL
, _("Incompatible tileset capabilities"));
1273 gfx_filename
= secfile_lookup_str(file
, "file.gfx");
1275 sf
->big_sprite
= load_gfx_file(gfx_filename
);
1277 if (!sf
->big_sprite
) {
1278 tileset_error(LOG_FATAL
, _("Could not load gfx file for the spec file \"%s\"."),
1281 secfile_destroy(file
);
1284 /**************************************************************************
1285 Scan all sprites declared in the given specfile. This means that the
1286 positions of the sprites in the big_sprite are saved in the
1287 small_sprite structs.
1288 **************************************************************************/
1289 static void scan_specfile(struct tileset
*t
, struct specfile
*sf
,
1292 struct section_file
*file
;
1293 struct section_list
*sections
;
1296 if (!(file
= secfile_load(sf
->file_name
, TRUE
))) {
1297 tileset_error(LOG_FATAL
, _("Could not open '%s':\n%s"), sf
->file_name
, secfile_error());
1299 if (!check_tilespec_capabilities(file
, "spec",
1300 SPEC_CAPSTR
, sf
->file_name
, TRUE
)) {
1301 tileset_error(LOG_FATAL
, _("Specfile %s has incompatible capabilities"), sf
->file_name
);
1304 /* currently unused */
1305 (void) secfile_entry_lookup(file
, "info.artists");
1307 if ((sections
= secfile_sections_by_name_prefix(file
, "grid_"))) {
1308 section_list_iterate(sections
, psection
) {
1310 int x_top_left
, y_top_left
, dx
, dy
;
1312 const char *sec_name
= section_name(psection
);
1314 pixel_border
= secfile_lookup_int_default(file
, 0, "%s.pixel_border",
1317 if (!secfile_lookup_int(file
, &x_top_left
, "%s.x_top_left", sec_name
)
1318 || !secfile_lookup_int(file
, &y_top_left
,
1319 "%s.y_top_left", sec_name
)
1320 || !secfile_lookup_int(file
, &dx
, "%s.dx", sec_name
)
1321 || !secfile_lookup_int(file
, &dy
, "%s.dy", sec_name
)) {
1322 log_error("Grid \"%s\" invalid: %s", sec_name
, secfile_error());
1327 while (NULL
!= secfile_entry_lookup(file
, "%s.tiles%d.tag",
1329 struct small_sprite
*ss
;
1336 if (!secfile_lookup_int(file
, &row
, "%s.tiles%d.row", sec_name
, j
)
1337 || !secfile_lookup_int(file
, &column
, "%s.tiles%d.column",
1339 || !(tags
= secfile_lookup_str_vec(file
, &num_tags
,
1342 log_error("Small sprite \"%s.tiles%d\" invalid: %s",
1343 sec_name
, j
, secfile_error());
1346 hot_x
= secfile_lookup_int_default(file
, 0, "%s.tiles%d.hot_x",
1348 hot_y
= secfile_lookup_int_default(file
, 0, "%s.tiles%d.hot_y",
1351 /* there must be at least 1 because of the while(): */
1352 fc_assert_action(num_tags
> 0, continue);
1354 x1
= x_top_left
+ (dx
+ pixel_border
) * column
;
1355 y1
= y_top_left
+ (dy
+ pixel_border
) * row
;
1357 ss
= fc_malloc(sizeof(*ss
));
1369 small_sprite_list_prepend(t
->small_sprites
, ss
);
1371 if (!duplicates_ok
) {
1372 for (k
= 0; k
< num_tags
; k
++) {
1373 if (!sprite_hash_insert(t
->sprite_hash
, tags
[k
], ss
)) {
1374 log_error("warning: already have a sprite for \"%s\".",
1379 for (k
= 0; k
< num_tags
; k
++) {
1380 (void) sprite_hash_replace(t
->sprite_hash
, tags
[k
], ss
);
1387 } section_list_iterate_end
;
1388 section_list_destroy(sections
);
1391 /* Load "extra" sprites. Each sprite is one file. */
1393 while (NULL
!= secfile_entry_lookup(file
, "extra.sprites%d.tag", ++i
)) {
1394 struct small_sprite
*ss
;
1396 const char *filename
;
1400 if (!(tags
= secfile_lookup_str_vec(file
, &num_tags
,
1401 "extra.sprites%d.tag", i
))
1402 || !(filename
= secfile_lookup_str(file
,
1403 "extra.sprites%d.file", i
))) {
1404 log_error("Extra sprite \"extra.sprites%d\" invalid: %s",
1405 i
, secfile_error());
1408 hot_x
= secfile_lookup_int_default(file
, 0, "extra.sprites%d.hot_x", i
);
1409 hot_y
= secfile_lookup_int_default(file
, 0, "extra.sprites%d.hot_y", i
);
1411 ss
= fc_malloc(sizeof(*ss
));
1413 ss
->file
= fc_strdup(filename
);
1419 small_sprite_list_prepend(t
->small_sprites
, ss
);
1421 if (!duplicates_ok
) {
1422 for (k
= 0; k
< num_tags
; k
++) {
1423 if (!sprite_hash_insert(t
->sprite_hash
, tags
[k
], ss
)) {
1424 log_error("warning: already have a sprite for \"%s\".", tags
[k
]);
1428 for (k
= 0; k
< num_tags
; k
++) {
1429 (void) sprite_hash_replace(t
->sprite_hash
, tags
[k
], ss
);
1435 secfile_check_unused(file
);
1436 secfile_destroy(file
);
1439 /**********************************************************************
1440 Returns the correct name of the gfx file (with path and extension)
1441 Must be free'd when no longer used
1442 ***********************************************************************/
1443 static char *tilespec_gfx_filename(const char *gfx_filename
)
1445 const char *gfx_current_fileext
;
1446 const char **gfx_fileexts
= gfx_fileextensions();
1448 while((gfx_current_fileext
= *gfx_fileexts
++))
1451 fc_malloc(strlen(gfx_filename
) + strlen(gfx_current_fileext
) + 2);
1452 const char *real_full_name
;
1454 sprintf(full_name
,"%s.%s",gfx_filename
,gfx_current_fileext
);
1456 real_full_name
= fileinfoname(get_data_dirs(), full_name
);
1458 if (real_full_name
) {
1459 return fc_strdup(real_full_name
);
1463 tileset_error(LOG_FATAL
, _("Couldn't find a supported gfx file extension for \"%s\"."),
1469 /**********************************************************************
1470 Determine the sprite_type string.
1471 ***********************************************************************/
1472 static int check_sprite_type(const char *sprite_type
, const char *tile_section
)
1474 if (fc_strcasecmp(sprite_type
, "corner") == 0) {
1477 if (fc_strcasecmp(sprite_type
, "single") == 0) {
1480 if (fc_strcasecmp(sprite_type
, "whole") == 0) {
1483 log_error("[%s] unknown sprite_type \"%s\".", tile_section
, sprite_type
);
1487 /**********************************************************************
1488 Finds and reads the toplevel tilespec file based on given name.
1489 Sets global variables, including tile sizes and full names for
1491 ***********************************************************************/
1492 struct tileset
*tileset_read_toplevel(const char *tileset_name
, bool verbose
)
1494 struct section_file
*file
;
1498 size_t num_spec_files
;
1499 const char **spec_filenames
;
1500 size_t num_prefered_themes
;
1501 struct section_list
*sections
= NULL
;
1502 const char *file_capstr
;
1503 bool duplicates_ok
, is_hex
;
1504 enum direction8 dir
;
1505 const int spl
= strlen(TILE_SECTION_PREFIX
);
1506 struct tileset
*t
= NULL
;
1508 const char *roadname
;
1511 fname
= tilespec_fullname(tileset_name
);
1514 log_error("Can't find tileset \"%s\".", tileset_name
);
1518 log_verbose("tilespec file is \"%s\".", fname
);
1520 if (!(file
= secfile_load(fname
, TRUE
))) {
1521 log_error("Could not open '%s':\n%s", fname
, secfile_error());
1526 if (!check_tilespec_capabilities(file
, "tilespec",
1527 TILESPEC_CAPSTR
, fname
, verbose
)) {
1528 secfile_destroy(file
);
1534 file_capstr
= secfile_lookup_str(file
, "%s.options", "tilespec");
1535 duplicates_ok
= (NULL
!= file_capstr
1536 && has_capabilities("+duplicates_ok", file_capstr
));
1538 (void) secfile_entry_lookup(file
, "tilespec.name"); /* currently unused */
1540 sz_strlcpy(t
->name
, tileset_name
);
1541 if (!secfile_lookup_int(file
, &t
->priority
, "tilespec.priority")
1542 || !secfile_lookup_bool(file
, &is_hex
, "tilespec.is_hex")) {
1543 log_error("Tileset \"%s\" invalid: %s", t
->name
, secfile_error());
1547 tstr
= secfile_lookup_str(file
, "tilespec.type");
1549 log_error("Tileset \"%s\": no tileset type", t
->name
);
1553 if (!fc_strcasecmp(tstr
, "overview")) {
1554 t
->type
= TS_OVERVIEW
;
1555 } else if (!fc_strcasecmp(tstr
, "isometric")) {
1556 t
->type
= TS_ISOMETRIC
;
1558 log_error("Tileset \"%s\": unknown tileset type \"%s\"", t
->name
, tstr
);
1562 /* Read hex-tileset information. */
1563 t
->hex_width
= t
->hex_height
= 0;
1567 if (!secfile_lookup_int(file
, &hex_side
, "tilespec.hex_side")) {
1568 log_error("Tileset \"%s\" invalid: %s", t
->name
, secfile_error());
1572 if (t
->type
== TS_ISOMETRIC
) {
1573 t
->hex_width
= hex_side
;
1575 t
->hex_height
= hex_side
;
1577 /* Hex tilesets are drawn the same as isometric. */
1578 /* FIXME: There will be other legal values to be used with hex
1579 * tileset in the future, and this would just overwrite it. */
1580 t
->type
= TS_ISOMETRIC
;
1583 if (t
->type
== TS_ISOMETRIC
&& !isometric_view_supported()) {
1584 log_normal(_("Client does not support isometric tilesets."));
1585 log_normal(_("Using default tileset instead."));
1586 fc_assert(tileset_name
!= NULL
);
1589 if (t
->type
== TS_OVERVIEW
&& !overhead_view_supported()) {
1590 log_normal(_("Client does not support overhead view tilesets."));
1591 log_normal(_("Using default tileset instead."));
1592 fc_assert(tileset_name
!= NULL
);
1596 /* Create arrays of valid and cardinal tileset dirs. These depend
1597 * entirely on the tileset, not the topology. They are also in clockwise
1598 * rotational ordering. */
1599 t
->num_valid_tileset_dirs
= t
->num_cardinal_tileset_dirs
= 0;
1602 if (is_valid_tileset_dir(t
, dir
)) {
1603 t
->valid_tileset_dirs
[t
->num_valid_tileset_dirs
] = dir
;
1604 t
->num_valid_tileset_dirs
++;
1606 if (is_cardinal_tileset_dir(t
, dir
)) {
1607 t
->cardinal_tileset_dirs
[t
->num_cardinal_tileset_dirs
] = dir
;
1608 t
->num_cardinal_tileset_dirs
++;
1612 } while (dir
!= DIR8_NORTH
);
1613 fc_assert(t
->num_valid_tileset_dirs
% 2 == 0); /* Assumed elsewhere. */
1614 t
->num_index_valid
= 1 << t
->num_valid_tileset_dirs
;
1615 t
->num_index_cardinal
= 1 << t
->num_cardinal_tileset_dirs
;
1617 if (!secfile_lookup_int(file
, &t
->normal_tile_width
,
1618 "tilespec.normal_tile_width")
1619 || !secfile_lookup_int(file
, &t
->normal_tile_height
,
1620 "tilespec.normal_tile_height")) {
1621 log_error("Tileset \"%s\" invalid: %s", t
->name
, secfile_error());
1624 if (t
->type
== TS_ISOMETRIC
) {
1625 t
->full_tile_width
= t
->normal_tile_width
;
1626 if (tileset_hex_height(t
) > 0) {
1627 t
->full_tile_height
= t
->normal_tile_height
;
1629 t
->full_tile_height
= 3 * t
->normal_tile_height
/ 2;
1632 t
->full_tile_width
= t
->normal_tile_width
;
1633 t
->full_tile_height
= t
->normal_tile_height
;
1636 = secfile_lookup_int_default(file
, t
->full_tile_width
, "tilespec.unit_width");
1638 = secfile_lookup_int_default(file
, t
->full_tile_height
, "tilespec.unit_height");
1639 if (!secfile_lookup_int(file
, &t
->small_sprite_width
,
1640 "tilespec.small_tile_width")
1641 || !secfile_lookup_int(file
, &t
->small_sprite_height
,
1642 "tilespec.small_tile_height")) {
1643 log_error("Tileset \"%s\" invalid: %s", t
->name
, secfile_error());
1646 log_verbose("tile sizes %dx%d, %d%d unit, %d%d small",
1647 t
->normal_tile_width
, t
->normal_tile_height
,
1648 t
->full_tile_width
, t
->full_tile_height
,
1649 t
->small_sprite_width
, t
->small_sprite_height
);
1651 /* FIXME: use specenum to load these. */
1652 if (!secfile_lookup_int(file
, &ei1
,
1653 "tilespec.fogstyle")
1654 || !secfile_lookup_int(file
, &ei2
,
1655 "tilespec.darkness_style")) {
1656 log_error("Tileset \"%s\" invalid: %s", t
->name
, secfile_error());
1660 t
->darkness_style
= ei2
;
1662 if (t
->darkness_style
< DARKNESS_NONE
1663 || t
->darkness_style
> DARKNESS_CORNER
1664 || (t
->darkness_style
== DARKNESS_ISORECT
1665 && (t
->type
== TS_OVERVIEW
|| t
->hex_width
> 0 || t
->hex_height
> 0))) {
1666 log_error("Invalid darkness style set in tileset \"%s\".", t
->name
);
1669 t
->darkness_layer
= secfile_lookup_int_default(file
, 0, "tilespec.darkness_layer");
1670 if (t
->darkness_layer
< 0 || t
->darkness_layer
>= TERRAIN_LAYER_COUNT
) {
1671 tileset_error(LOG_ERROR
, "Invalid darkness layer %d in tileset \"%s\"",
1672 t
->darkness_layer
, t
->name
);
1676 if (!secfile_lookup_int(file
, &t
->unit_flag_offset_x
,
1677 "tilespec.unit_flag_offset_x")
1678 || !secfile_lookup_int(file
, &t
->unit_flag_offset_y
,
1679 "tilespec.unit_flag_offset_y")
1680 || !secfile_lookup_int(file
, &t
->city_flag_offset_x
,
1681 "tilespec.city_flag_offset_x")
1682 || !secfile_lookup_int(file
, &t
->city_flag_offset_y
,
1683 "tilespec.city_flag_offset_y")
1684 || !secfile_lookup_int(file
, &t
->unit_offset_x
,
1685 "tilespec.unit_offset_x")
1686 || !secfile_lookup_int(file
, &t
->unit_offset_y
,
1687 "tilespec.unit_offset_y")
1688 || !secfile_lookup_int(file
, &t
->citybar_offset_y
,
1689 "tilespec.citybar_offset_y")
1690 || !secfile_lookup_int(file
, &t
->tilelabel_offset_y
,
1691 "tilespec.tilelabel_offset_y")
1692 || !secfile_lookup_int(file
, &t
->city_names_font_size
,
1693 "tilespec.city_names_font_size")
1694 || !secfile_lookup_int(file
, &t
->city_productions_font_size
,
1695 "tilespec.city_productions_font_size")) {
1696 log_error("Tileset \"%s\" invalid: %s", t
->name
, secfile_error());
1700 set_city_names_font_sizes(t
->city_names_font_size
,
1701 t
->city_productions_font_size
);
1703 c
= secfile_lookup_str(file
, "tilespec.main_intro_file");
1704 t
->main_intro_filename
= tilespec_gfx_filename(c
);
1705 log_debug("intro file %s", t
->main_intro_filename
);
1707 c
= secfile_lookup_str(file
, "tilespec.minimap_intro_file");
1708 t
->minimap_intro_filename
= tilespec_gfx_filename(c
);
1709 log_debug("radar file %s", t
->minimap_intro_filename
);
1711 /* Terrain layer info. */
1712 for (i
= 0; i
< MAX_NUM_LAYERS
; i
++) {
1713 struct tileset_layer
*tslp
= &t
->layers
[i
];
1717 (char **) secfile_lookup_str_vec(file
, &tslp
->match_count
,
1718 "layer%d.match_types", i
);
1719 for (j
= 0; j
< tslp
->match_count
; j
++) {
1720 tslp
->match_types
[j
] = fc_strdup(tslp
->match_types
[j
]);
1722 for (k
= 0; k
< j
; k
++) {
1723 if (tslp
->match_types
[k
][0] == tslp
->match_types
[j
][0]) {
1724 tileset_error(LOG_FATAL
, _("[layer%d] match_types: \"%s\" initial "
1725 "('%c') is not unique."),
1726 i
, tslp
->match_types
[j
], tslp
->match_types
[j
][0]);
1727 /* FIXME: Returns NULL. */
1733 /* Tile drawing info. */
1734 sections
= secfile_sections_by_name_prefix(file
, TILE_SECTION_PREFIX
);
1735 if (NULL
== sections
|| 0 == section_list_size(sections
)) {
1736 tileset_error(LOG_ERROR
, _("No [%s] sections supported by tileset \"%s\"."),
1737 TILE_SECTION_PREFIX
, fname
);
1741 fc_assert(t
->tile_hash
== NULL
);
1742 t
->tile_hash
= drawing_hash_new();
1744 section_list_iterate(sections
, psection
) {
1745 const char *sec_name
= section_name(psection
);
1746 struct drawing_data
*draw
= drawing_data_new(sec_name
+ spl
);
1747 const char *sprite_type
, *str
;
1750 draw
->blending
= secfile_lookup_int_default(file
, 0, "%s.blend_layer",
1752 draw
->blending
= CLIP(0, draw
->blending
, MAX_NUM_LAYERS
);
1754 draw
->is_reversed
= secfile_lookup_bool_default(file
, FALSE
,
1757 draw
->num_layers
= secfile_lookup_int_default(file
, 0, "%s.num_layers",
1759 draw
->num_layers
= CLIP(1, draw
->num_layers
, MAX_NUM_LAYERS
);
1761 for (l
= 0; l
< draw
->num_layers
; l
++) {
1762 struct drawing_layer
*dlp
= &draw
->layer
[l
];
1763 struct tileset_layer
*tslp
= &t
->layers
[l
];
1764 const char *match_type
;
1765 const char **match_with
;
1769 = secfile_lookup_bool_default(file
, FALSE
, "%s.layer%d_is_tall",
1772 = secfile_lookup_int_default(file
, 0, "%s.layer%d_offset_x",
1775 = secfile_lookup_int_default(file
, 0, "%s.layer%d_offset_y",
1778 match_type
= secfile_lookup_str_default(file
, NULL
,
1779 "%s.layer%d_match_type",
1784 /* Determine our match_type. */
1785 for (j
= 0; j
< tslp
->match_count
; j
++) {
1786 if (fc_strcasecmp(tslp
->match_types
[j
], match_type
) == 0) {
1790 if (j
>= tslp
->match_count
) {
1791 log_error("[%s] invalid match_type \"%s\".", sec_name
, match_type
);
1793 dlp
->match_index
[dlp
->match_indices
++] = j
;
1797 match_with
= secfile_lookup_str_vec(file
, &count
,
1798 "%s.layer%d_match_with",
1803 if (count
> MAX_NUM_MATCH_WITH
) {
1804 log_error("[%s] match_with has too many types (%d, max %d)",
1805 sec_name
, (int) count
, MAX_NUM_MATCH_WITH
);
1806 count
= MAX_NUM_MATCH_WITH
;
1809 if (1 < dlp
->match_indices
) {
1810 log_error("[%s] previous match_with ignored.", sec_name
);
1811 dlp
->match_indices
= 1;
1812 } else if (1 > dlp
->match_indices
) {
1813 log_error("[%s] missing match_type, using \"%s\".",
1814 sec_name
, tslp
->match_types
[0]);
1815 dlp
->match_index
[0] = 0;
1816 dlp
->match_indices
= 1;
1819 for (k
= 0; k
< count
; k
++) {
1820 for (j
= 0; j
< tslp
->match_count
; j
++) {
1821 if (fc_strcasecmp(tslp
->match_types
[j
], match_with
[k
]) == 0) {
1825 if (j
>= tslp
->match_count
) {
1826 log_error("[%s] layer%d_match_with: invalid \"%s\".",
1827 sec_name
, l
, match_with
[k
]);
1828 } else if (1 < count
) {
1831 for (m
= 0; m
< dlp
->match_indices
; m
++) {
1832 if (dlp
->match_index
[m
] == j
) {
1833 log_error("[%s] layer%d_match_with: duplicate \"%s\".",
1834 sec_name
, l
, match_with
[k
]);
1838 if (m
>= dlp
->match_indices
) {
1839 dlp
->match_index
[dlp
->match_indices
++] = j
;
1842 dlp
->match_index
[dlp
->match_indices
++] = j
;
1849 /* Check match_indices */
1850 switch (dlp
->match_indices
) {
1853 dlp
->match_style
= MATCH_NONE
;
1856 if (dlp
->match_index
[0] == dlp
->match_index
[1] ) {
1857 dlp
->match_style
= MATCH_SAME
;
1859 dlp
->match_style
= MATCH_PAIR
;
1863 dlp
->match_style
= MATCH_FULL
;
1868 = secfile_lookup_str_default(file
, "whole", "%s.layer%d_sprite_type",
1870 dlp
->sprite_type
= check_sprite_type(sprite_type
, sec_name
);
1872 switch (dlp
->sprite_type
) {
1874 /* OK, no problem */
1878 || dlp
->offset_x
> 0
1879 || dlp
->offset_y
> 0) {
1880 log_error("[%s] layer %d: you cannot have tall terrain or\n"
1881 "a sprite offset with a cell-based drawing method.",
1883 dlp
->is_tall
= FALSE
;
1884 dlp
->offset_x
= dlp
->offset_y
= 0;
1890 str
= secfile_lookup_str(file
, "%s.mine_sprite", sec_name
);
1892 draw
->mine_tag
= fc_strdup(str
);
1895 if (!drawing_hash_insert(t
->tile_hash
, draw
->name
, draw
)) {
1896 log_error("warning: duplicate tilespec entry [%s].", sec_name
);
1899 } section_list_iterate_end
;
1900 section_list_destroy(sections
);
1903 t
->rstyle_hash
= rstyle_hash_new();
1904 t
->rivers
= road_type_list_new();
1906 for (i
= 0; (roadname
= secfile_lookup_str_default(file
, NULL
,
1907 "roads.styles%d.name",
1909 const char *style_name
;
1910 enum roadstyle_id
*style
= fc_malloc(sizeof(enum roadstyle_id
));
1913 style_name
= secfile_lookup_str_default(file
, "AllSeparate",
1914 "roads.styles%d.style", i
);
1915 *style
= roadstyle_id_by_name(style_name
, fc_strcasecmp
);
1916 if (!roadstyle_id_is_valid(*style
)) {
1917 log_error("Unknown road style \"%s\" for road \"%s\"",
1918 style_name
, roadname
);
1923 name
= fc_malloc(strlen(roadname
) + 1);
1924 strcpy(name
, roadname
);
1926 if (!rstyle_hash_insert(t
->rstyle_hash
, name
, style
)) {
1927 log_error("warning: duplicate roadstyle entry [%s].", roadname
);
1934 spec_filenames
= secfile_lookup_str_vec(file
, &num_spec_files
,
1936 if (NULL
== spec_filenames
|| 0 == num_spec_files
) {
1937 log_error("No tile graphics files specified in \"%s\"", fname
);
1941 fc_assert(t
->sprite_hash
== NULL
);
1942 t
->sprite_hash
= sprite_hash_new();
1943 for (i
= 0; i
< num_spec_files
; i
++) {
1944 struct specfile
*sf
= fc_malloc(sizeof(*sf
));
1947 log_debug("spec file %s", spec_filenames
[i
]);
1949 sf
->big_sprite
= NULL
;
1950 dname
= fileinfoname(get_data_dirs(), spec_filenames
[i
]);
1953 log_error("Can't find spec file \"%s\".", spec_filenames
[i
]);
1957 sf
->file_name
= fc_strdup(dname
);
1958 scan_specfile(t
, sf
, duplicates_ok
);
1960 specfile_list_prepend(t
->specfiles
, sf
);
1962 free(spec_filenames
);
1964 t
->color_system
= color_system_read(file
);
1966 /* FIXME: remove this hack. */
1967 t
->prefered_themes
=
1968 (char **) secfile_lookup_str_vec(file
, &num_prefered_themes
,
1969 "tilespec.preferred_themes");
1970 if (num_prefered_themes
<= 0) {
1971 t
->prefered_themes
=
1972 (char **) secfile_lookup_str_vec(file
, &num_prefered_themes
,
1973 "tilespec.prefered_themes");
1975 t
->num_prefered_themes
= num_prefered_themes
;
1976 for (i
= 0; i
< t
->num_prefered_themes
; i
++) {
1977 t
->prefered_themes
[i
] = fc_strdup(t
->prefered_themes
[i
]);
1980 secfile_check_unused(file
);
1981 secfile_destroy(file
);
1982 log_verbose("finished reading \"%s\".", fname
);
1988 secfile_destroy(file
);
1991 if (NULL
!= sections
) {
1992 section_list_destroy(sections
);
1997 /**********************************************************************
1998 Returns a text name for the citizen, as used in the tileset.
1999 ***********************************************************************/
2000 static const char *citizen_rule_name(enum citizen_category citizen
)
2002 /* These strings are used in reading the tileset. Do not
2007 case CITIZEN_CONTENT
:
2009 case CITIZEN_UNHAPPY
:
2016 log_error("Unknown citizen type: %d.", (int) citizen
);
2020 /****************************************************************************
2021 Return a directional string for the cardinal directions. Normally the
2022 binary value 1000 will be converted into "n1e0s0w0". This is in a
2024 ****************************************************************************/
2025 static const char *cardinal_index_str(const struct tileset
*t
, int idx
)
2031 for (i
= 0; i
< t
->num_cardinal_tileset_dirs
; i
++) {
2032 int value
= (idx
>> i
) & 1;
2034 cat_snprintf(c
, sizeof(c
), "%s%d",
2035 dir_get_tileset_name(t
->cardinal_tileset_dirs
[i
]), value
);
2041 /****************************************************************************
2042 Do the same thing as cardinal_str, except including all valid directions.
2043 The returned string is a pointer to static memory.
2044 ****************************************************************************/
2045 static char *valid_index_str(const struct tileset
*t
, int index
)
2051 for (i
= 0; i
< t
->num_valid_tileset_dirs
; i
++) {
2052 int value
= (index
>> i
) & 1;
2054 cat_snprintf(c
, sizeof(c
), "%s%d",
2055 dir_get_tileset_name(t
->valid_tileset_dirs
[i
]), value
);
2061 /**************************************************************************
2062 Loads the sprite. If the sprite is already loaded a reference
2063 counter is increased. Can return NULL if the sprite couldn't be
2065 **************************************************************************/
2066 static struct sprite
*load_sprite(struct tileset
*t
, const char *tag_name
)
2068 struct small_sprite
*ss
;
2070 log_debug("load_sprite(tag='%s')", tag_name
);
2071 /* Lookup information about where the sprite is found. */
2072 if (!sprite_hash_lookup(t
->sprite_hash
, tag_name
, &ss
)) {
2076 fc_assert(ss
->ref_count
>= 0);
2079 /* If the sprite hasn't been loaded already, then load it. */
2080 fc_assert(ss
->ref_count
== 0);
2082 ss
->sprite
= load_gfx_file(ss
->file
);
2084 tileset_error(LOG_FATAL
, _("Couldn't load gfx file \"%s\" for sprite '%s'."),
2085 ss
->file
, tag_name
);
2090 ensure_big_sprite(ss
->sf
);
2091 get_sprite_dimensions(ss
->sf
->big_sprite
, &sf_w
, &sf_h
);
2092 if (ss
->x
< 0 || ss
->x
+ ss
->width
> sf_w
2093 || ss
->y
< 0 || ss
->y
+ ss
->height
> sf_h
) {
2094 tileset_error(LOG_ERROR
, _("Sprite '%s' in file \"%s\" isn't within the image!"),
2095 tag_name
, ss
->sf
->file_name
);
2099 crop_sprite(ss
->sf
->big_sprite
, ss
->x
, ss
->y
, ss
->width
, ss
->height
,
2104 /* Track the reference count so we know when to free the sprite. */
2110 /**************************************************************************
2111 Create a sprite with the given color and tag.
2112 **************************************************************************/
2113 static struct sprite
*create_plr_sprite(struct color
*pcolor
)
2115 struct sprite
*sprite
;
2117 fc_assert_ret_val(pcolor
!= NULL
, NULL
);
2119 sprite
= create_sprite(128, 64, pcolor
);
2124 /**************************************************************************
2125 Unloads the sprite. Decrease the reference counter. If the last
2126 reference is removed the sprite is freed.
2127 **************************************************************************/
2128 static void unload_sprite(struct tileset
*t
, const char *tag_name
)
2130 struct small_sprite
*ss
;
2132 sprite_hash_lookup(t
->sprite_hash
, tag_name
, &ss
);
2134 fc_assert_ret(ss
->ref_count
>= 1);
2135 fc_assert_ret(ss
->sprite
);
2139 if (ss
->ref_count
== 0) {
2140 /* Nobody's using the sprite anymore, so we should free it. We know
2141 * where to find it if we need it again. */
2142 log_debug("freeing sprite '%s'.", tag_name
);
2143 free_sprite(ss
->sprite
);
2148 /**************************************************************************
2149 Return TRUE iff the specified sprite exists in the tileset (whether
2150 or not it is currently loaded).
2151 **************************************************************************/
2152 static bool sprite_exists(const struct tileset
*t
, const char *tag_name
)
2154 /* Lookup information about where the sprite is found. */
2155 return sprite_hash_lookup(t
->sprite_hash
, tag_name
, NULL
);
2158 /* Not very safe, but convenient: */
2159 #define SET_SPRITE(field, tag) \
2161 t->sprites.field = load_sprite(t, tag); \
2162 if (t->sprites.field == NULL) { \
2163 tileset_error(LOG_FATAL, _("Sprite tag '%s' missing."), tag); \
2167 /* Sets sprites.field to tag or (if tag isn't available) to alt */
2168 #define SET_SPRITE_ALT(field, tag, alt) \
2170 t->sprites.field = load_sprite(t, tag); \
2171 if (!t->sprites.field) { \
2172 t->sprites.field = load_sprite(t, alt); \
2174 if (t->sprites.field == NULL) { \
2175 tileset_error(LOG_FATAL, _("Sprite tag '%s' and alternate '%s' are " \
2176 "both missing."), tag, alt); \
2180 /* Sets sprites.field to tag, or NULL if not available */
2181 #define SET_SPRITE_OPT(field, tag) \
2182 t->sprites.field = load_sprite(t, tag)
2184 #define SET_SPRITE_ALT_OPT(field, tag, alt) \
2186 t->sprites.field = tiles_lookup_sprite_tag_alt(t, LOG_VERBOSE, tag, alt,\
2187 "sprite", #field); \
2190 /****************************************************************************
2191 Setup the graphics for specialist types.
2192 ****************************************************************************/
2193 void tileset_setup_specialist_type(struct tileset
*t
, Specialist_type_id id
)
2195 /* Load the specialist sprite graphics. */
2198 const char *name
= specialist_rule_name(specialist_by_number(id
));
2199 const char *graphic_alt
= specialist_by_number(id
)->graphic_alt
;
2201 for (j
= 0; j
< MAX_NUM_CITIZEN_SPRITES
; j
++) {
2202 /* Try rule name + index number */
2203 fc_snprintf(buffer
, sizeof(buffer
), "specialist.%s_%d", name
, j
);
2204 t
->sprites
.specialist
[id
].sprite
[j
] = load_sprite(t
, buffer
);
2206 /* Break if no more index specific sprites are defined */
2207 if (!t
->sprites
.specialist
[id
].sprite
[j
]) {
2212 /* Nothing? Try the alt tag */
2214 t
->sprites
.specialist
[id
].sprite
[j
] = load_sprite(t
, graphic_alt
);
2216 if (t
->sprites
.specialist
[id
].sprite
[j
]) {
2221 t
->sprites
.specialist
[id
].count
= j
;
2223 /* Still nothing? Give up. */
2225 tileset_error(LOG_FATAL
, _("No graphics for specialist \"%s\"."), name
);
2229 /****************************************************************************
2230 Setup the graphics for (non-specialist) citizen types.
2231 ****************************************************************************/
2232 static void tileset_setup_citizen_types(struct tileset
*t
)
2237 /* Load the citizen sprite graphics, no specialist. */
2238 for (i
= 0; i
< CITIZEN_LAST
; i
++) {
2239 const char *name
= citizen_rule_name(i
);
2241 for (j
= 0; j
< MAX_NUM_CITIZEN_SPRITES
; j
++) {
2242 fc_snprintf(buffer
, sizeof(buffer
), "citizen.%s_%d", name
, j
);
2243 t
->sprites
.citizen
[i
].sprite
[j
] = load_sprite(t
, buffer
);
2244 if (!t
->sprites
.citizen
[i
].sprite
[j
]) {
2248 t
->sprites
.citizen
[i
].count
= j
;
2250 tileset_error(LOG_FATAL
, _("No graphics for citizen \"%s\"."), name
);
2255 /****************************************************************************
2256 Return the sprite in the city_sprite listing that corresponds to this
2257 city - based on city style and size.
2259 See also load_city_sprite, free_city_sprite.
2260 ****************************************************************************/
2261 static struct sprite
*get_city_sprite(const struct city_sprite
*city_sprite
,
2262 const struct city
*pcity
)
2264 /* get style and match the best tile based on city size */
2265 int style
= style_of_city(pcity
);
2267 struct city_style_threshold
*thresholds
;
2270 fc_assert_ret_val(style
< city_sprite
->num_styles
, NULL
);
2272 if (is_ocean_tile(pcity
->tile
)
2273 && city_sprite
->styles
[style
].oceanic_num_thresholds
!= 0) {
2274 num_thresholds
= city_sprite
->styles
[style
].oceanic_num_thresholds
;
2275 thresholds
= city_sprite
->styles
[style
].oceanic_thresholds
;
2277 num_thresholds
= city_sprite
->styles
[style
].land_num_thresholds
;
2278 thresholds
= city_sprite
->styles
[style
].land_thresholds
;
2281 if (num_thresholds
== 0) {
2285 /* Get the sprite with the index defined by the effects. */
2286 img_index
= pcity
->client
.city_image
;
2287 if (img_index
== -100) {
2288 /* Server doesn't know right value as this is from old savegame.
2289 * Guess here based on *client* side information as was done in
2290 * versions where information was not saved to savegame - this should
2291 * give us right answer of what city looked like by the time it was
2293 img_index
= get_city_bonus(pcity
, EFT_CITY_IMAGE
);
2295 img_index
= CLIP(0, img_index
, num_thresholds
- 1);
2297 return thresholds
[img_index
].sprite
;
2300 /****************************************************************************
2301 Allocates one threshold set for city sprite
2302 ****************************************************************************/
2303 static int load_city_thresholds_sprites(struct tileset
*t
, const char *tag
,
2304 char *graphic
, char *graphic_alt
,
2305 struct city_style_threshold
**thresholds
)
2308 char *gfx_in_use
= graphic
;
2309 int num_thresholds
= 0;
2310 struct sprite
*sprite
;
2315 for (size
= 0; size
< MAX_CITY_SIZE
; size
++) {
2316 fc_snprintf(buffer
, sizeof(buffer
), "%s_%s_%d",
2317 gfx_in_use
, tag
, size
);
2318 if ((sprite
= load_sprite(t
, buffer
))) {
2320 *thresholds
= fc_realloc(*thresholds
, num_thresholds
* sizeof(**thresholds
));
2321 (*thresholds
)[num_thresholds
- 1].sprite
= sprite
;
2322 } else if (size
== 0) {
2323 if (gfx_in_use
== graphic
) {
2324 /* Try again with graphic_alt. */
2326 gfx_in_use
= graphic_alt
;
2328 /* Don't load any others if the 0 element isn't there. */
2334 return num_thresholds
;
2337 /****************************************************************************
2338 Allocates and loads a new city sprite from the given sprite tags.
2342 See also get_city_sprite, free_city_sprite.
2343 ****************************************************************************/
2344 static struct city_sprite
*load_city_sprite(struct tileset
*t
,
2347 struct city_sprite
*city_sprite
= fc_malloc(sizeof(*city_sprite
));
2350 /* Store number of styles we have allocated memory for.
2351 * game.control.styles_count might change if client disconnects from
2352 * server and connects new one. */
2353 city_sprite
->num_styles
= game
.control
.styles_count
;
2354 city_sprite
->styles
= fc_malloc(city_sprite
->num_styles
2355 * sizeof(*city_sprite
->styles
));
2357 for (style
= 0; style
< city_sprite
->num_styles
; style
++) {
2358 city_sprite
->styles
[style
].land_num_thresholds
=
2359 load_city_thresholds_sprites(t
, tag
, city_styles
[style
].graphic
,
2360 city_styles
[style
].graphic_alt
,
2361 &city_sprite
->styles
[style
].land_thresholds
);
2362 city_sprite
->styles
[style
].oceanic_num_thresholds
=
2363 load_city_thresholds_sprites(t
, tag
, city_styles
[style
].oceanic_graphic
,
2364 city_styles
[style
].oceanic_graphic_alt
,
2365 &city_sprite
->styles
[style
].oceanic_thresholds
);
2371 /****************************************************************************
2372 Frees a city sprite.
2374 See also get_city_sprite, load_city_sprite.
2375 ****************************************************************************/
2376 static void free_city_sprite(struct city_sprite
*city_sprite
)
2383 for (style
= 0; style
< city_sprite
->num_styles
; style
++) {
2384 if (city_sprite
->styles
[style
].land_thresholds
) {
2385 free(city_sprite
->styles
[style
].land_thresholds
);
2387 if (city_sprite
->styles
[style
].oceanic_thresholds
) {
2388 free(city_sprite
->styles
[style
].oceanic_thresholds
);
2391 free(city_sprite
->styles
);
2395 /**********************************************************************
2396 Initialize 'sprites' structure based on hardwired tags which
2397 freeciv always requires.
2398 ***********************************************************************/
2399 static void tileset_lookup_sprite_tags(struct tileset
*t
)
2401 char buffer
[512], buffer2
[512];
2402 const int W
= t
->normal_tile_width
, H
= t
->normal_tile_height
;
2405 fc_assert_ret(t
->sprite_hash
!= NULL
);
2407 SET_SPRITE(treaty_thumb
[0], "treaty.disagree_thumb_down");
2408 SET_SPRITE(treaty_thumb
[1], "treaty.agree_thumb_up");
2410 for (j
= 0; j
< INDICATOR_COUNT
; j
++) {
2411 const char *names
[] = {"science_bulb", "warming_sun", "cooling_flake"};
2413 for (i
= 0; i
< NUM_TILES_PROGRESS
; i
++) {
2414 fc_snprintf(buffer
, sizeof(buffer
), "s.%s_%d", names
[j
], i
);
2415 SET_SPRITE(indicator
[j
][i
], buffer
);
2419 SET_SPRITE(arrow
[ARROW_RIGHT
], "s.right_arrow");
2420 SET_SPRITE(arrow
[ARROW_PLUS
], "s.plus");
2421 SET_SPRITE(arrow
[ARROW_MINUS
], "s.minus");
2422 if (t
->type
== TS_ISOMETRIC
) {
2423 SET_SPRITE(dither_tile
, "t.dither_tile");
2426 SET_SPRITE(mask
.tile
, "mask.tile");
2427 SET_SPRITE(mask
.worked_tile
, "mask.worked_tile");
2428 SET_SPRITE(mask
.unworked_tile
, "mask.unworked_tile");
2430 SET_SPRITE(tax_luxury
, "s.tax_luxury");
2431 SET_SPRITE(tax_science
, "s.tax_science");
2432 SET_SPRITE(tax_gold
, "s.tax_gold");
2434 tileset_setup_citizen_types(t
);
2436 for (i
= 0; i
< SPACESHIP_COUNT
; i
++) {
2437 const char *names
[SPACESHIP_COUNT
]
2438 = {"solar_panels", "life_support", "habitation",
2439 "structural", "fuel", "propulsion", "exhaust"};
2441 fc_snprintf(buffer
, sizeof(buffer
), "spaceship.%s", names
[i
]);
2442 SET_SPRITE(spaceship
[i
], buffer
);
2445 for (i
= 0; i
< CURSOR_LAST
; i
++) {
2446 for (f
= 0; f
< NUM_CURSOR_FRAMES
; f
++) {
2447 const char *names
[CURSOR_LAST
] =
2448 {"goto", "patrol", "paradrop", "nuke", "select",
2449 "invalid", "attack", "edit_paint", "edit_add", "wait"};
2450 struct small_sprite
*ss
;
2452 fc_assert(ARRAY_SIZE(names
) == CURSOR_LAST
);
2453 fc_snprintf(buffer
, sizeof(buffer
), "cursor.%s%d", names
[i
], f
);
2454 SET_SPRITE(cursor
[i
].frame
[f
], buffer
);
2455 if (sprite_hash_lookup(t
->sprite_hash
, buffer
, &ss
)) {
2456 t
->sprites
.cursor
[i
].hot_x
= ss
->hot_x
;
2457 t
->sprites
.cursor
[i
].hot_y
= ss
->hot_y
;
2462 for (i
= 0; i
< ICON_COUNT
; i
++) {
2463 const char *names
[ICON_COUNT
] = {"freeciv", "citydlg"};
2465 fc_snprintf(buffer
, sizeof(buffer
), "icon.%s", names
[i
]);
2466 SET_SPRITE(icon
[i
], buffer
);
2469 SET_SPRITE(explode
.nuke
, "explode.nuke");
2471 sprite_vector_init(&t
->sprites
.explode
.unit
);
2472 for (i
= 0; ; i
++) {
2473 struct sprite
*sprite
;
2475 fc_snprintf(buffer
, sizeof(buffer
), "explode.unit_%d", i
);
2476 sprite
= load_sprite(t
, buffer
);
2480 sprite_vector_append(&t
->sprites
.explode
.unit
, sprite
);
2483 SET_SPRITE(unit
.auto_attack
, "unit.auto_attack");
2484 SET_SPRITE(unit
.auto_settler
, "unit.auto_settler");
2485 SET_SPRITE(unit
.auto_explore
, "unit.auto_explore");
2486 SET_SPRITE(unit
.fallout
, "unit.fallout");
2487 SET_SPRITE(unit
.fortified
, "unit.fortified");
2488 SET_SPRITE(unit
.fortifying
, "unit.fortifying");
2489 SET_SPRITE(unit
.go_to
, "unit.goto");
2490 SET_SPRITE(unit
.irrigate
, "unit.irrigate");
2491 SET_SPRITE(unit
.mine
, "unit.mine");
2492 SET_SPRITE(unit
.pillage
, "unit.pillage");
2493 SET_SPRITE(unit
.pollution
, "unit.pollution");
2494 SET_SPRITE(unit
.sentry
, "unit.sentry");
2495 SET_SPRITE(unit
.convert
, "unit.convert");
2496 SET_SPRITE(unit
.stack
, "unit.stack");
2497 SET_SPRITE(unit
.loaded
, "unit.loaded");
2498 SET_SPRITE(unit
.transform
, "unit.transform");
2499 SET_SPRITE(unit
.connect
, "unit.connect");
2500 SET_SPRITE(unit
.patrol
, "unit.patrol");
2501 for (i
= 0; i
< MAX_NUM_BATTLEGROUPS
; i
++) {
2502 fc_snprintf(buffer
, sizeof(buffer
), "unit.battlegroup_%d", i
);
2503 fc_snprintf(buffer2
, sizeof(buffer2
), "city.size_%d", i
+ 1);
2504 fc_assert(MAX_NUM_BATTLEGROUPS
< NUM_TILES_DIGITS
);
2505 SET_SPRITE_ALT(unit
.battlegroup
[i
], buffer
, buffer2
);
2507 SET_SPRITE(unit
.lowfuel
, "unit.lowfuel");
2508 SET_SPRITE(unit
.tired
, "unit.tired");
2510 for(i
=0; i
<NUM_TILES_HP_BAR
; i
++) {
2511 fc_snprintf(buffer
, sizeof(buffer
), "unit.hp_%d", i
*10);
2512 SET_SPRITE(unit
.hp_bar
[i
], buffer
);
2515 for (i
= 0; i
< MAX_VET_LEVELS
; i
++) {
2516 /* Veteran level sprites are optional. For instance "green" units
2517 * usually have no special graphic. */
2518 fc_snprintf(buffer
, sizeof(buffer
), "unit.vet_%d", i
);
2519 t
->sprites
.unit
.vet_lev
[i
] = load_sprite(t
, buffer
);
2522 t
->sprites
.unit
.select
[0] = NULL
;
2523 if (sprite_exists(t
, "unit.select0")) {
2524 for (i
= 0; i
< NUM_TILES_SELECT
; i
++) {
2525 fc_snprintf(buffer
, sizeof(buffer
), "unit.select%d", i
);
2526 SET_SPRITE(unit
.select
[i
], buffer
);
2530 SET_SPRITE(citybar
.shields
, "citybar.shields");
2531 SET_SPRITE(citybar
.food
, "citybar.food");
2532 SET_SPRITE(citybar
.trade
, "citybar.trade");
2533 SET_SPRITE(citybar
.occupied
, "citybar.occupied");
2534 SET_SPRITE(citybar
.background
, "citybar.background");
2535 sprite_vector_init(&t
->sprites
.citybar
.occupancy
);
2536 for (i
= 0; ; i
++) {
2537 struct sprite
*sprite
;
2539 fc_snprintf(buffer
, sizeof(buffer
), "citybar.occupancy_%d", i
);
2540 sprite
= load_sprite(t
, buffer
);
2544 sprite_vector_append(&t
->sprites
.citybar
.occupancy
, sprite
);
2546 if (t
->sprites
.citybar
.occupancy
.size
< 2) {
2547 tileset_error(LOG_FATAL
, _("Missing necessary citybar.occupancy_N sprites."));
2550 #define SET_EDITOR_SPRITE(x) SET_SPRITE(editor.x, "editor." #x)
2551 SET_EDITOR_SPRITE(erase
);
2552 SET_EDITOR_SPRITE(brush
);
2553 SET_EDITOR_SPRITE(copy
);
2554 SET_EDITOR_SPRITE(paste
);
2555 SET_EDITOR_SPRITE(copypaste
);
2556 SET_EDITOR_SPRITE(startpos
);
2557 SET_EDITOR_SPRITE(terrain
);
2558 SET_EDITOR_SPRITE(terrain_resource
);
2559 SET_EDITOR_SPRITE(terrain_special
);
2560 SET_EDITOR_SPRITE(unit
);
2561 SET_EDITOR_SPRITE(city
);
2562 SET_EDITOR_SPRITE(vision
);
2563 SET_EDITOR_SPRITE(territory
);
2564 SET_EDITOR_SPRITE(properties
);
2565 SET_EDITOR_SPRITE(road
);
2566 SET_EDITOR_SPRITE(military_base
);
2567 #undef SET_EDITOR_SPRITE
2569 SET_SPRITE(city
.disorder
, "city.disorder");
2571 for(i
=0; i
<NUM_TILES_DIGITS
; i
++) {
2572 fc_snprintf(buffer
, sizeof(buffer
), "city.size_%d", i
);
2573 SET_SPRITE(city
.size
[i
], buffer
);
2574 fc_snprintf(buffer2
, sizeof(buffer2
), "path.turns_%d", i
);
2575 SET_SPRITE_ALT(path
.turns
[i
], buffer2
, buffer
);
2577 fc_snprintf(buffer
, sizeof(buffer
), "city.size_%d0", i
);
2578 SET_SPRITE(city
.size_tens
[i
], buffer
);
2579 fc_snprintf(buffer2
, sizeof(buffer2
), "path.turns_%d0", i
);
2580 SET_SPRITE_ALT(path
.turns_tens
[i
], buffer2
, buffer
);
2582 fc_snprintf(buffer
, sizeof(buffer
), "city.size_%d00", i
);
2583 SET_SPRITE_OPT(city
.size_hundreds
[i
], buffer
);
2584 fc_snprintf(buffer2
, sizeof(buffer2
), "path.turns_%d00", i
);
2585 SET_SPRITE_ALT_OPT(path
.turns_hundreds
[i
], buffer2
, buffer
);
2587 fc_snprintf(buffer
, sizeof(buffer
), "city.t_food_%d", i
);
2588 SET_SPRITE(city
.tile_foodnum
[i
], buffer
);
2589 fc_snprintf(buffer
, sizeof(buffer
), "city.t_shields_%d", i
);
2590 SET_SPRITE(city
.tile_shieldnum
[i
], buffer
);
2591 fc_snprintf(buffer
, sizeof(buffer
), "city.t_trade_%d", i
);
2592 SET_SPRITE(city
.tile_tradenum
[i
], buffer
);
2595 /* Must have at least one upkeep sprite per output type (and unhappy) */
2596 /* The rest are optional; we copy the previous sprite for unspecified ones */
2597 fc_strlcpy(buffer
, "upkeep.unhappy", sizeof(buffer
));
2598 SET_SPRITE(upkeep
.unhappy
[0], buffer
);
2599 for(i
=1; i
<MAX_NUM_UPKEEP_SPRITES
; i
++) {
2600 fc_snprintf(buffer2
, sizeof(buffer2
), "upkeep.unhappy%d", i
+1);
2601 if (sprite_exists(t
, buffer2
)) {
2602 SET_SPRITE(upkeep
.unhappy
[i
], buffer2
);
2603 fc_strlcpy(buffer
, buffer2
, sizeof(buffer
));
2605 SET_SPRITE(upkeep
.unhappy
[i
], buffer
);
2608 output_type_iterate(o
) {
2609 fc_snprintf(buffer
, sizeof(buffer
),
2610 "upkeep.%s", get_output_identifier(o
));
2611 SET_SPRITE_OPT(upkeep
.output
[o
][0], buffer
);
2612 for(i
=1; i
<MAX_NUM_UPKEEP_SPRITES
; i
++) {
2613 fc_snprintf(buffer2
, sizeof(buffer2
),
2614 "upkeep.%s%d", get_output_identifier(o
), i
+1);
2615 if (sprite_exists(t
, buffer2
)) {
2616 SET_SPRITE(upkeep
.output
[o
][i
], buffer2
);
2617 fc_strlcpy(buffer
, buffer2
, sizeof(buffer
));
2619 /* Optional, as maybe the upkeep 1 sprite didn't exist either */
2620 SET_SPRITE_OPT(upkeep
.output
[o
][i
], buffer
);
2623 } output_type_iterate_end
;
2625 SET_SPRITE(user
.attention
, "user.attention");
2627 SET_SPRITE(tx
.fallout
, "tx.fallout");
2628 SET_SPRITE(tx
.pollution
, "tx.pollution");
2629 SET_SPRITE(tx
.village
, "tx.village");
2630 SET_SPRITE(tx
.fog
, "tx.fog");
2632 sprite_vector_init(&t
->sprites
.colors
.overlays
);
2633 for (i
= 0; ; i
++) {
2634 struct sprite
*sprite
;
2636 fc_snprintf(buffer
, sizeof(buffer
), "colors.overlay_%d", i
);
2637 sprite
= load_sprite(t
, buffer
);
2641 sprite_vector_append(&t
->sprites
.colors
.overlays
, sprite
);
2644 tileset_error(LOG_FATAL
, _("Missing overlay-color sprite colors.overlay_0."));
2647 /* Chop up and build the overlay graphics. */
2648 sprite_vector_reserve(&t
->sprites
.city
.worked_tile_overlay
,
2649 sprite_vector_size(&t
->sprites
.colors
.overlays
));
2650 sprite_vector_reserve(&t
->sprites
.city
.unworked_tile_overlay
,
2651 sprite_vector_size(&t
->sprites
.colors
.overlays
));
2652 for (i
= 0; i
< sprite_vector_size(&t
->sprites
.colors
.overlays
); i
++) {
2653 struct sprite
*color
, *color_mask
;
2654 struct sprite
*worked
, *unworked
;
2656 color
= *sprite_vector_get(&t
->sprites
.colors
.overlays
, i
);
2657 color_mask
= crop_sprite(color
, 0, 0, W
, H
, t
->sprites
.mask
.tile
, 0, 0);
2658 worked
= crop_sprite(color_mask
, 0, 0, W
, H
,
2659 t
->sprites
.mask
.worked_tile
, 0, 0);
2660 unworked
= crop_sprite(color_mask
, 0, 0, W
, H
,
2661 t
->sprites
.mask
.unworked_tile
, 0, 0);
2662 free_sprite(color_mask
);
2663 t
->sprites
.city
.worked_tile_overlay
.p
[i
] = worked
;
2664 t
->sprites
.city
.unworked_tile_overlay
.p
[i
] = unworked
;
2669 SET_SPRITE(grid
.unavailable
, "grid.unavailable");
2670 SET_SPRITE_OPT(grid
.nonnative
, "grid.nonnative");
2672 for (i
= 0; i
< EDGE_COUNT
; i
++) {
2675 if (i
== EDGE_UD
&& t
->hex_width
== 0) {
2677 } else if (i
== EDGE_LR
&& t
->hex_height
== 0) {
2681 fc_snprintf(buffer
, sizeof(buffer
), "grid.main.%s", edge_name
[i
]);
2682 SET_SPRITE(grid
.main
[i
], buffer
);
2684 fc_snprintf(buffer
, sizeof(buffer
), "grid.city.%s", edge_name
[i
]);
2685 SET_SPRITE(grid
.city
[i
], buffer
);
2687 fc_snprintf(buffer
, sizeof(buffer
), "grid.worked.%s", edge_name
[i
]);
2688 SET_SPRITE(grid
.worked
[i
], buffer
);
2690 fc_snprintf(buffer
, sizeof(buffer
), "grid.selected.%s", edge_name
[i
]);
2691 SET_SPRITE(grid
.selected
[i
], buffer
);
2693 fc_snprintf(buffer
, sizeof(buffer
), "grid.coastline.%s", edge_name
[i
]);
2694 SET_SPRITE(grid
.coastline
[i
], buffer
);
2696 for (j
= 0; j
< 2; j
++) {
2697 fc_snprintf(buffer
, sizeof(buffer
), "grid.borders.%c",
2699 SET_SPRITE(grid
.borders
[i
][j
], buffer
);
2704 /* We use direction-specific irrigation and farmland graphics, if they
2705 * are available. If not, we just fall back to the basic irrigation
2707 for (i
= 0; i
< t
->num_index_cardinal
; i
++) {
2708 fc_snprintf(buffer
, sizeof(buffer
), "tx.s_irrigation_%s",
2709 cardinal_index_str(t
, i
));
2710 SET_SPRITE_ALT(tx
.irrigation
[i
], buffer
, "tx.irrigation");
2712 for (i
= 0; i
< t
->num_index_cardinal
; i
++) {
2713 fc_snprintf(buffer
, sizeof(buffer
), "tx.s_farmland_%s",
2714 cardinal_index_str(t
, i
));
2715 SET_SPRITE_ALT(tx
.farmland
[i
], buffer
, "tx.farmland");
2718 switch (t
->darkness_style
) {
2722 case DARKNESS_ISORECT
:
2724 /* Isometric: take a single tx.darkness tile and split it into 4. */
2725 struct sprite
*darkness
= load_sprite(t
, "tx.darkness");
2726 const int W
= t
->normal_tile_width
, H
= t
->normal_tile_height
;
2727 int offsets
[4][2] = {{W
/ 2, 0}, {0, H
/ 2}, {W
/ 2, H
/ 2}, {0, 0}};
2730 tileset_error(LOG_FATAL
, _("Sprite tx.darkness missing."));
2732 for (i
= 0; i
< 4; i
++) {
2733 t
->sprites
.tx
.darkness
[i
] = crop_sprite(darkness
, offsets
[i
][0],
2734 offsets
[i
][1], W
/ 2, H
/ 2,
2739 case DARKNESS_CARD_SINGLE
:
2740 for (i
= 0; i
< t
->num_cardinal_tileset_dirs
; i
++) {
2741 enum direction8 dir
= t
->cardinal_tileset_dirs
[i
];
2743 fc_snprintf(buffer
, sizeof(buffer
), "tx.darkness_%s",
2744 dir_get_tileset_name(dir
));
2745 SET_SPRITE(tx
.darkness
[i
], buffer
);
2748 case DARKNESS_CARD_FULL
:
2749 for(i
= 1; i
< t
->num_index_cardinal
; i
++) {
2750 fc_snprintf(buffer
, sizeof(buffer
), "tx.darkness_%s",
2751 cardinal_index_str(t
, i
));
2752 SET_SPRITE(tx
.darkness
[i
], buffer
);
2755 case DARKNESS_CORNER
:
2756 t
->sprites
.tx
.fullfog
= fc_realloc(t
->sprites
.tx
.fullfog
,
2757 81 * sizeof(*t
->sprites
.tx
.fullfog
));
2758 for (i
= 0; i
< 81; i
++) {
2759 /* Unknown, fog, known. */
2760 char ids
[] = {'u', 'f', 'k'};
2761 char buf
[512] = "t.fog";
2762 int values
[4], j
, k
= i
;
2764 for (j
= 0; j
< 4; j
++) {
2768 cat_snprintf(buf
, sizeof(buf
), "_%c", ids
[values
[j
]]);
2772 t
->sprites
.tx
.fullfog
[i
] = load_sprite(t
, buf
);
2777 /* no other place to initialize these variables */
2778 sprite_vector_init(&t
->sprites
.nation_flag
);
2779 sprite_vector_init(&t
->sprites
.nation_shield
);
2782 /**************************************************************************
2783 Load sprites of one river type.
2784 **************************************************************************/
2785 static bool load_river_sprites(struct tileset
*t
,
2786 struct river_sprites
*store
, const char *tag_pfx
)
2789 const char dir_char
[] = "nsew";
2792 for (i
= 0; i
< t
->num_index_cardinal
; i
++) {
2793 fc_snprintf(buffer
, sizeof(buffer
), "%s_s_%s",
2794 tag_pfx
, cardinal_index_str(t
, i
));
2795 store
->spec
[i
] = load_sprite(t
, buffer
);
2796 if (store
->spec
[i
] == NULL
) {
2801 for (i
= 0; i
< 4; i
++) {
2802 fc_snprintf(buffer
, sizeof(buffer
), "%s_outlet_%c",
2803 tag_pfx
, dir_char
[i
]);
2804 store
->outlet
[i
] = load_sprite(t
, buffer
);
2805 if (store
->outlet
[i
] == NULL
) {
2813 /**************************************************************************
2814 Frees any internal buffers which are created by load_sprite. Should
2815 be called after the last (for a given period of time) load_sprite
2816 call. This saves a fair amount of memory, but it will take extra time
2817 the next time we start loading sprites again.
2818 **************************************************************************/
2819 void finish_loading_sprites(struct tileset
*t
)
2821 specfile_list_iterate(t
->specfiles
, sf
) {
2822 if (sf
->big_sprite
) {
2823 free_sprite(sf
->big_sprite
);
2824 sf
->big_sprite
= NULL
;
2826 } specfile_list_iterate_end
;
2829 /**********************************************************************
2830 Load the tiles; requires tilespec_read_toplevel() called previously.
2831 Leads to tile_sprites being allocated and filled with pointers
2832 to sprites. Also sets up and populates sprite_hash, and calls func
2833 to initialize 'sprites' structure.
2834 ***********************************************************************/
2835 void tileset_load_tiles(struct tileset
*t
)
2837 tileset_lookup_sprite_tags(t
);
2838 finish_loading_sprites(t
);
2841 /**********************************************************************
2842 Lookup sprite to match tag, or else to match alt if don't find,
2843 or else return NULL, and emit log message.
2844 ***********************************************************************/
2845 struct sprite
*tiles_lookup_sprite_tag_alt(struct tileset
*t
,
2846 enum log_level level
,
2847 const char *tag
, const char *alt
,
2853 /* (should get sprite_hash before connection) */
2854 fc_assert_ret_val_msg(NULL
!= t
->sprite_hash
, NULL
,
2855 "attempt to lookup for %s \"%s\" before "
2856 "sprite_hash setup", what
, name
);
2858 sp
= load_sprite(t
, tag
);
2861 sp
= load_sprite(t
, alt
);
2863 log_verbose("Using alternate graphic \"%s\" "
2864 "(instead of \"%s\") for %s \"%s\".",
2865 alt
, tag
, what
, name
);
2868 if (level
<= LOG_ERROR
) {
2869 tileset_error(level
, _("Don't have graphics tags \"%s\" or \"%s\" for %s \"%s\"."),
2870 tag
, alt
, what
, name
);
2872 log_base(level
, "Don't have graphics tags \"%s\" or \"%s\" for %s \"%s\".",
2873 tag
, alt
, what
, name
);
2879 /**********************************************************************
2880 Helper function to load sprite for one unit orientation
2881 ***********************************************************************/
2882 static bool tileset_setup_unit_direction(struct tileset
*t
,
2884 const char *base_str
,
2885 enum direction8 dir
,
2886 const char *dirsuffix
)
2890 fc_snprintf(buf
, sizeof(buf
), "%s_%s", base_str
, dirsuffix
);
2892 /* We don't use _alt graphics here, as that could lead to loading
2893 * real icon gfx, but alternative orientation gfx. Tileset author
2894 * probably meant icon gfx to be used as fallback for all orientations */
2895 t
->sprites
.units
.facing
[uidx
][dir
] = load_sprite(t
, buf
);
2897 if (t
->sprites
.units
.facing
[uidx
][dir
] != NULL
) {
2904 /**********************************************************************
2905 Try to setup all unit type sprites from single tag
2906 ***********************************************************************/
2907 bool static tileset_setup_unit_type_from_tag(struct tileset
*t
,
2908 int uidx
, const char *tag
)
2910 bool facing_sprites
= TRUE
;
2912 t
->sprites
.units
.icon
[uidx
] = load_sprite(t
, tag
);
2914 #define LOAD_FACING_SPRITE(dir, dname) \
2915 if (!tileset_setup_unit_direction(t, uidx, tag, dir, dname)) { \
2916 facing_sprites = FALSE; \
2919 LOAD_FACING_SPRITE(DIR8_NORTHWEST
, "nw");
2920 LOAD_FACING_SPRITE(DIR8_NORTH
, "n");
2921 LOAD_FACING_SPRITE(DIR8_NORTHEAST
, "ne");
2922 LOAD_FACING_SPRITE(DIR8_WEST
, "w");
2923 LOAD_FACING_SPRITE(DIR8_EAST
, "e");
2924 LOAD_FACING_SPRITE(DIR8_SOUTHWEST
, "sw");
2925 LOAD_FACING_SPRITE(DIR8_SOUTH
, "s");
2926 LOAD_FACING_SPRITE(DIR8_SOUTHEAST
, "se");
2928 if (!facing_sprites
&& t
->sprites
.units
.icon
[uidx
] == NULL
) {
2929 /* Neither icon gfx or orientation sprites */
2935 #undef LOAD_FACING_SPRITE
2938 /**********************************************************************
2939 Set unit_type sprite value; should only happen after
2940 tilespec_load_tiles().
2941 ***********************************************************************/
2942 void tileset_setup_unit_type(struct tileset
*t
, struct unit_type
*ut
)
2944 int uidx
= utype_index(ut
);
2946 if (!tileset_setup_unit_type_from_tag(t
, uidx
, ut
->graphic_str
)
2947 && !tileset_setup_unit_type_from_tag(t
, uidx
, ut
->graphic_alt
)) {
2948 tileset_error(LOG_FATAL
, _("Missing %s unit tag \"%s\" and alternative \"%s\"."),
2949 utype_rule_name(ut
), ut
->graphic_str
, ut
->graphic_alt
);
2953 /**********************************************************************
2954 Set improvement_type sprite value; should only happen after
2955 tilespec_load_tiles().
2956 ***********************************************************************/
2957 void tileset_setup_impr_type(struct tileset
*t
,
2958 struct impr_type
*pimprove
)
2960 t
->sprites
.building
[improvement_index(pimprove
)] =
2961 tiles_lookup_sprite_tag_alt(t
, LOG_VERBOSE
, pimprove
->graphic_str
,
2962 pimprove
->graphic_alt
, "improvement",
2963 improvement_rule_name(pimprove
));
2965 /* should maybe do something if NULL, eg generic default? */
2968 /**********************************************************************
2969 Set tech_type sprite value; should only happen after
2970 tilespec_load_tiles().
2971 ***********************************************************************/
2972 void tileset_setup_tech_type(struct tileset
*t
,
2973 struct advance
*padvance
)
2975 if (valid_advance(padvance
)) {
2976 t
->sprites
.tech
[advance_index(padvance
)] =
2977 tiles_lookup_sprite_tag_alt(t
, LOG_VERBOSE
, padvance
->graphic_str
,
2978 padvance
->graphic_alt
, "technology",
2979 advance_rule_name(padvance
));
2981 /* should maybe do something if NULL, eg generic default? */
2983 t
->sprites
.tech
[advance_index(padvance
)] = NULL
;
2987 /****************************************************************************
2988 Set resource sprite values; should only happen after
2989 tilespec_load_tiles().
2990 ****************************************************************************/
2991 void tileset_setup_resource(struct tileset
*t
,
2992 const struct resource
*presource
)
2994 fc_assert_ret(NULL
!= presource
);
2995 t
->sprites
.resource
[resource_index(presource
)] =
2996 tiles_lookup_sprite_tag_alt(t
, LOG_VERBOSE
, presource
->graphic_str
,
2997 presource
->graphic_alt
, "resource",
2998 resource_rule_name(presource
));
3001 /****************************************************************************
3002 Set road sprite values; should only happen after
3003 tilespec_load_tiles().
3004 ****************************************************************************/
3005 void tileset_setup_road(struct tileset
*t
,
3006 struct road_type
*proad
)
3008 char full_tag_name
[MAX_LEN_NAME
+ strlen("_isolated")];
3009 char full_alt_name
[MAX_LEN_NAME
+ strlen("_isolated")];
3010 const int id
= road_index(proad
);
3012 enum roadstyle_id
*roadstyle
;
3014 if (!rstyle_hash_lookup(t
->rstyle_hash
, proad
->graphic_str
,
3016 && !rstyle_hash_lookup(t
->rstyle_hash
, proad
->graphic_alt
,
3018 tileset_error(LOG_FATAL
, _("No roadstyle for \"%s\" or \"%s\"."),
3020 proad
->graphic_alt
);
3023 t
->sprites
.roads
[id
].roadstyle
= *roadstyle
;
3025 if (*roadstyle
== RSTYLE_RIVER
) {
3026 road_type_list_append(t
->rivers
, proad
);
3029 /* Isolated road graphics are used by RSTYLE_ALL_SEPARATE and
3030 RSTYLE_PARITY_COMBINED. */
3031 if (*roadstyle
== RSTYLE_ALL_SEPARATE
|| *roadstyle
== RSTYLE_PARITY_COMBINED
) {
3032 fc_snprintf(full_tag_name
, sizeof(full_tag_name
),
3033 "%s_isolated", proad
->graphic_str
);
3034 fc_snprintf(full_alt_name
, sizeof(full_alt_name
),
3035 "%s_isolated", proad
->graphic_alt
);
3037 SET_SPRITE_ALT(roads
[id
].isolated
, full_tag_name
, full_alt_name
);
3040 if (*roadstyle
== RSTYLE_ALL_SEPARATE
) {
3041 /* RSTYLE_ALL_SEPARATE has just 8 additional sprites for each road type:
3042 * one going off in each direction. */
3043 for (i
= 0; i
< t
->num_valid_tileset_dirs
; i
++) {
3044 enum direction8 dir
= t
->valid_tileset_dirs
[i
];
3045 const char *dir_name
= dir_get_tileset_name(dir
);
3047 fc_snprintf(full_tag_name
, sizeof(full_tag_name
),
3048 "%s_%s", proad
->graphic_str
, dir_name
);
3049 fc_snprintf(full_alt_name
, sizeof(full_alt_name
),
3050 "%s_%s", proad
->graphic_alt
, dir_name
);
3052 SET_SPRITE_ALT(roads
[id
].u
.dir
[i
], full_tag_name
, full_alt_name
);
3054 } else if (*roadstyle
== RSTYLE_PARITY_COMBINED
) {
3055 int num_index
= 1 << (t
->num_valid_tileset_dirs
/ 2), j
;
3057 /* RSTYLE_PARITY_COMBINED has 32 additional sprites for each road type:
3058 * 16 each for cardinal and diagonal directions. Each set
3059 * of 16 provides a NSEW-indexed sprite to provide connectors for
3060 * all rails in the cardinal/diagonal directions. The 0 entry is
3061 * unused (the "isolated" sprite is used instead). */
3063 for (i
= 1; i
< num_index
; i
++) {
3064 char c
[64] = "", d
[64] = "";
3066 for (j
= 0; j
< t
->num_valid_tileset_dirs
/ 2; j
++) {
3067 int value
= (i
>> j
) & 1;
3069 cat_snprintf(c
, sizeof(c
), "%s%d",
3070 dir_get_tileset_name(t
->valid_tileset_dirs
[2 * j
]),
3072 cat_snprintf(d
, sizeof(d
), "%s%d",
3073 dir_get_tileset_name(t
->valid_tileset_dirs
[2 * j
+ 1]),
3077 fc_snprintf(full_tag_name
, sizeof(full_tag_name
),
3078 "%s_c_%s", proad
->graphic_str
, c
);
3079 fc_snprintf(full_alt_name
, sizeof(full_alt_name
),
3080 "%s_c_%s", proad
->graphic_alt
, c
);
3082 SET_SPRITE_ALT(roads
[id
].u
.combo
.even
[i
], full_tag_name
, full_alt_name
);
3084 fc_snprintf(full_tag_name
, sizeof(full_tag_name
),
3085 "%s_d_%s", proad
->graphic_str
, d
);
3086 fc_snprintf(full_alt_name
, sizeof(full_alt_name
),
3087 "%s_d_%s", proad
->graphic_alt
, d
);
3089 SET_SPRITE_ALT(roads
[id
].u
.combo
.odd
[i
], full_tag_name
, full_alt_name
);
3091 } else if (*roadstyle
== RSTYLE_ALL_COMBINED
) {
3092 /* RSTYLE_ALL_COMBINED includes 256 sprites, one for every possibility.
3093 * Just go around clockwise, with all combinations. */
3094 for (i
= 0; i
< t
->num_index_valid
; i
++) {
3095 char *idx_str
= valid_index_str(t
, i
);
3097 fc_snprintf(full_tag_name
, sizeof(full_tag_name
),
3098 "%s_%s", proad
->graphic_str
, idx_str
);
3099 fc_snprintf(full_alt_name
, sizeof(full_alt_name
),
3100 "%s_%s", proad
->graphic_alt
, idx_str
);
3102 SET_SPRITE_ALT(roads
[id
].u
.total
[i
], full_tag_name
, full_alt_name
);
3104 } else if (*roadstyle
== RSTYLE_RIVER
) {
3105 if (!load_river_sprites(t
, &t
->sprites
.roads
[id
].u
.rivers
,
3106 proad
->graphic_str
)) {
3107 if (!load_river_sprites(t
, &t
->sprites
.roads
[id
].u
.rivers
,
3108 proad
->graphic_alt
)) {
3109 tileset_error(LOG_FATAL
, _("Cannot load river \"%s\" or \"%s\""),
3110 proad
->graphic_str
, proad
->graphic_alt
);
3117 /* Corner road graphics are used by RSTYLE_ALL_SEPARATE and
3118 * RSTYLE_PARITY_COMBINED. */
3119 if (*roadstyle
== RSTYLE_ALL_SEPARATE
|| *roadstyle
== RSTYLE_PARITY_COMBINED
) {
3120 for (i
= 0; i
< t
->num_valid_tileset_dirs
; i
++) {
3121 enum direction8 dir
= t
->valid_tileset_dirs
[i
];
3123 if (!is_cardinal_tileset_dir(t
, dir
)) {
3124 const char *dtn
= dir_get_tileset_name(dir
);
3126 fc_snprintf(full_tag_name
, sizeof(full_tag_name
),
3127 "%s_c_%s", proad
->graphic_str
, dtn
);
3128 fc_snprintf(full_alt_name
, sizeof(full_alt_name
),
3129 "%s_c_%s", proad
->graphic_alt
, dtn
);
3131 SET_SPRITE_ALT_OPT(roads
[id
].corner
[dir
], full_tag_name
, full_alt_name
);
3136 t
->sprites
.roads
[id
].activity
= load_sprite(t
, proad
->activity_gfx
);
3137 if (t
->sprites
.roads
[id
].activity
== NULL
) {
3138 t
->sprites
.roads
[id
].activity
= load_sprite(t
, proad
->act_gfx_alt
);
3139 if (t
->sprites
.roads
[id
].activity
== NULL
) {
3140 tileset_error(LOG_FATAL
, _("Missing %s building activity tag \"%s\" and alternative \"%s\"."),
3141 road_rule_name(proad
), proad
->activity_gfx
, proad
->act_gfx_alt
);
3146 /****************************************************************************
3147 Set base sprite values; should only happen after
3148 tilespec_load_tiles().
3149 ****************************************************************************/
3150 void tileset_setup_base(struct tileset
*t
,
3151 const struct base_type
*pbase
)
3153 char full_tag_name
[MAX_LEN_NAME
+ strlen("_fg")];
3154 const int id
= base_index(pbase
);
3156 fc_assert_ret(id
>= 0 && id
< base_count());
3158 sz_strlcpy(full_tag_name
, pbase
->graphic_str
);
3159 strcat(full_tag_name
, "_bg");
3160 t
->sprites
.bases
[id
].background
= load_sprite(t
, full_tag_name
);
3162 sz_strlcpy(full_tag_name
, pbase
->graphic_str
);
3163 strcat(full_tag_name
, "_mg");
3164 t
->sprites
.bases
[id
].middleground
= load_sprite(t
, full_tag_name
);
3166 sz_strlcpy(full_tag_name
, pbase
->graphic_str
);
3167 strcat(full_tag_name
, "_fg");
3168 t
->sprites
.bases
[id
].foreground
= load_sprite(t
, full_tag_name
);
3170 if (t
->sprites
.bases
[id
].background
== NULL
3171 && t
->sprites
.bases
[id
].middleground
== NULL
3172 && t
->sprites
.bases
[id
].foreground
== NULL
) {
3173 /* No primary graphics at all. Try alternative */
3174 log_verbose("Using alternate graphic \"%s\" "
3175 "(instead of \"%s\") for base \"%s\".",
3176 pbase
->graphic_alt
, pbase
->graphic_str
,
3177 base_rule_name(pbase
));
3179 sz_strlcpy(full_tag_name
, pbase
->graphic_alt
);
3180 strcat(full_tag_name
, "_bg");
3181 t
->sprites
.bases
[id
].background
= load_sprite(t
, full_tag_name
);
3183 sz_strlcpy(full_tag_name
, pbase
->graphic_alt
);
3184 strcat(full_tag_name
, "_mg");
3185 t
->sprites
.bases
[id
].middleground
= load_sprite(t
, full_tag_name
);
3187 sz_strlcpy(full_tag_name
, pbase
->graphic_alt
);
3188 strcat(full_tag_name
, "_fg");
3189 t
->sprites
.bases
[id
].foreground
= load_sprite(t
, full_tag_name
);
3191 if (t
->sprites
.bases
[id
].background
== NULL
3192 && t
->sprites
.bases
[id
].middleground
== NULL
3193 && t
->sprites
.bases
[id
].foreground
== NULL
) {
3194 /* Cannot find alternative graphics either */
3195 tileset_error(LOG_FATAL
, _("No graphics for base \"%s\" at all!"),
3196 base_rule_name(pbase
));
3200 t
->sprites
.bases
[id
].activity
= load_sprite(t
, pbase
->activity_gfx
);
3201 if (t
->sprites
.bases
[id
].activity
== NULL
) {
3202 t
->sprites
.bases
[id
].activity
= load_sprite(t
, pbase
->act_gfx_alt
);
3203 if (t
->sprites
.bases
[id
].activity
== NULL
) {
3204 tileset_error(LOG_FATAL
, _("Missing %s building activity tag \"%s\" and alternative \"%s\"."),
3205 base_rule_name(pbase
), pbase
->activity_gfx
, pbase
->act_gfx_alt
);
3211 /**********************************************************************
3212 Set tile_type sprite values; should only happen after
3213 tilespec_load_tiles().
3214 ***********************************************************************/
3215 void tileset_setup_tile_type(struct tileset
*t
,
3216 const struct terrain
*pterrain
)
3218 struct drawing_data
*draw
;
3219 struct sprite
*sprite
;
3220 char buffer
[MAX_LEN_NAME
+ 20];
3223 if (0 == strlen(terrain_rule_name(pterrain
))) {
3227 if (!drawing_hash_lookup(t
->tile_hash
, pterrain
->graphic_str
, &draw
)
3228 && !drawing_hash_lookup(t
->tile_hash
, pterrain
->graphic_alt
, &draw
)) {
3229 tileset_error(LOG_FATAL
, _("Terrain \"%s\": no graphic tile \"%s\" or \"%s\"."),
3230 terrain_rule_name(pterrain
), pterrain
->graphic_str
,
3231 pterrain
->graphic_alt
);
3234 /* Set up each layer of the drawing. */
3235 for (l
= 0; l
< draw
->num_layers
; l
++) {
3236 struct drawing_layer
*dlp
= &draw
->layer
[l
];
3237 struct tileset_layer
*tslp
= &t
->layers
[l
];
3238 sprite_vector_init(&dlp
->base
);
3239 sprite_vector_init(&dlp
->allocated
);
3241 switch (dlp
->sprite_type
) {
3243 switch (dlp
->match_style
) {
3245 /* Load whole sprites for this tile. */
3246 for (i
= 0; ; i
++) {
3247 fc_snprintf(buffer
, sizeof(buffer
), "t.l%d.%s%d",
3248 l
, draw
->name
, i
+ 1);
3249 sprite
= load_sprite(t
, buffer
);
3253 sprite_vector_reserve(&dlp
->base
, i
+ 1);
3254 dlp
->base
.p
[i
] = sprite
;
3256 /* check for base sprite, allowing missing sprites above base */
3257 if (0 == i
&& 0 == l
) {
3258 tileset_error(LOG_FATAL
, _("Missing base sprite tag \"%s\"."), buffer
);
3262 /* Load 16 cardinally-matched sprites. */
3263 for (i
= 0; i
< t
->num_index_cardinal
; i
++) {
3264 fc_snprintf(buffer
, sizeof(buffer
), "t.l%d.%s_%s",
3265 l
, draw
->name
, cardinal_index_str(t
, i
));
3267 tiles_lookup_sprite_tag_alt(t
, LOG_FATAL
, buffer
, "",
3269 terrain_rule_name(pterrain
));
3274 fc_assert(FALSE
); /* not yet defined */
3280 const int count
= dlp
->match_indices
;
3281 int number
= NUM_CORNER_DIRS
;
3283 switch (dlp
->match_style
) {
3289 /* N directions (NSEW) * 3 dimensions of matching */
3290 fc_assert(count
== 2);
3291 number
= NUM_CORNER_DIRS
* 2 * 2 * 2;
3295 /* N directions (NSEW) * 3 dimensions of matching */
3296 /* could use exp() or expi() here? */
3297 number
= NUM_CORNER_DIRS
* count
* count
* count
;
3302 = fc_calloc(number
, sizeof(*dlp
->cells
));
3304 for (i
= 0; i
< number
; i
++) {
3305 enum direction4 dir
= i
% NUM_CORNER_DIRS
;
3306 int value
= i
/ NUM_CORNER_DIRS
;
3308 switch (dlp
->match_style
) {
3310 fc_snprintf(buffer
, sizeof(buffer
), "t.l%d.%s_cell_%c",
3311 l
, draw
->name
, direction4letters
[dir
]);
3313 tiles_lookup_sprite_tag_alt(t
, LOG_FATAL
, buffer
, "",
3315 terrain_rule_name(pterrain
));
3318 fc_snprintf(buffer
, sizeof(buffer
), "t.l%d.%s_cell_%c%d%d%d",
3319 l
, draw
->name
, direction4letters
[dir
],
3320 (value
) & 1, (value
>> 1) & 1, (value
>> 2) & 1);
3322 tiles_lookup_sprite_tag_alt(t
, LOG_FATAL
, buffer
, "",
3323 "same cell terrain",
3324 terrain_rule_name(pterrain
));
3327 fc_snprintf(buffer
, sizeof(buffer
), "t.l%d.%s_cell_%c_%c_%c_%c",
3328 l
, draw
->name
, direction4letters
[dir
],
3329 tslp
->match_types
[dlp
->match_index
[(value
) & 1]][0],
3330 tslp
->match_types
[dlp
->match_index
[(value
>> 1) & 1]][0],
3331 tslp
->match_types
[dlp
->match_index
[(value
>> 2) & 1]][0]);
3333 tiles_lookup_sprite_tag_alt(t
, LOG_FATAL
, buffer
, "",
3334 "cell pair terrain",
3335 terrain_rule_name(pterrain
));
3339 int this = dlp
->match_index
[0];
3343 v1
= dlp
->match_index
[value
% count
];
3345 v2
= dlp
->match_index
[value
% count
];
3347 v3
= dlp
->match_index
[value
% count
];
3349 fc_assert(v1
< count
&& v2
< count
&& v3
< count
);
3351 /* Assume merged cells. This should be a separate option. */
3372 default: /* avoid warnings */
3380 /* Use first character of match_types,
3381 * already checked for uniqueness. */
3382 fc_snprintf(buffer
, sizeof(buffer
),
3383 "t.l%d.cellgroup_%c_%c_%c_%c", l
,
3384 tslp
->match_types
[n
][0], tslp
->match_types
[e
][0],
3385 tslp
->match_types
[s
][0], tslp
->match_types
[w
][0]);
3386 sprite
= load_sprite(t
, buffer
);
3389 /* Crop the sprite to separate this cell. */
3390 int vec_size
= sprite_vector_size(&dlp
->allocated
);
3392 const int W
= t
->normal_tile_width
;
3393 const int H
= t
->normal_tile_height
;
3394 int x
[4] = {W
/ 4, W
/ 4, 0, W
/ 2};
3395 int y
[4] = {H
/ 2, 0, H
/ 4, H
/ 4};
3396 int xo
[4] = {0, 0, -W
/ 2, W
/ 2};
3397 int yo
[4] = {H
/ 2, -H
/ 2, 0, 0};
3399 sprite
= crop_sprite(sprite
,
3400 x
[dir
], y
[dir
], W
/ 2, H
/ 2,
3401 t
->sprites
.mask
.tile
,
3404 /* We allocated new sprite with crop_sprite. Store its
3405 * address so we can free it. */
3406 sprite_vector_reserve(&dlp
->allocated
, vec_size
+ 1);
3407 dlp
->allocated
.p
[vec_size
] = sprite
;
3409 log_error("Terrain graphics tag \"%s\" missing.", buffer
);
3412 dlp
->cells
[i
] = sprite
;
3422 /* try an optional special name */
3423 fc_snprintf(buffer
, sizeof(buffer
), "t.blend.%s", draw
->name
);
3425 tiles_lookup_sprite_tag_alt(t
, LOG_VERBOSE
, buffer
, "",
3427 terrain_rule_name(pterrain
));
3429 if (draw
->blending
> 0) {
3430 const int l
= draw
->blending
- 1;
3432 if (NULL
== draw
->blender
) {
3434 /* try an already loaded base */
3435 while (NULL
== draw
->blender
3436 && i
< draw
->blending
3437 && 0 < draw
->layer
[i
].base
.size
) {
3438 draw
->blender
= draw
->layer
[i
++].base
.p
[0];
3442 if (NULL
== draw
->blender
) {
3443 /* try an unloaded base name */
3444 fc_snprintf(buffer
, sizeof(buffer
), "t.l%d.%s1", l
, draw
->name
);
3446 tiles_lookup_sprite_tag_alt(t
, LOG_FATAL
, buffer
, "",
3447 "base (blend) terrain",
3448 terrain_rule_name(pterrain
));
3452 if (NULL
!= draw
->blender
) {
3453 /* Set up blending sprites. This only works in iso-view! */
3454 const int W
= t
->normal_tile_width
;
3455 const int H
= t
->normal_tile_height
;
3456 const int offsets
[4][2] = {
3457 {W
/ 2, 0}, {0, H
/ 2}, {W
/ 2, H
/ 2}, {0, 0}
3459 enum direction4 dir
= 0;
3461 for (; dir
< 4; dir
++) {
3462 draw
->blend
[dir
] = crop_sprite(draw
->blender
,
3463 offsets
[dir
][0], offsets
[dir
][1],
3465 t
->sprites
.dither_tile
, 0, 0);
3469 if (draw
->mine_tag
) {
3470 draw
->mine
= load_sprite(t
, draw
->mine_tag
);
3475 t
->sprites
.drawing
[terrain_index(pterrain
)] = draw
;
3478 /**********************************************************************
3479 Set government sprite value; should only happen after
3480 tilespec_load_tiles().
3481 ***********************************************************************/
3482 void tileset_setup_government(struct tileset
*t
,
3483 struct government
*gov
)
3485 t
->sprites
.government
[government_index(gov
)] =
3486 tiles_lookup_sprite_tag_alt(t
, LOG_FATAL
, gov
->graphic_str
,
3487 gov
->graphic_alt
, "government",
3488 government_rule_name(gov
));
3490 /* should probably do something if NULL, eg generic default? */
3493 /**********************************************************************
3494 Set nation flag sprite value; should only happen after
3495 tilespec_load_tiles().
3496 ***********************************************************************/
3497 void tileset_setup_nation_flag(struct tileset
*t
,
3498 struct nation_type
*nation
)
3500 char *tags
[] = {nation
->flag_graphic_str
,
3501 nation
->flag_graphic_alt
,
3504 struct sprite
*flag
= NULL
, *shield
= NULL
;
3507 for (i
= 0; tags
[i
] && !flag
; i
++) {
3508 fc_snprintf(buf
, sizeof(buf
), "f.%s", tags
[i
]);
3509 flag
= load_sprite(t
, buf
);
3511 for (i
= 0; tags
[i
] && !shield
; i
++) {
3512 fc_snprintf(buf
, sizeof(buf
), "f.shield.%s", tags
[i
]);
3513 shield
= load_sprite(t
, buf
);
3515 if (!flag
|| !shield
) {
3516 /* Should never get here because of the f.unknown fallback. */
3517 tileset_error(LOG_FATAL
, _("Nation %s: no national flag."), nation_rule_name(nation
));
3520 sprite_vector_reserve(&t
->sprites
.nation_flag
, nation_count());
3521 t
->sprites
.nation_flag
.p
[nation_index(nation
)] = flag
;
3523 sprite_vector_reserve(&t
->sprites
.nation_shield
, nation_count());
3524 t
->sprites
.nation_shield
.p
[nation_index(nation
)] = shield
;
3527 /**********************************************************************
3528 Return the flag graphic to be used by the city.
3529 ***********************************************************************/
3530 struct sprite
*get_city_flag_sprite(const struct tileset
*t
,
3531 const struct city
*pcity
)
3533 return get_nation_flag_sprite(t
, nation_of_city(pcity
));
3536 /**********************************************************************
3537 Return a sprite for the national flag for this unit.
3538 ***********************************************************************/
3539 static struct sprite
*get_unit_nation_flag_sprite(const struct tileset
*t
,
3540 const struct unit
*punit
)
3542 struct nation_type
*pnation
= nation_of_unit(punit
);
3544 if (draw_unit_shields
) {
3545 return t
->sprites
.nation_shield
.p
[nation_index(pnation
)];
3547 return t
->sprites
.nation_flag
.p
[nation_index(pnation
)];
3551 #define FULL_TILE_X_OFFSET ((t->normal_tile_width - t->full_tile_width) / 2)
3552 #define FULL_TILE_Y_OFFSET (t->normal_tile_height - t->full_tile_height)
3554 #define ADD_SPRITE(s, draw_fog, x_offset, y_offset) \
3555 (fc_assert(s != NULL), \
3557 sprs->foggable = (draw_fog && t->fogstyle == FOG_AUTO), \
3558 sprs->offset_x = x_offset, \
3559 sprs->offset_y = y_offset, \
3561 #define ADD_SPRITE_SIMPLE(s) ADD_SPRITE(s, TRUE, 0, 0)
3562 #define ADD_SPRITE_FULL(s) \
3563 ADD_SPRITE(s, TRUE, FULL_TILE_X_OFFSET, FULL_TILE_Y_OFFSET)
3565 /**************************************************************************
3566 Assemble some data that is used in building the tile sprite arrays.
3567 (map_x, map_y) : the (normalized) map position
3568 The values we fill in:
3569 tterrain_near : terrain types of all adjacent terrain
3570 tspecial_near : specials of all adjacent terrain
3571 **************************************************************************/
3572 static void build_tile_data(const struct tile
*ptile
,
3573 struct terrain
*pterrain
,
3574 struct terrain
**tterrain_near
,
3575 bv_special
*tspecial_near
,
3576 bv_roads
*troad_near
)
3578 enum direction8 dir
;
3580 /* Loop over all adjacent tiles. We should have an iterator for this. */
3581 for (dir
= 0; dir
< 8; dir
++) {
3582 struct tile
*tile1
= mapstep(ptile
, dir
);
3584 if (tile1
&& client_tile_get_known(tile1
) != TILE_UNKNOWN
) {
3585 struct terrain
*terrain1
= tile_terrain(tile1
);
3587 if (NULL
!= terrain1
) {
3588 tterrain_near
[dir
] = terrain1
;
3589 tspecial_near
[dir
] = tile_specials(tile1
);
3590 troad_near
[dir
] = tile_roads(tile1
);
3593 log_error("build_tile_data() tile (%d,%d) has no terrain!",
3596 /* At the edges of the (known) map, pretend the same terrain continued
3597 * past the edge of the map. */
3598 tterrain_near
[dir
] = pterrain
;
3599 BV_CLR_ALL(tspecial_near
[dir
]);
3600 BV_CLR_ALL(troad_near
[dir
]);
3604 /**********************************************************************
3605 Fill in the sprite array for the unit type.
3606 ***********************************************************************/
3607 static int fill_unit_type_sprite_array(const struct tileset
*t
,
3608 struct drawn_sprite
*sprs
,
3609 const struct unit_type
*putype
,
3610 enum direction8 facing
)
3612 struct drawn_sprite
*save_sprs
= sprs
;
3613 struct sprite
*uspr
= get_unittype_sprite(t
, putype
, facing
, FALSE
);
3615 ADD_SPRITE(uspr
, TRUE
,
3616 FULL_TILE_X_OFFSET
+ t
->unit_offset_x
,
3617 FULL_TILE_Y_OFFSET
+ t
->unit_offset_y
);
3619 return sprs
- save_sprs
;
3622 /**********************************************************************
3623 Fill in the sprite array for the unit.
3624 ***********************************************************************/
3625 static int fill_unit_sprite_array(const struct tileset
*t
,
3626 struct drawn_sprite
*sprs
,
3627 const struct unit
*punit
,
3628 bool stack
, bool backdrop
)
3630 struct drawn_sprite
*save_sprs
= sprs
;
3632 struct unit_type
*ptype
= unit_type(punit
);
3635 if (!solid_color_behind_units
) {
3636 ADD_SPRITE(get_unit_nation_flag_sprite(t
, punit
), TRUE
,
3637 FULL_TILE_X_OFFSET
+ t
->unit_flag_offset_x
,
3638 FULL_TILE_Y_OFFSET
+ t
->unit_flag_offset_y
);
3640 /* Taken care of in the LAYER_BACKGROUND. */
3644 /* Add the sprite for the unit type. */
3645 sprs
+= fill_unit_type_sprite_array(t
, sprs
, ptype
,
3648 if (t
->sprites
.unit
.loaded
&& unit_transported(punit
)) {
3649 ADD_SPRITE_FULL(t
->sprites
.unit
.loaded
);
3652 if(punit
->activity
!=ACTIVITY_IDLE
) {
3653 struct sprite
*s
= NULL
;
3654 switch(punit
->activity
) {
3656 s
= t
->sprites
.unit
.mine
;
3658 case ACTIVITY_POLLUTION
:
3659 s
= t
->sprites
.unit
.pollution
;
3661 case ACTIVITY_FALLOUT
:
3662 s
= t
->sprites
.unit
.fallout
;
3664 case ACTIVITY_PILLAGE
:
3665 s
= t
->sprites
.unit
.pillage
;
3667 case ACTIVITY_IRRIGATE
:
3668 s
= t
->sprites
.unit
.irrigate
;
3670 case ACTIVITY_EXPLORE
:
3671 s
= t
->sprites
.unit
.auto_explore
;
3673 case ACTIVITY_FORTIFIED
:
3674 s
= t
->sprites
.unit
.fortified
;
3676 case ACTIVITY_FORTIFYING
:
3677 s
= t
->sprites
.unit
.fortifying
;
3679 case ACTIVITY_SENTRY
:
3680 s
= t
->sprites
.unit
.sentry
;
3683 s
= t
->sprites
.unit
.go_to
;
3685 case ACTIVITY_TRANSFORM
:
3686 s
= t
->sprites
.unit
.transform
;
3689 s
= t
->sprites
.bases
[punit
->activity_target
.obj
.base
].activity
;
3691 case ACTIVITY_GEN_ROAD
:
3692 s
= t
->sprites
.roads
[punit
->activity_target
.obj
.road
].activity
;
3694 case ACTIVITY_CONVERT
:
3695 s
= t
->sprites
.unit
.convert
;
3704 if (punit
->ai_controlled
&& punit
->activity
!= ACTIVITY_EXPLORE
) {
3705 if (is_military_unit(punit
)) {
3706 ADD_SPRITE_FULL(t
->sprites
.unit
.auto_attack
);
3708 ADD_SPRITE_FULL(t
->sprites
.unit
.auto_settler
);
3712 if (unit_has_orders(punit
)) {
3713 if (punit
->orders
.repeat
) {
3714 ADD_SPRITE_FULL(t
->sprites
.unit
.patrol
);
3715 } else if (punit
->activity
!= ACTIVITY_IDLE
) {
3716 ADD_SPRITE_SIMPLE(t
->sprites
.unit
.connect
);
3718 ADD_SPRITE_FULL(t
->sprites
.unit
.go_to
);
3722 if (punit
->battlegroup
!= BATTLEGROUP_NONE
) {
3723 ADD_SPRITE_FULL(t
->sprites
.unit
.battlegroup
[punit
->battlegroup
]);
3726 if (t
->sprites
.unit
.lowfuel
3727 && utype_fuel(ptype
)
3729 && punit
->moves_left
<= 2 * SINGLE_MOVE
) {
3730 /* Show a low-fuel graphic if the plane has 2 or fewer moves left. */
3731 ADD_SPRITE_FULL(t
->sprites
.unit
.lowfuel
);
3733 if (t
->sprites
.unit
.tired
3734 && punit
->moves_left
< SINGLE_MOVE
3735 && ptype
->move_rate
> 0) {
3736 /* Show a "tired" graphic if the unit has fewer than one move
3737 * remaining, except for units for which it's full movement. */
3738 ADD_SPRITE_FULL(t
->sprites
.unit
.tired
);
3741 if (stack
|| punit
->client
.occupied
) {
3742 ADD_SPRITE_FULL(t
->sprites
.unit
.stack
);
3745 if (t
->sprites
.unit
.vet_lev
[punit
->veteran
]) {
3746 ADD_SPRITE_FULL(t
->sprites
.unit
.vet_lev
[punit
->veteran
]);
3749 ihp
= ((NUM_TILES_HP_BAR
-1)*punit
->hp
) / ptype
->hp
;
3750 ihp
= CLIP(0, ihp
, NUM_TILES_HP_BAR
-1);
3751 ADD_SPRITE_FULL(t
->sprites
.unit
.hp_bar
[ihp
]);
3753 return sprs
- save_sprs
;
3756 /**************************************************************************
3757 Add any corner road sprites to the sprite array.
3758 **************************************************************************/
3759 static int fill_road_corner_sprites(const struct tileset
*t
,
3760 const struct road_type
*proad
,
3761 struct drawn_sprite
*sprs
,
3762 bool road
, bool *road_near
,
3763 bool hider
, bool *hider_near
)
3765 struct drawn_sprite
*saved_sprs
= sprs
;
3767 int road_idx
= road_index(proad
);
3769 if (is_cardinal_only_road(proad
)) {
3773 fc_assert_ret_val(draw_roads_rails
, 0);
3775 /* Roads going diagonally adjacent to this tile need to be
3776 * partly drawn on this tile. */
3778 /* Draw the corner sprite if:
3779 * - There is a diagonal road (not rail!) between two adjacent tiles.
3780 * - There is no diagonal road (not rail!) that intersects this road.
3781 * The logic is simple: roads are drawn underneath railrods, but are
3782 * not always covered by them (even in the corners!). But if a railroad
3783 * connects two tiles, only the railroad (no road) is drawn between
3786 for (i
= 0; i
< t
->num_valid_tileset_dirs
; i
++) {
3787 enum direction8 dir
= t
->valid_tileset_dirs
[i
];
3789 if (!is_cardinal_tileset_dir(t
, dir
)) {
3790 /* Draw corner sprites for this non-cardinal direction. */
3791 int cw
= (i
+ 1) % t
->num_valid_tileset_dirs
;
3793 = (i
+ t
->num_valid_tileset_dirs
- 1) % t
->num_valid_tileset_dirs
;
3794 enum direction8 dir_cw
= t
->valid_tileset_dirs
[cw
];
3795 enum direction8 dir_ccw
= t
->valid_tileset_dirs
[ccw
];
3797 if (t
->sprites
.roads
[road_idx
].corner
[dir
]
3798 && (road_near
[dir_cw
] && road_near
[dir_ccw
]
3799 && !(hider_near
[dir_cw
] && hider_near
[dir_ccw
]))
3800 && !(road
&& road_near
[dir
] && !(hider
&& hider_near
[dir
]))) {
3801 ADD_SPRITE_SIMPLE(t
->sprites
.roads
[road_idx
].corner
[dir
]);
3806 return sprs
- saved_sprs
;
3809 /**************************************************************************
3810 Fill all road and rail sprites into the sprite array.
3811 **************************************************************************/
3812 static int fill_road_sprite_array(const struct tileset
*t
,
3813 const struct road_type
*proad
,
3814 struct drawn_sprite
*sprs
,
3816 bv_roads
*troad_near
,
3817 struct terrain
*tterrain_near
[8],
3818 const struct city
*pcity
)
3820 struct drawn_sprite
*saved_sprs
= sprs
;
3821 bool road
, road_near
[8], hider
, hider_near
[8];
3822 bool land_near
[8], hland_near
[8];
3823 bool draw_road
[8], draw_single_road
;
3824 enum direction8 dir
;
3827 enum roadstyle_id roadstyle
;
3829 if (!draw_roads_rails
) {
3830 /* Don't draw anything. */
3834 road_idx
= road_index(proad
);
3836 roadstyle
= t
->sprites
.roads
[road_idx
].roadstyle
;
3838 if (roadstyle
== RSTYLE_RIVER
) {
3842 if (road_has_flag(proad
, RF_CONNECT_LAND
)) {
3847 for (i
= 0; i
< 8; i
++) {
3848 land_near
[i
] = FALSE
;
3852 /* Fill some data arrays. rail_near and road_near store whether road/rail
3853 * is present in the given direction. draw_rail and draw_road store
3854 * whether road/rail is to be drawn in that direction. draw_single_road
3855 * and draw_single_rail store whether we need an isolated road/rail to be
3857 road
= BV_ISSET(troad
, road_idx
);
3860 road_type_list_iterate(proad
->hiders
, phider
) {
3861 if (BV_ISSET(troad
, road_index(phider
))) {
3865 } road_type_list_iterate_end
;
3867 if (road
&& (!pcity
|| !draw_cities
) && !hider
) {
3868 draw_single_road
= TRUE
;
3870 draw_single_road
= FALSE
;
3873 for (dir
= 0; dir
< 8; dir
++) {
3876 /* Check if there is adjacent road/rail. */
3877 if (!is_cardinal_only_road(proad
)
3878 || is_cardinal_tileset_dir(t
, dir
)) {
3879 road_near
[dir
] = BV_ISSET(troad_near
[dir
], road_idx
);
3881 land_near
[dir
] = (tterrain_near
[dir
] != T_UNKNOWN
3882 && terrain_type_terrain_class(tterrain_near
[dir
]) != TC_OCEAN
);
3885 road_near
[dir
] = FALSE
;
3886 land_near
[dir
] = FALSE
;
3889 /* Draw rail/road if there is a connection from this tile to the
3890 * adjacent tile. But don't draw road if there is also a rail
3892 roads_exist
= road
&& (road_near
[dir
] || land_near
[dir
]);
3893 draw_road
[dir
] = roads_exist
;
3894 hider_near
[dir
] = FALSE
;
3895 hland_near
[dir
] = tterrain_near
[dir
] != T_UNKNOWN
3896 && terrain_type_terrain_class(tterrain_near
[dir
]) != TC_OCEAN
;
3897 road_type_list_iterate(proad
->hiders
, phider
) {
3898 bool hider_dir
= FALSE
;
3899 bool land_dir
= FALSE
;
3901 if (!is_cardinal_only_road(phider
)
3902 || is_cardinal_tileset_dir(t
, dir
)) {
3903 if (BV_ISSET(troad_near
[dir
], road_index(phider
))) {
3904 hider_near
[dir
] = TRUE
;
3908 && road_has_flag(phider
, RF_CONNECT_LAND
)) {
3911 if (hider_dir
|| land_dir
) {
3912 if (BV_ISSET(troad
, road_index(phider
))) {
3913 draw_road
[dir
] = FALSE
;
3917 } road_type_list_iterate_end
;
3919 /* Don't draw an isolated road/rail if there's any connection.
3920 * draw_single_road would be true in the first place only if start tile has road,
3921 * so it will have road connection with any adjacent road tile. We check from real
3922 * existence of road (road_near[dir]) and not from whether road gets drawn (draw_road[dir])
3923 * as latter can be FALSE when road is simply hidden by another one, and we don't want to
3924 * draw single road in that case either. */
3925 if (draw_single_road
&& road_near
[dir
]) {
3926 draw_single_road
= FALSE
;
3930 /* Draw road corners */
3932 += fill_road_corner_sprites(t
, proad
, sprs
, road
, road_near
, hider
, hider_near
);
3934 if (roadstyle
== RSTYLE_ALL_SEPARATE
) {
3935 /* With RSTYLE_ALL_SEPARATE, we simply draw one road for every connection.
3936 * This means we only need a few sprites, but a lot of drawing is
3937 * necessary and it generally doesn't look very good. */
3940 /* First draw roads under rails. */
3942 for (i
= 0; i
< t
->num_valid_tileset_dirs
; i
++) {
3943 if (draw_road
[t
->valid_tileset_dirs
[i
]]) {
3944 ADD_SPRITE_SIMPLE(t
->sprites
.roads
[road_idx
].u
.dir
[i
]);
3948 } else if (roadstyle
== RSTYLE_PARITY_COMBINED
) {
3949 /* With RSTYLE_PARITY_COMBINED, we draw one sprite for cardinal road connections,
3950 * one sprite for diagonal road connections, and the same for rail.
3951 * This means we need about 4x more sprites than in style 0, but up to
3952 * 4x less drawing is needed. The drawing quality may also be
3955 /* First draw roads under rails. */
3957 int road_even_tileno
= 0, road_odd_tileno
= 0, i
;
3959 for (i
= 0; i
< t
->num_valid_tileset_dirs
/ 2; i
++) {
3960 enum direction8 even
= t
->valid_tileset_dirs
[2 * i
];
3961 enum direction8 odd
= t
->valid_tileset_dirs
[2 * i
+ 1];
3963 if (draw_road
[even
]) {
3964 road_even_tileno
|= 1 << i
;
3966 if (draw_road
[odd
]) {
3967 road_odd_tileno
|= 1 << i
;
3971 /* Draw the cardinal/even roads first. */
3972 if (road_even_tileno
!= 0) {
3973 ADD_SPRITE_SIMPLE(t
->sprites
.roads
[road_idx
].u
.combo
.even
[road_even_tileno
]);
3975 if (road_odd_tileno
!= 0) {
3976 ADD_SPRITE_SIMPLE(t
->sprites
.roads
[road_idx
].u
.combo
.odd
[road_odd_tileno
]);
3979 } else if (roadstyle
== RSTYLE_ALL_COMBINED
) {
3980 /* RSTYLE_ALL_COMBINED is a very simple method that lets us simply retrieve
3981 * entire finished tiles, with a bitwise index of the presence of
3982 * roads in each direction. */
3984 /* Draw roads first */
3986 int road_tileno
= 0, i
;
3988 for (i
= 0; i
< t
->num_valid_tileset_dirs
; i
++) {
3989 enum direction8 dir
= t
->valid_tileset_dirs
[i
];
3991 if (draw_road
[dir
]) {
3992 road_tileno
|= 1 << i
;
3996 if (road_tileno
!= 0 || draw_single_road
) {
3997 ADD_SPRITE_SIMPLE(t
->sprites
.roads
[road_idx
].u
.total
[road_tileno
]);
4004 /* Draw isolated rail/road separately (RSTYLE_ALL_SEPARATE and
4005 RSTYLE_PARITY_COMBINED only). */
4006 if (roadstyle
== RSTYLE_ALL_SEPARATE
|| roadstyle
== RSTYLE_PARITY_COMBINED
) {
4007 if (draw_single_road
) {
4008 ADD_SPRITE_SIMPLE(t
->sprites
.roads
[road_idx
].isolated
);
4012 return sprs
- saved_sprs
;
4015 /**************************************************************************
4016 Return the index of the sprite to be used for irrigation or farmland in
4019 We assume that the current tile has farmland or irrigation. We then
4020 choose a sprite (index) based upon which cardinally adjacent tiles have
4021 either farmland or irrigation (the two are considered interchangable for
4023 **************************************************************************/
4024 static int get_irrigation_index(const struct tileset
*t
,
4025 bv_special
*tspecial_near
)
4029 for (i
= 0; i
< t
->num_cardinal_tileset_dirs
; i
++) {
4030 enum direction8 dir
= t
->cardinal_tileset_dirs
[i
];
4032 /* A tile with S_FARMLAND will also have S_IRRIGATION set. */
4033 if (contains_special(tspecial_near
[dir
], S_IRRIGATION
)) {
4041 /**************************************************************************
4042 Fill in the farmland/irrigation sprite for the tile.
4043 **************************************************************************/
4044 static int fill_irrigation_sprite_array(const struct tileset
*t
,
4045 struct drawn_sprite
*sprs
,
4046 bv_special tspecial
,
4047 bv_special
*tspecial_near
,
4048 const struct city
*pcity
)
4050 struct drawn_sprite
*saved_sprs
= sprs
;
4052 /* Tiles with S_FARMLAND also have S_IRRIGATION set. */
4053 fc_assert_ret_val(!contains_special(tspecial
, S_FARMLAND
)
4054 || contains_special(tspecial
, S_IRRIGATION
), 0);
4056 /* We don't draw the irrigation if there's a city (it just gets overdrawn
4057 * anyway, and ends up looking bad). */
4059 && contains_special(tspecial
, S_IRRIGATION
)
4060 && !(pcity
&& draw_cities
)) {
4061 int index
= get_irrigation_index(t
, tspecial_near
);
4063 if (contains_special(tspecial
, S_FARMLAND
)) {
4064 ADD_SPRITE_SIMPLE(t
->sprites
.tx
.farmland
[index
]);
4066 ADD_SPRITE_SIMPLE(t
->sprites
.tx
.irrigation
[index
]);
4070 return sprs
- saved_sprs
;
4073 /**************************************************************************
4074 Fill in the city overlays for the tile. This includes the citymap
4075 overlays on the mapview as well as the tile output sprites.
4076 **************************************************************************/
4077 static int fill_city_overlays_sprite_array(const struct tileset
*t
,
4078 struct drawn_sprite
*sprs
,
4079 const struct tile
*ptile
,
4080 const struct city
*citymode
)
4082 const struct city
*pcity
;
4083 const struct city
*pwork
;
4084 struct unit
*psettler
;
4085 struct drawn_sprite
*saved_sprs
= sprs
;
4087 const int NUM_CITY_COLORS
= t
->sprites
.city
.worked_tile_overlay
.size
;
4089 if (NULL
== ptile
|| TILE_UNKNOWN
== client_tile_get_known(ptile
)) {
4092 pwork
= tile_worked(ptile
);
4097 pcity
= find_city_or_settler_near_tile(ptile
, &psettler
);
4100 /* Below code does not work if pcity is invisible.
4101 * Make sure it is not. */
4102 fc_assert_ret_val(pcity
== NULL
|| pcity
->tile
!= NULL
, 0);
4103 if (pcity
&& !pcity
->tile
) {
4107 if (pcity
&& city_base_to_city_map(&city_x
, &city_y
, pcity
, ptile
)) {
4108 /* FIXME: check elsewhere for valid tile (instead of above) */
4110 if (!citymode
&& pcity
->client
.colored
) {
4111 /* Add citymap overlay for a city. */
4112 int index
= pcity
->client
.color_index
% NUM_CITY_COLORS
;
4114 if (NULL
!= pwork
&& pwork
== pcity
) {
4115 ADD_SPRITE_SIMPLE(t
->sprites
.city
.worked_tile_overlay
.p
[index
]);
4116 } else if (city_can_work_tile(pcity
, ptile
)) {
4117 ADD_SPRITE_SIMPLE(t
->sprites
.city
.unworked_tile_overlay
.p
[index
]);
4119 } else if (NULL
!= pwork
&& pwork
== pcity
4120 && (citymode
|| draw_city_output
)) {
4121 /* Add on the tile output sprites. */
4122 int food
= city_tile_output_now(pcity
, ptile
, O_FOOD
);
4123 int shields
= city_tile_output_now(pcity
, ptile
, O_SHIELD
);
4124 int trade
= city_tile_output_now(pcity
, ptile
, O_TRADE
);
4125 const int ox
= t
->type
== TS_ISOMETRIC
? t
->normal_tile_width
/ 3 : 0;
4126 const int oy
= t
->type
== TS_ISOMETRIC
? -t
->normal_tile_height
/ 3 : 0;
4128 food
= CLIP(0, food
, NUM_TILES_DIGITS
- 1);
4129 shields
= CLIP(0, shields
, NUM_TILES_DIGITS
- 1);
4130 trade
= CLIP(0, trade
, NUM_TILES_DIGITS
- 1);
4132 ADD_SPRITE(t
->sprites
.city
.tile_foodnum
[food
], TRUE
, ox
, oy
);
4133 ADD_SPRITE(t
->sprites
.city
.tile_shieldnum
[shields
], TRUE
, ox
, oy
);
4134 ADD_SPRITE(t
->sprites
.city
.tile_tradenum
[trade
], TRUE
, ox
, oy
);
4136 } else if (psettler
&& psettler
->client
.colored
) {
4137 /* Add citymap overlay for a unit. */
4138 int index
= psettler
->client
.color_index
% NUM_CITY_COLORS
;
4140 ADD_SPRITE_SIMPLE(t
->sprites
.city
.unworked_tile_overlay
.p
[index
]);
4143 return sprs
- saved_sprs
;
4146 /****************************************************************************
4147 Helper function for fill_terrain_sprite_layer.
4148 Fill in the sprite array for blended terrain.
4149 ****************************************************************************/
4150 static int fill_terrain_sprite_blending(const struct tileset
*t
,
4151 struct drawn_sprite
*sprs
,
4152 const struct tile
*ptile
,
4153 const struct terrain
*pterrain
,
4154 struct terrain
**tterrain_near
)
4156 struct drawn_sprite
*saved_sprs
= sprs
;
4157 const int W
= t
->normal_tile_width
, H
= t
->normal_tile_height
;
4158 const int offsets
[4][2] = {
4159 {W
/2, 0}, {0, H
/ 2}, {W
/ 2, H
/ 2}, {0, 0}
4161 enum direction4 dir
= 0;
4164 * We want to mark unknown tiles so that an unreal tile will be
4165 * given the same marking as our current tile - that way we won't
4166 * get the "unknown" dither along the edge of the map.
4168 for (; dir
< 4; dir
++) {
4169 struct tile
*tile1
= mapstep(ptile
, DIR4_TO_DIR8
[dir
]);
4170 struct terrain
*other
;
4173 || client_tile_get_known(tile1
) == TILE_UNKNOWN
4174 || pterrain
== (other
= tterrain_near
[DIR4_TO_DIR8
[dir
]])
4175 || (0 == t
->sprites
.drawing
[terrain_index(other
)]->blending
4176 && NULL
== t
->sprites
.drawing
[terrain_index(other
)]->blender
)) {
4180 ADD_SPRITE(t
->sprites
.drawing
[terrain_index(other
)]->blend
[dir
], TRUE
,
4181 offsets
[dir
][0], offsets
[dir
][1]);
4184 return sprs
- saved_sprs
;
4187 /****************************************************************************
4188 Add sprites for fog (and some forms of darkness).
4189 ****************************************************************************/
4190 static int fill_fog_sprite_array(const struct tileset
*t
,
4191 struct drawn_sprite
*sprs
,
4192 const struct tile
*ptile
,
4193 const struct tile_edge
*pedge
,
4194 const struct tile_corner
*pcorner
)
4196 struct drawn_sprite
*saved_sprs
= sprs
;
4198 if (t
->fogstyle
== FOG_SPRITE
&& draw_fog_of_war
4200 && TILE_KNOWN_UNSEEN
== client_tile_get_known(ptile
)) {
4201 /* With FOG_AUTO, fog is done this way. */
4202 ADD_SPRITE_SIMPLE(t
->sprites
.tx
.fog
);
4205 if (t
->darkness_style
== DARKNESS_CORNER
&& pcorner
&& draw_fog_of_war
) {
4208 for (i
= 3; i
>= 0; i
--) {
4209 const int unknown
= 0, fogged
= 1, known
= 2;
4212 if (!pcorner
->tile
[i
]) {
4215 switch (client_tile_get_known(pcorner
->tile
[i
])) {
4216 case TILE_KNOWN_SEEN
:
4219 case TILE_KNOWN_UNSEEN
:
4227 fc_assert(value
>= 0 && value
< 3);
4229 tileno
= tileno
* 3 + value
;
4232 if (t
->sprites
.tx
.fullfog
[tileno
]) {
4233 ADD_SPRITE_SIMPLE(t
->sprites
.tx
.fullfog
[tileno
]);
4237 return sprs
- saved_sprs
;
4240 /****************************************************************************
4241 Helper function for fill_terrain_sprite_layer.
4242 ****************************************************************************/
4243 static int fill_terrain_sprite_array(struct tileset
*t
,
4244 struct drawn_sprite
*sprs
,
4245 int l
, /* layer_num */
4246 const struct tile
*ptile
,
4247 const struct terrain
*pterrain
,
4248 struct terrain
**tterrain_near
,
4249 struct drawing_data
*draw
)
4251 struct drawn_sprite
*saved_sprs
= sprs
;
4252 struct drawing_layer
*dlp
= &draw
->layer
[l
];
4253 int this = dlp
->match_index
[0];
4254 int that
= dlp
->match_index
[1];
4255 int ox
= dlp
->offset_x
;
4256 int oy
= dlp
->offset_y
;
4259 #define MATCH(dir) \
4260 (t->sprites.drawing[terrain_index(tterrain_near[(dir)])]->num_layers > l \
4261 ? t->sprites.drawing[terrain_index(tterrain_near[(dir)])]->layer[l].match_index[0] \
4264 switch (dlp
->sprite_type
) {
4267 switch (dlp
->match_style
) {
4270 int count
= sprite_vector_size(&dlp
->base
);
4273 /* Pseudo-random reproducable algorithm to pick a sprite. Use modulo
4274 * to limit the number to a handleable size [0..32000). */
4275 count
= fc_randomly(tile_index(ptile
) % 32000, count
);
4278 ox
+= FULL_TILE_X_OFFSET
;
4279 oy
+= FULL_TILE_Y_OFFSET
;
4281 ADD_SPRITE(dlp
->base
.p
[count
], TRUE
, ox
, oy
);
4289 for (i
= 0; i
< t
->num_cardinal_tileset_dirs
; i
++) {
4290 enum direction8 dir
= t
->cardinal_tileset_dirs
[i
];
4292 if (MATCH(dir
) == this) {
4298 ox
+= FULL_TILE_X_OFFSET
;
4299 oy
+= FULL_TILE_Y_OFFSET
;
4301 ADD_SPRITE(dlp
->match
[tileno
], TRUE
, ox
, oy
);
4306 fc_assert(FALSE
); /* not yet defined */
4313 /* Divide the tile up into four rectangular cells. Each of these
4314 * cells covers one corner, and each is adjacent to 3 different
4315 * tiles. For each cell we pick a sprite based upon the adjacent
4316 * terrains at each of those tiles. Thus, we have 8 different sprites
4317 * for each of the 4 cells (32 sprites total).
4319 * These arrays correspond to the direction4 ordering. */
4320 const int W
= t
->normal_tile_width
;
4321 const int H
= t
->normal_tile_height
;
4322 const int iso_offsets
[4][2] = {
4323 {W
/ 4, 0}, {W
/ 4, H
/ 2}, {W
/ 2, H
/ 4}, {0, H
/ 4}
4325 const int noniso_offsets
[4][2] = {
4326 {0, 0}, {W
/ 2, H
/ 2}, {W
/ 2, 0}, {0, H
/ 2}
4329 /* put corner cells */
4330 for (i
= 0; i
< NUM_CORNER_DIRS
; i
++) {
4331 const int count
= dlp
->match_indices
;
4332 int array_index
= 0;
4333 enum direction8 dir
= dir_ccw(DIR4_TO_DIR8
[i
]);
4334 int x
= (t
->type
== TS_ISOMETRIC
? iso_offsets
[i
][0] : noniso_offsets
[i
][0]);
4335 int y
= (t
->type
== TS_ISOMETRIC
? iso_offsets
[i
][1] : noniso_offsets
[i
][1]);
4336 int m
[3] = {MATCH(dir_ccw(dir
)), MATCH(dir
), MATCH(dir_cw(dir
))};
4339 /* synthesize 4 dimensional array? */
4340 switch (dlp
->match_style
) {
4342 /* We have no need for matching, just plug the piece in place. */
4345 array_index
= array_index
* 2 + (m
[2] != this);
4346 array_index
= array_index
* 2 + (m
[1] != this);
4347 array_index
= array_index
* 2 + (m
[0] != this);
4350 array_index
= array_index
* 2 + (m
[2] == that
);
4351 array_index
= array_index
* 2 + (m
[1] == that
);
4352 array_index
= array_index
* 2 + (m
[0] == that
);
4359 for (; j
< 3; j
++) {
4361 for (; k
< count
; k
++) {
4362 n
[j
] = k
; /* default to last entry */
4363 if (m
[j
] == dlp
->match_index
[k
])
4369 array_index
= array_index
* count
+ n
[2];
4370 array_index
= array_index
* count
+ n
[1];
4371 array_index
= array_index
* count
+ n
[0];
4375 array_index
= array_index
* NUM_CORNER_DIRS
+ i
;
4377 s
= dlp
->cells
[array_index
];
4379 ADD_SPRITE(s
, TRUE
, x
, y
);
4387 return sprs
- saved_sprs
;
4390 /****************************************************************************
4391 Helper function for fill_terrain_sprite_layer.
4392 Fill in the sprite array of darkness.
4393 ****************************************************************************/
4394 static int fill_terrain_sprite_darkness(struct tileset
*t
,
4395 struct drawn_sprite
*sprs
,
4396 const struct tile
*ptile
,
4397 struct terrain
**tterrain_near
)
4399 struct drawn_sprite
*saved_sprs
= sprs
;
4401 struct tile
*adjc_tile
;
4403 #define UNKNOWN(dir) \
4404 ((adjc_tile = mapstep(ptile, (dir))) \
4405 && client_tile_get_known(adjc_tile) == TILE_UNKNOWN)
4407 switch (t
->darkness_style
) {
4410 case DARKNESS_ISORECT
:
4411 for (i
= 0; i
< 4; i
++) {
4412 const int W
= t
->normal_tile_width
, H
= t
->normal_tile_height
;
4413 int offsets
[4][2] = {{W
/ 2, 0}, {0, H
/ 2}, {W
/ 2, H
/ 2}, {0, 0}};
4415 if (UNKNOWN(DIR4_TO_DIR8
[i
])) {
4416 ADD_SPRITE(t
->sprites
.tx
.darkness
[i
], TRUE
,
4417 offsets
[i
][0], offsets
[i
][1]);
4421 case DARKNESS_CARD_SINGLE
:
4422 for (i
= 0; i
< t
->num_cardinal_tileset_dirs
; i
++) {
4423 if (UNKNOWN(t
->cardinal_tileset_dirs
[i
])) {
4424 ADD_SPRITE_SIMPLE(t
->sprites
.tx
.darkness
[i
]);
4428 case DARKNESS_CARD_FULL
:
4429 /* We're looking to find the INDEX_NSEW for the directions that
4430 * are unknown. We want to mark unknown tiles so that an unreal
4431 * tile will be given the same marking as our current tile - that
4432 * way we won't get the "unknown" dither along the edge of the
4435 for (i
= 0; i
< t
->num_cardinal_tileset_dirs
; i
++) {
4436 if (UNKNOWN(t
->cardinal_tileset_dirs
[i
])) {
4442 ADD_SPRITE_SIMPLE(t
->sprites
.tx
.darkness
[tileno
]);
4445 case DARKNESS_CORNER
:
4446 /* Handled separately. */
4451 return sprs
- saved_sprs
;
4454 /****************************************************************************
4455 Add sprites for the base tile to the sprite list. This doesn't
4456 include specials or rivers.
4457 ****************************************************************************/
4458 static int fill_terrain_sprite_layer(struct tileset
*t
,
4459 struct drawn_sprite
*sprs
,
4461 const struct tile
*ptile
,
4462 const struct terrain
*pterrain
,
4463 struct terrain
**tterrain_near
)
4465 struct sprite
*sprite
;
4466 struct drawn_sprite
*saved_sprs
= sprs
;
4467 struct drawing_data
*draw
= t
->sprites
.drawing
[terrain_index(pterrain
)];
4468 const int l
= (draw
->is_reversed
4469 ? (draw
->num_layers
- layer_num
- 1) : layer_num
);
4471 fc_assert(layer_num
< TERRAIN_LAYER_COUNT
);
4473 /* Skip the normal drawing process. */
4474 /* FIXME: this should avoid calling load_sprite since it's slow and
4475 * increases the refcount without limit. */
4476 if (ptile
->spec_sprite
&& (sprite
= load_sprite(t
, ptile
->spec_sprite
))) {
4478 ADD_SPRITE_SIMPLE(sprite
);
4485 if (l
< draw
->num_layers
) {
4486 sprs
+= fill_terrain_sprite_array(t
, sprs
, l
, ptile
, pterrain
, tterrain_near
, draw
);
4488 if ((l
+ 1) == draw
->blending
) {
4489 sprs
+= fill_terrain_sprite_blending(t
, sprs
, ptile
, pterrain
, tterrain_near
);
4493 /* Add darkness on top of the designed terrain layer. Note that darkness is always
4494 * drawn, even in citymode, etc. */
4495 if (layer_num
== t
->darkness_layer
) {
4496 sprs
+= fill_terrain_sprite_darkness(t
, sprs
, ptile
, tterrain_near
);
4499 return sprs
- saved_sprs
;
4502 /****************************************************************************
4503 Indicate whether a unit is to be drawn with a surrounding city outline
4504 under current conditions.
4505 (This includes being in focus, but if the caller has already checked that,
4506 they can bypass this slightly expensive check with check_focus == FALSE.)
4507 ****************************************************************************/
4508 bool unit_drawn_with_city_outline(const struct unit
*punit
, bool check_focus
)
4510 /* Display an outline for city-builder type units if they are selected,
4511 * and on a tile where a city can be built.
4512 * But suppress the outline if the unit has orders (likely it is in
4513 * transit to somewhere else and this will just slow down redraws). */
4514 return draw_city_outlines
4515 && unit_has_type_flag(punit
, UTYF_CITIES
)
4516 && !unit_has_orders(punit
)
4517 && (client_tile_get_known(unit_tile(punit
)) != TILE_UNKNOWN
4518 && city_can_be_built_here(unit_tile(punit
), punit
))
4519 && (!check_focus
|| unit_is_in_focus(punit
));
4522 /****************************************************************************
4523 Fill in the grid sprites for the given tile, city, and unit.
4524 ****************************************************************************/
4525 static int fill_grid_sprite_array(const struct tileset
*t
,
4526 struct drawn_sprite
*sprs
,
4527 const struct tile
*ptile
,
4528 const struct tile_edge
*pedge
,
4529 const struct tile_corner
*pcorner
,
4530 const struct unit
*punit
,
4531 const struct city
*pcity
,
4532 const struct city
*citymode
)
4534 struct drawn_sprite
*saved_sprs
= sprs
;
4537 bool known
[NUM_EDGE_TILES
], city
[NUM_EDGE_TILES
];
4538 bool unit
[NUM_EDGE_TILES
], worked
[NUM_EDGE_TILES
];
4540 struct unit_list
*pfocus_units
= get_units_in_focus();
4542 for (i
= 0; i
< NUM_EDGE_TILES
; i
++) {
4543 int dummy_x
, dummy_y
;
4544 const struct tile
*tile
= pedge
->tile
[i
];
4545 struct player
*powner
= tile
? tile_owner(tile
) : NULL
;
4547 known
[i
] = tile
&& client_tile_get_known(tile
) != TILE_UNKNOWN
;
4549 if (tile
&& !citymode
) {
4550 unit_list_iterate(pfocus_units
, pfocus_unit
) {
4551 if (unit_drawn_with_city_outline(pfocus_unit
, FALSE
)
4552 && city_tile_to_city_map(&dummy_x
, &dummy_y
,
4553 game
.info
.init_city_radius_sq
,
4554 unit_tile(pfocus_unit
), tile
)) {
4558 } unit_list_iterate_end
;
4563 && (NULL
== powner
|| NULL
== client
.conn
.playing
4564 || powner
== client
.conn
.playing
)
4565 && (NULL
== client
.conn
.playing
4566 || player_in_city_map(client
.conn
.playing
, tile
)));
4569 /* In citymode, we only draw worked tiles for this city - other
4570 * tiles may be marked as unavailable. */
4571 worked
[i
] = (tile_worked(tile
) == citymode
);
4573 worked
[i
] = (NULL
!= tile_worked(tile
));
4578 if (mapdeco_is_highlight_set(pedge
->tile
[0])
4579 || mapdeco_is_highlight_set(pedge
->tile
[1])) {
4580 ADD_SPRITE_SIMPLE(t
->sprites
.grid
.selected
[pedge
->type
]);
4581 } else if (!draw_terrain
&& draw_coastline
4582 && pedge
->tile
[0] && pedge
->tile
[1]
4583 && known
[0] && known
[1]
4584 && (is_ocean_tile(pedge
->tile
[0])
4585 ^ is_ocean_tile(pedge
->tile
[1]))) {
4586 ADD_SPRITE_SIMPLE(t
->sprites
.grid
.coastline
[pedge
->type
]);
4587 } else if (draw_map_grid
) {
4588 if (worked
[0] || worked
[1]) {
4589 ADD_SPRITE_SIMPLE(t
->sprites
.grid
.worked
[pedge
->type
]);
4590 } else if (city
[0] || city
[1]) {
4591 ADD_SPRITE_SIMPLE(t
->sprites
.grid
.city
[pedge
->type
]);
4592 } else if (known
[0] || known
[1]) {
4593 ADD_SPRITE_SIMPLE(t
->sprites
.grid
.main
[pedge
->type
]);
4595 } else if (draw_city_outlines
) {
4596 if (XOR(city
[0], city
[1])) {
4597 ADD_SPRITE_SIMPLE(t
->sprites
.grid
.city
[pedge
->type
]);
4599 if (XOR(unit
[0], unit
[1])) {
4600 ADD_SPRITE_SIMPLE(t
->sprites
.grid
.worked
[pedge
->type
]);
4605 && BORDERS_DISABLED
!= game
.info
.borders
4608 struct player
*owner0
= tile_owner(pedge
->tile
[0]);
4609 struct player
*owner1
= tile_owner(pedge
->tile
[1]);
4611 if (owner0
!= owner1
) {
4613 int plrid
= player_index(owner0
);
4614 ADD_SPRITE_SIMPLE(t
->sprites
.player
[plrid
].grid_borders
4618 int plrid
= player_index(owner1
);
4619 ADD_SPRITE_SIMPLE(t
->sprites
.player
[plrid
].grid_borders
4624 } else if (NULL
!= ptile
&& TILE_UNKNOWN
!= client_tile_get_known(ptile
)) {
4628 /* test to ensure valid coordinates? */
4629 && city_base_to_city_map(&cx
, &cy
, citymode
, ptile
)
4630 && !client_city_can_work_tile(citymode
, ptile
)) {
4631 ADD_SPRITE_SIMPLE(t
->sprites
.grid
.unavailable
);
4634 if (draw_native
&& citymode
== NULL
) {
4636 struct unit_list
*pfocus_units
= get_units_in_focus();
4638 unit_list_iterate(pfocus_units
, punit
) {
4639 if (!is_native_tile(unit_type(punit
), ptile
)) {
4643 } unit_list_iterate_end
;
4646 if (t
->sprites
.grid
.nonnative
!= NULL
) {
4647 ADD_SPRITE_SIMPLE(t
->sprites
.grid
.nonnative
);
4649 ADD_SPRITE_SIMPLE(t
->sprites
.grid
.unavailable
);
4655 return sprs
- saved_sprs
;
4658 /****************************************************************************
4659 Fill in the given sprite array with any needed goto sprites.
4660 ****************************************************************************/
4661 static int fill_goto_sprite_array(const struct tileset
*t
,
4662 struct drawn_sprite
*sprs
,
4663 const struct tile
*ptile
,
4664 const struct tile_edge
*pedge
,
4665 const struct tile_corner
*pcorner
)
4667 struct drawn_sprite
*saved_sprs
= sprs
;
4669 if (is_valid_goto_destination(ptile
)) {
4673 goto_get_turns(NULL
, &length
);
4676 ADD_SPRITE_SIMPLE(t
->sprites
.path
.turns
[0]);
4679 ADD_SPRITE_SIMPLE(t
->sprites
.path
.turns
[length
% 10]);
4681 ADD_SPRITE_SIMPLE(t
->sprites
.path
.turns_tens
[(length
/ 10) % 10]);
4682 if (100 <= length
) {
4683 struct sprite
*sprite
=
4684 t
->sprites
.path
.turns_hundreds
[(length
/ 100) % 10];
4686 if (NULL
!= sprite
) {
4687 ADD_SPRITE_SIMPLE(sprite
);
4691 if (1000 <= length
) {
4699 /* Warn only once by tileset. */
4700 static char last_reported
[256] = "";
4702 if (0 != strcmp(last_reported
, t
->name
)) {
4703 log_normal(_("Tileset \"%s\" doesn't support long goto paths, "
4704 "such as %d. Path not displayed as expected."),
4706 sz_strlcpy(last_reported
, t
->name
);
4711 return sprs
- saved_sprs
;
4714 /****************************************************************************
4715 Fill in the sprite array for the given tile, city, and unit.
4717 ptile, if specified, gives the tile. If specified the terrain and specials
4718 will be drawn for this tile. In this case (map_x,map_y) should give the
4719 location of the tile.
4721 punit, if specified, gives the unit. For tile drawing this should
4722 generally be get_drawable_unit(); otherwise it can be any unit.
4724 pcity, if specified, gives the city. For tile drawing this should
4725 generally be tile_city(ptile); otherwise it can be any city.
4727 citymode specifies whether this is part of a citydlg. If so some drawing
4728 is done differently.
4729 ****************************************************************************/
4730 int fill_sprite_array(struct tileset
*t
,
4731 struct drawn_sprite
*sprs
, enum mapview_layer layer
,
4732 const struct tile
*ptile
,
4733 const struct tile_edge
*pedge
,
4734 const struct tile_corner
*pcorner
,
4735 const struct unit
*punit
, const struct city
*pcity
,
4736 const struct city
*citymode
,
4737 const struct unit_type
*putype
)
4740 bv_special tspecial_near
[8];
4741 bv_special tspecial
;
4743 bv_roads troad_near
[8];
4744 struct terrain
*tterrain_near
[8];
4745 struct terrain
*pterrain
= NULL
;
4746 struct drawn_sprite
*save_sprs
= sprs
;
4747 struct player
*owner
= NULL
;
4748 /* Unit drawing is disabled when the view options are turned off,
4749 * but only where we're drawing on the mapview. */
4750 bool do_draw_unit
= (punit
&& (draw_units
|| !ptile
4752 && unit_is_in_focus(punit
))));
4753 bool solid_bg
= (solid_color_behind_units
4755 || (pcity
&& draw_cities
)
4756 || (ptile
&& !draw_terrain
)));
4759 int count
= 0, i
, cx
, cy
;
4760 const struct tile
*const *tiles
= NULL
;
4766 } else if (pcorner
) {
4767 tiles
= pcorner
->tile
;
4768 count
= NUM_CORNER_TILES
;
4770 tiles
= pedge
->tile
;
4771 count
= NUM_EDGE_TILES
;
4774 for (i
= 0; i
< count
; i
++) {
4775 if (tiles
[i
] && city_base_to_city_map(&cx
, &cy
, citymode
, tiles
[i
])) {
4785 if (ptile
&& client_tile_get_known(ptile
) != TILE_UNKNOWN
) {
4786 tspecial
= tile_specials(ptile
);
4787 troad
= tile_roads(ptile
);
4788 pterrain
= tile_terrain(ptile
);
4790 if (NULL
!= pterrain
) {
4791 build_tile_data(ptile
, pterrain
, tterrain_near
, tspecial_near
,
4794 log_error("fill_sprite_array() tile (%d,%d) has no terrain!",
4798 BV_CLR_ALL(tspecial
);
4803 case LAYER_BACKGROUND
:
4804 /* Set up background color. */
4805 if (solid_color_behind_units
) {
4807 owner
= unit_owner(punit
);
4808 } else if (pcity
&& draw_cities
) {
4809 owner
= city_owner(pcity
);
4813 ADD_SPRITE_SIMPLE(t
->sprites
.player
[player_index(owner
)].background
);
4814 } else if (ptile
&& !draw_terrain
) {
4815 ADD_SPRITE_SIMPLE(t
->sprites
.background
.graphic
);
4819 case LAYER_TERRAIN1
:
4820 if (NULL
!= pterrain
&& draw_terrain
&& !solid_bg
) {
4821 sprs
+= fill_terrain_sprite_layer(t
, sprs
, 0, ptile
, pterrain
, tterrain_near
);
4825 case LAYER_TERRAIN2
:
4826 if (NULL
!= pterrain
&& draw_terrain
&& !solid_bg
) {
4827 sprs
+= fill_terrain_sprite_layer(t
, sprs
, 1, ptile
, pterrain
, tterrain_near
);
4831 case LAYER_TERRAIN3
:
4832 if (NULL
!= pterrain
&& draw_terrain
&& !solid_bg
) {
4833 fc_assert(MAX_NUM_LAYERS
== 3);
4834 sprs
+= fill_terrain_sprite_layer(t
, sprs
, 2, ptile
, pterrain
, tterrain_near
);
4839 if (NULL
!= pterrain
) {
4840 if (draw_terrain
&& !solid_bg
4841 && terrain_type_terrain_class(pterrain
) == TC_OCEAN
) {
4842 for (dir
= 0; dir
< 4; dir
++) {
4843 int didx
= DIR4_TO_DIR8
[dir
];
4845 road_type_list_iterate(t
->rivers
, priver
) {
4846 int idx
= road_index(priver
);
4848 if (BV_ISSET(troad_near
[didx
], idx
)) {
4849 ADD_SPRITE_SIMPLE(t
->sprites
.roads
[idx
].u
.rivers
.outlet
[dir
]);
4852 } road_type_list_iterate_end
;
4856 sprs
+= fill_irrigation_sprite_array(t
, sprs
, tspecial
, tspecial_near
,
4859 if (draw_terrain
&& !solid_bg
) {
4860 road_type_list_iterate(t
->rivers
, priver
) {
4861 int idx
= road_index(priver
);
4863 if (BV_ISSET(troad
, idx
)) {
4866 /* Draw rivers on top of irrigation. */
4868 for (i
= 0; i
< t
->num_cardinal_tileset_dirs
; i
++) {
4869 enum direction8 dir
= t
->cardinal_tileset_dirs
[i
];
4871 if (terrain_type_terrain_class(tterrain_near
[dir
]) == TC_OCEAN
4872 || BV_ISSET(troad_near
[dir
], idx
)) {
4877 ADD_SPRITE_SIMPLE(t
->sprites
.roads
[idx
].u
.rivers
.spec
[tileno
]);
4879 } road_type_list_iterate_end
;
4885 if (NULL
!= pterrain
) {
4886 road_type_iterate(proad
) {
4887 sprs
+= fill_road_sprite_array(t
, proad
, sprs
,
4889 tterrain_near
, pcity
);
4890 } road_type_iterate_end
;
4894 case LAYER_SPECIAL1
:
4895 if (NULL
!= pterrain
) {
4896 if (draw_specials
) {
4897 if (tile_resource_is_valid(ptile
)) {
4898 ADD_SPRITE_SIMPLE(t
->sprites
.resource
[resource_index(tile_resource(ptile
))]);
4902 if (ptile
&& draw_fortress_airbase
) {
4903 base_type_iterate(pbase
) {
4904 if (tile_has_base(ptile
, pbase
)
4905 && t
->sprites
.bases
[base_index(pbase
)].background
) {
4906 ADD_SPRITE_FULL(t
->sprites
.bases
[base_index(pbase
)].background
);
4908 } base_type_iterate_end
;
4911 if (draw_mines
&& contains_special(tspecial
, S_MINE
)) {
4912 struct drawing_data
*draw
= t
->sprites
.drawing
[terrain_index(pterrain
)];
4914 if (NULL
!= draw
->mine
) {
4915 ADD_SPRITE_SIMPLE(draw
->mine
);
4919 if (draw_specials
&& contains_special(tspecial
, S_HUT
)) {
4920 ADD_SPRITE_SIMPLE(t
->sprites
.tx
.village
);
4926 if (t
->type
== TS_ISOMETRIC
) {
4927 sprs
+= fill_grid_sprite_array(t
, sprs
, ptile
, pedge
, pcorner
,
4928 punit
, pcity
, citymode
);
4933 /* City. Some city sprites are drawn later. */
4934 if (pcity
&& draw_cities
) {
4935 if (!draw_full_citybar
&& !solid_color_behind_units
) {
4936 ADD_SPRITE(get_city_flag_sprite(t
, pcity
), TRUE
,
4937 FULL_TILE_X_OFFSET
+ t
->city_flag_offset_x
,
4938 FULL_TILE_Y_OFFSET
+ t
->city_flag_offset_y
);
4940 /* For iso-view the city.wall graphics include the full city, whereas
4941 * for non-iso view they are an overlay on top of the base city
4943 if (t
->type
== TS_OVERVIEW
|| !pcity
->client
.walls
) {
4944 ADD_SPRITE_FULL(get_city_sprite(t
->sprites
.city
.tile
, pcity
));
4946 if (t
->type
== TS_ISOMETRIC
&& pcity
->client
.walls
) {
4947 ADD_SPRITE_FULL(get_city_sprite(t
->sprites
.city
.wall
, pcity
));
4949 if (!draw_full_citybar
&& pcity
->client
.occupied
) {
4950 ADD_SPRITE_FULL(get_city_sprite(t
->sprites
.city
.occupied
, pcity
));
4952 if (t
->type
== TS_OVERVIEW
&& pcity
->client
.walls
) {
4953 ADD_SPRITE_FULL(get_city_sprite(t
->sprites
.city
.wall
, pcity
));
4955 if (pcity
->client
.unhappy
) {
4956 ADD_SPRITE_FULL(t
->sprites
.city
.disorder
);
4961 case LAYER_SPECIAL2
:
4962 if (NULL
!= pterrain
) {
4963 if (ptile
&& draw_fortress_airbase
) {
4964 base_type_iterate(pbase
) {
4965 if (tile_has_base(ptile
, pbase
)
4966 && t
->sprites
.bases
[base_index(pbase
)].middleground
) {
4967 ADD_SPRITE_FULL(t
->sprites
.bases
[base_index(pbase
)].middleground
);
4969 } base_type_iterate_end
;
4972 if (draw_pollution
&& contains_special(tspecial
, S_POLLUTION
)) {
4973 ADD_SPRITE_SIMPLE(t
->sprites
.tx
.pollution
);
4975 if (draw_pollution
&& contains_special(tspecial
, S_FALLOUT
)) {
4976 ADD_SPRITE_SIMPLE(t
->sprites
.tx
.fallout
);
4982 case LAYER_FOCUS_UNIT
:
4983 if (do_draw_unit
&& XOR(layer
== LAYER_UNIT
, unit_is_in_focus(punit
))) {
4984 bool stacked
= ptile
&& (unit_list_size(ptile
->units
) > 1);
4985 bool backdrop
= !pcity
;
4987 if (ptile
&& unit_is_in_focus(punit
)
4988 && t
->sprites
.unit
.select
[0]) {
4989 /* Special case for drawing the selection rectangle. The blinking
4990 * unit is handled separately, inside get_drawable_unit(). */
4991 ADD_SPRITE_SIMPLE(t
->sprites
.unit
.select
[focus_unit_state
]);
4994 sprs
+= fill_unit_sprite_array(t
, sprs
, punit
, stacked
, backdrop
);
4995 } else if (putype
!= NULL
) {
4996 /* Only the sprite for the unit type. */
4997 sprs
+= fill_unit_type_sprite_array(t
, sprs
, putype
,
4998 direction8_invalid());
5002 case LAYER_SPECIAL3
:
5003 if (NULL
!= pterrain
) {
5004 if (ptile
&& draw_fortress_airbase
) {
5005 bool show_flag
= FALSE
;
5006 struct player
*owner
= base_owner(ptile
);
5008 base_type_iterate(pbase
) {
5009 if (tile_has_base(ptile
, pbase
)) {
5010 if (t
->sprites
.bases
[base_index(pbase
)].foreground
) {
5011 /* Draw fortress front in iso-view (non-iso view only has a fortress
5013 ADD_SPRITE_FULL(t
->sprites
.bases
[base_index(pbase
)].foreground
);
5015 if (base_has_flag(pbase
, BF_SHOW_FLAG
)) {
5019 } base_type_iterate_end
;
5021 if (show_flag
&& owner
!= NULL
) {
5022 ADD_SPRITE(get_nation_flag_sprite(t
, nation_of_player(owner
)), TRUE
,
5023 FULL_TILE_X_OFFSET
+ t
->city_flag_offset_x
,
5024 FULL_TILE_Y_OFFSET
+ t
->city_flag_offset_y
);
5031 sprs
+= fill_fog_sprite_array(t
, sprs
, ptile
, pedge
, pcorner
);
5035 /* City size. Drawing this under fog makes it hard to read. */
5036 if (pcity
&& draw_cities
&& !draw_full_citybar
) {
5039 ADD_SPRITE(t
->sprites
.city
.size
[city_size_get(pcity
) % 10],
5040 FALSE
, FULL_TILE_X_OFFSET
, FULL_TILE_Y_OFFSET
);
5041 if (10 <= city_size_get(pcity
)) {
5042 ADD_SPRITE(t
->sprites
.city
.size_tens
[(city_size_get(pcity
) / 10)
5043 % 10], FALSE
, FULL_TILE_X_OFFSET
, FULL_TILE_Y_OFFSET
);
5044 if (100 <= city_size_get(pcity
)) {
5045 struct sprite
*sprite
=
5046 t
->sprites
.city
.size_hundreds
[(city_size_get(pcity
) / 100) % 10];
5048 if (NULL
!= sprite
) {
5049 ADD_SPRITE(sprite
, FALSE
,
5050 FULL_TILE_X_OFFSET
, FULL_TILE_Y_OFFSET
);
5054 if (1000 <= city_size_get(pcity
)) {
5061 /* Warn only once by tileset. */
5062 static char last_reported
[256] = "";
5064 if (0 != strcmp(last_reported
, t
->name
)) {
5065 log_normal(_("Tileset \"%s\" doesn't support big cities size, "
5066 "such as %d. Size not displayed as expected."),
5067 t
->name
, city_size_get(pcity
));
5068 sz_strlcpy(last_reported
, t
->name
);
5075 if (t
->type
== TS_OVERVIEW
) {
5076 sprs
+= fill_grid_sprite_array(t
, sprs
, ptile
, pedge
, pcorner
,
5077 punit
, pcity
, citymode
);
5081 case LAYER_OVERLAYS
:
5082 sprs
+= fill_city_overlays_sprite_array(t
, sprs
, ptile
, citymode
);
5083 if (mapdeco_is_crosshair_set(ptile
)) {
5084 ADD_SPRITE_SIMPLE(t
->sprites
.user
.attention
);
5089 case LAYER_TILELABEL
:
5090 /* Nothing. This is just a placeholder. */
5094 if (ptile
&& goto_is_active()) {
5095 sprs
+= fill_goto_sprite_array(t
, sprs
, ptile
, pedge
, pcorner
);
5100 if (ptile
&& editor_is_active()) {
5101 if (editor_tile_is_selected(ptile
)) {
5102 int color
= 2 % tileset_num_city_colors(tileset
);
5103 ADD_SPRITE_SIMPLE(t
->sprites
.city
.unworked_tile_overlay
.p
[color
]);
5106 if (NULL
!= map_startpos_get(ptile
)) {
5107 /* FIXME: Use a more representative sprite. */
5108 ADD_SPRITE_SIMPLE(t
->sprites
.user
.attention
);
5118 return sprs
- save_sprs
;
5121 /**********************************************************************
5122 Set city tiles sprite values; should only happen after
5123 tilespec_load_tiles().
5124 ***********************************************************************/
5125 void tileset_setup_city_tiles(struct tileset
*t
, int style
)
5127 if (style
== game
.control
.styles_count
- 1) {
5129 /* Free old sprites */
5130 free_city_sprite(t
->sprites
.city
.tile
);
5131 free_city_sprite(t
->sprites
.city
.wall
);
5132 free_city_sprite(t
->sprites
.city
.occupied
);
5134 t
->sprites
.city
.tile
= load_city_sprite(t
, "city");
5135 t
->sprites
.city
.wall
= load_city_sprite(t
, "wall");
5136 t
->sprites
.city
.occupied
= load_city_sprite(t
, "occupied");
5138 for (style
= 0; style
< game
.control
.styles_count
; style
++) {
5139 if (t
->sprites
.city
.tile
->styles
[style
].land_num_thresholds
== 0) {
5140 tileset_error(LOG_FATAL
, _("City style \"%s\": no city graphics."),
5141 city_style_rule_name(style
));
5143 if (t
->sprites
.city
.wall
->styles
[style
].land_num_thresholds
== 0) {
5144 tileset_error(LOG_FATAL
, _("City style \"%s\": no wall graphics."),
5145 city_style_rule_name(style
));
5147 if (t
->sprites
.city
.occupied
->styles
[style
].land_num_thresholds
== 0) {
5148 tileset_error(LOG_FATAL
, _("City style \"%s\": no occupied graphics."),
5149 city_style_rule_name(style
));
5155 /****************************************************************************
5156 Return the amount of time between calls to toggle_focus_unit_state.
5157 The main loop needs to call toggle_focus_unit_state about this often
5158 to do the active-unit animation.
5159 ****************************************************************************/
5160 double get_focus_unit_toggle_timeout(const struct tileset
*t
)
5162 if (t
->sprites
.unit
.select
[0]) {
5169 /****************************************************************************
5170 Reset the focus unit state. This should be called when changing
5172 ****************************************************************************/
5173 void reset_focus_unit_state(struct tileset
*t
)
5175 focus_unit_state
= 0;
5178 /****************************************************************************
5179 Setup tileset for showing combat where focus unit participates.
5180 ****************************************************************************/
5181 void focus_unit_in_combat(struct tileset
*t
)
5183 if (!t
->sprites
.unit
.select
[0]) {
5184 reset_focus_unit_state(t
);
5188 /****************************************************************************
5189 Toggle/increment the focus unit state. This should be called once
5190 every get_focus_unit_toggle_timeout() seconds.
5191 ****************************************************************************/
5192 void toggle_focus_unit_state(struct tileset
*t
)
5195 if (t
->sprites
.unit
.select
[0]) {
5196 focus_unit_state
%= NUM_TILES_SELECT
;
5198 focus_unit_state
%= 2;
5202 /**********************************************************************
5203 Find unit that we can display from given tile.
5204 ***********************************************************************/
5205 struct unit
*get_drawable_unit(const struct tileset
*t
,
5207 const struct city
*citymode
)
5209 struct unit
*punit
= find_visible_unit(ptile
);
5214 if (citymode
&& unit_owner(punit
) == city_owner(citymode
))
5217 if (!unit_is_in_focus(punit
)
5218 || t
->sprites
.unit
.select
[0] || focus_unit_state
== 0)
5224 /****************************************************************************
5225 This patch unloads all sprites from the sprite hash (the hash itself
5227 ****************************************************************************/
5228 static void unload_all_sprites(struct tileset
*t
)
5230 if (t
->sprite_hash
) {
5231 sprite_hash_iterate(t
->sprite_hash
, tag_name
, ss
) {
5232 while (ss
->ref_count
> 0) {
5233 unload_sprite(t
, tag_name
);
5235 } sprite_hash_iterate_end
;
5239 /**********************************************************************
5240 Free all sprites from tileset.
5241 ***********************************************************************/
5242 void tileset_free_tiles(struct tileset
*t
)
5244 log_debug("tileset_free_tiles()");
5246 unload_all_sprites(t
);
5248 free_city_sprite(t
->sprites
.city
.tile
);
5249 t
->sprites
.city
.tile
= NULL
;
5250 free_city_sprite(t
->sprites
.city
.wall
);
5251 t
->sprites
.city
.wall
= NULL
;
5252 free_city_sprite(t
->sprites
.city
.occupied
);
5253 t
->sprites
.city
.occupied
= NULL
;
5255 if (t
->sprite_hash
) {
5256 sprite_hash_destroy(t
->sprite_hash
);
5257 t
->sprite_hash
= NULL
;
5260 small_sprite_list_iterate(t
->small_sprites
, ss
) {
5261 small_sprite_list_remove(t
->small_sprites
, ss
);
5265 fc_assert(ss
->sprite
== NULL
);
5267 } small_sprite_list_iterate_end
;
5269 specfile_list_iterate(t
->specfiles
, sf
) {
5270 specfile_list_remove(t
->specfiles
, sf
);
5271 free(sf
->file_name
);
5272 if (sf
->big_sprite
) {
5273 free_sprite(sf
->big_sprite
);
5274 sf
->big_sprite
= NULL
;
5277 } specfile_list_iterate_end
;
5279 sprite_vector_iterate(&t
->sprites
.city
.worked_tile_overlay
, psprite
) {
5280 free_sprite(*psprite
);
5281 } sprite_vector_iterate_end
;
5282 sprite_vector_free(&t
->sprites
.city
.worked_tile_overlay
);
5284 sprite_vector_iterate(&t
->sprites
.city
.unworked_tile_overlay
, psprite
) {
5285 free_sprite(*psprite
);
5286 } sprite_vector_iterate_end
;
5287 sprite_vector_free(&t
->sprites
.city
.unworked_tile_overlay
);
5289 if (t
->sprites
.tx
.fullfog
) {
5290 free(t
->sprites
.tx
.fullfog
);
5291 t
->sprites
.tx
.fullfog
= NULL
;
5294 sprite_vector_free(&t
->sprites
.colors
.overlays
);
5295 sprite_vector_free(&t
->sprites
.explode
.unit
);
5296 sprite_vector_free(&t
->sprites
.nation_flag
);
5297 sprite_vector_free(&t
->sprites
.nation_shield
);
5298 sprite_vector_free(&t
->sprites
.citybar
.occupancy
);
5300 tileset_background_free(t
);
5303 /**************************************************************************
5304 Return the sprite for drawing the given spaceship part.
5305 **************************************************************************/
5306 struct sprite
*get_spaceship_sprite(const struct tileset
*t
,
5307 enum spaceship_part part
)
5309 return t
->sprites
.spaceship
[part
];
5312 /**************************************************************************
5313 Return a sprite for the given citizen. The citizen's type is given,
5314 as well as their index (in the range [0..city_size_get(pcity))). The
5315 citizen's city can be used to determine which sprite to use (a NULL
5316 value indicates there is no city; i.e., the sprite is just being
5318 **************************************************************************/
5319 struct sprite
*get_citizen_sprite(const struct tileset
*t
,
5320 enum citizen_category type
,
5322 const struct city
*pcity
)
5324 const struct citizen_graphic
*graphic
;
5326 if (type
< CITIZEN_SPECIALIST
) {
5327 fc_assert(type
>= 0);
5328 graphic
= &t
->sprites
.citizen
[type
];
5330 fc_assert(type
< (CITIZEN_SPECIALIST
+ SP_MAX
));
5331 graphic
= &t
->sprites
.specialist
[type
- CITIZEN_SPECIALIST
];
5334 return graphic
->sprite
[citizen_index
% graphic
->count
];
5337 /**************************************************************************
5338 Return the sprite for the nation.
5339 **************************************************************************/
5340 struct sprite
*get_nation_flag_sprite(const struct tileset
*t
,
5341 const struct nation_type
*pnation
)
5343 return t
->sprites
.nation_flag
.p
[nation_index(pnation
)];
5346 /**************************************************************************
5347 Return the sprite for the technology/advance.
5348 **************************************************************************/
5349 struct sprite
*get_tech_sprite(const struct tileset
*t
, Tech_type_id tech
)
5351 fc_assert_ret_val(0 <= tech
&& tech
< advance_count(), NULL
);
5352 return t
->sprites
.tech
[tech
];
5355 /**************************************************************************
5356 Return the sprite for the building/improvement.
5357 **************************************************************************/
5358 struct sprite
*get_building_sprite(const struct tileset
*t
,
5359 struct impr_type
*pimprove
)
5361 fc_assert_ret_val(NULL
!= pimprove
, NULL
);
5362 return t
->sprites
.building
[improvement_index(pimprove
)];
5365 /****************************************************************************
5366 Return the sprite for the government.
5367 ****************************************************************************/
5368 struct sprite
*get_government_sprite(const struct tileset
*t
,
5369 const struct government
*gov
)
5371 fc_assert_ret_val(NULL
!= gov
, NULL
);
5372 return t
->sprites
.government
[government_index(gov
)];
5375 /****************************************************************************
5376 Return the sprite for the unit type (the base "unit" sprite).
5377 ****************************************************************************/
5378 struct sprite
*get_unittype_sprite(const struct tileset
*t
,
5379 const struct unit_type
*punittype
,
5380 enum direction8 facing
,
5383 int uidx
= utype_index(punittype
);
5385 fc_assert_ret_val(NULL
!= punittype
, NULL
);
5387 if (!is_valid_dir(facing
)) {
5388 /* Fallback to using random orientation sprite. */
5389 facing
= rand_direction();
5392 if (t
->sprites
.units
.icon
[uidx
]
5393 && (icon
|| t
->sprites
.units
.facing
[uidx
][facing
] == NULL
)) {
5394 /* Has icon sprite */
5395 return t
->sprites
.units
.icon
[uidx
];
5397 return t
->sprites
.units
.facing
[uidx
][facing
];
5401 /**************************************************************************
5402 Return a "sample" sprite for this city style.
5403 **************************************************************************/
5404 struct sprite
*get_sample_city_sprite(const struct tileset
*t
,
5407 int num_thresholds
=
5408 t
->sprites
.city
.tile
->styles
[city_style
].land_num_thresholds
;
5410 if (num_thresholds
== 0) {
5413 return (t
->sprites
.city
.tile
->styles
[city_style
]
5414 .land_thresholds
[num_thresholds
- 1].sprite
);
5418 /**************************************************************************
5419 Return a sprite with an "arrow" theme graphic.
5420 **************************************************************************/
5421 struct sprite
*get_arrow_sprite(const struct tileset
*t
,
5422 enum arrow_type arrow
)
5424 fc_assert_ret_val(arrow
>= 0 && arrow
< ARROW_LAST
, NULL
);
5426 return t
->sprites
.arrow
[arrow
];
5429 /**************************************************************************
5430 Return a tax sprite for the given output type (usually gold/lux/sci).
5431 **************************************************************************/
5432 struct sprite
*get_tax_sprite(const struct tileset
*t
, Output_type_id otype
)
5436 return t
->sprites
.tax_science
;
5438 return t
->sprites
.tax_gold
;
5440 return t
->sprites
.tax_luxury
;
5450 /**************************************************************************
5451 Return a thumbs-up/thumbs-down sprite to show treaty approval or
5453 **************************************************************************/
5454 struct sprite
*get_treaty_thumb_sprite(const struct tileset
*t
, bool on_off
)
5456 return t
->sprites
.treaty_thumb
[on_off
? 1 : 0];
5459 /**************************************************************************
5460 Return a sprite_vector containing the animation sprites for a unit
5462 **************************************************************************/
5463 const struct sprite_vector
*get_unit_explode_animation(const struct
5466 return &t
->sprites
.explode
.unit
;
5469 /****************************************************************************
5470 Return a sprite contining the single nuke graphic.
5472 TODO: This should be an animation like the unit explode animation.
5473 ****************************************************************************/
5474 struct sprite
*get_nuke_explode_sprite(const struct tileset
*t
)
5476 return t
->sprites
.explode
.nuke
;
5479 /**************************************************************************
5480 Return all the sprites used for city bar drawing.
5481 **************************************************************************/
5482 const struct citybar_sprites
*get_citybar_sprites(const struct tileset
*t
)
5484 if (draw_full_citybar
) {
5485 return &t
->sprites
.citybar
;
5491 /**************************************************************************
5492 Return all the sprites used for editor icons, images, etc.
5493 **************************************************************************/
5494 const struct editor_sprites
*get_editor_sprites(const struct tileset
*t
)
5496 return &t
->sprites
.editor
;
5499 /**************************************************************************
5500 Returns a sprite for the given cursor. The "hot" coordinates (the
5501 active coordinates of the mouse relative to the sprite) are placed int
5503 A cursor can consist of several frames to be used for animation.
5504 **************************************************************************/
5505 struct sprite
*get_cursor_sprite(const struct tileset
*t
,
5506 enum cursor_type cursor
,
5507 int *hot_x
, int *hot_y
, int frame
)
5509 *hot_x
= t
->sprites
.cursor
[cursor
].hot_x
;
5510 *hot_y
= t
->sprites
.cursor
[cursor
].hot_y
;
5511 return t
->sprites
.cursor
[cursor
].frame
[frame
];
5514 /****************************************************************************
5515 Return a sprite for the given icon. Icons are used by the operating
5516 system/window manager. Usually freeciv has to tell the OS what icon to
5519 Note that this function will return NULL before the sprites are loaded.
5520 The GUI code must be sure to call tileset_load_tiles before setting the
5522 ****************************************************************************/
5523 struct sprite
*get_icon_sprite(const struct tileset
*t
, enum icon_type icon
)
5525 return t
->sprites
.icon
[icon
];
5528 /****************************************************************************
5529 Returns a sprite with the "user-attention" crosshair graphic.
5531 FIXME: This function shouldn't be needed if the attention graphics are
5532 drawn natively by the tileset code.
5533 ****************************************************************************/
5534 struct sprite
*get_attention_crosshair_sprite(const struct tileset
*t
)
5536 return t
->sprites
.user
.attention
;
5539 /****************************************************************************
5540 Returns a sprite for the given indicator with the given index. The
5541 index should be in [0, NUM_TILES_PROGRESS).
5542 ****************************************************************************/
5543 struct sprite
*get_indicator_sprite(const struct tileset
*t
,
5544 enum indicator_type indicator
,
5547 index
= CLIP(0, index
, NUM_TILES_PROGRESS
- 1);
5548 fc_assert_ret_val(indicator
>= 0 && indicator
< INDICATOR_COUNT
, NULL
);
5549 return t
->sprites
.indicator
[indicator
][index
];
5552 /****************************************************************************
5553 Return a sprite for the unhappiness of the unit - to be shown as an
5554 overlay on the unit in the city support dialog, for instance.
5556 May return NULL if there's no unhappiness.
5557 ****************************************************************************/
5558 struct sprite
*get_unit_unhappy_sprite(const struct tileset
*t
,
5559 const struct unit
*punit
,
5562 const int unhappy
= CLIP(0, happy_cost
, MAX_NUM_UPKEEP_SPRITES
+1);
5565 return t
->sprites
.upkeep
.unhappy
[unhappy
- 1];
5571 /****************************************************************************
5572 Return a sprite for the upkeep of the unit - to be shown as an overlay
5573 on the unit in the city support dialog, for instance.
5575 May return NULL if there's no unhappiness.
5576 ****************************************************************************/
5577 struct sprite
*get_unit_upkeep_sprite(const struct tileset
*t
,
5578 Output_type_id otype
,
5579 const struct unit
*punit
,
5580 const int *upkeep_cost
)
5582 const int upkeep
= CLIP(0, upkeep_cost
[otype
], MAX_NUM_UPKEEP_SPRITES
+1);
5585 return t
->sprites
.upkeep
.output
[otype
][upkeep
- 1];
5591 /****************************************************************************
5592 Return a rectangular sprite containing a fog "color". This can be used
5593 for drawing fog onto arbitrary areas (like the overview).
5594 ****************************************************************************/
5595 struct sprite
*get_basic_fog_sprite(const struct tileset
*t
)
5597 return t
->sprites
.tx
.fog
;
5600 /****************************************************************************
5601 Return the tileset's color system.
5602 ****************************************************************************/
5603 struct color_system
*get_color_system(const struct tileset
*t
)
5605 return t
->color_system
;
5608 /****************************************************************************
5609 Loads prefered theme if there's any.
5610 ****************************************************************************/
5611 void tileset_use_prefered_theme(const struct tileset
*t
)
5613 char *default_theme_name
= NULL
;
5614 size_t default_theme_name_sz
= 0;
5617 switch (get_gui_type()) {
5619 default_theme_name
= gui_gtk2_default_theme_name
;
5620 default_theme_name_sz
= sizeof(gui_gtk2_default_theme_name
);
5623 default_theme_name
= gui_gtk3_default_theme_name
;
5624 default_theme_name_sz
= sizeof(gui_gtk3_default_theme_name
);
5627 default_theme_name
= gui_sdl_default_theme_name
;
5628 default_theme_name_sz
= sizeof(gui_sdl_default_theme_name
);
5637 if (NULL
== default_theme_name
|| 0 == default_theme_name_sz
) {
5638 /* Theme is not supported by this client. */
5642 for (i
= 0; i
< t
->num_prefered_themes
; i
++) {
5643 if (strcmp(t
->prefered_themes
[i
], default_theme_name
)) {
5644 if (popup_theme_suggestion_dialog(t
->prefered_themes
[i
])) {
5645 log_debug("trying theme \"%s\".", t
->prefered_themes
[i
]);
5646 if (load_theme(t
->prefered_themes
[i
])) {
5647 (void) fc_strlcpy(default_theme_name
, t
->prefered_themes
[i
],
5648 default_theme_name_sz
);
5654 log_verbose("The tileset doesn't specify preferred themes or none of its "
5655 "preferred themes can be used. Using system default.");
5659 /****************************************************************************
5660 Initialize tileset structure
5661 ****************************************************************************/
5662 void tileset_init(struct tileset
*t
)
5664 /* We currently have no city sprites loaded. */
5665 t
->sprites
.city
.tile
= NULL
;
5666 t
->sprites
.city
.wall
= NULL
;
5667 t
->sprites
.city
.occupied
= NULL
;
5669 t
->sprites
.background
.color
= NULL
;
5670 t
->sprites
.background
.graphic
= NULL
;
5672 player_slots_iterate(pslot
) {
5673 int i
, j
, id
= player_slot_index(pslot
);
5675 for (i
= 0; i
< EDGE_COUNT
; i
++) {
5676 for (j
= 0; j
< 2; j
++) {
5677 t
->sprites
.player
[id
].grid_borders
[i
][j
] = NULL
;
5681 t
->sprites
.player
[id
].color
= NULL
;
5682 t
->sprites
.player
[id
].background
= NULL
;
5683 } player_slots_iterate_end
;
5686 /****************************************************************************
5687 Fill the sprite array with sprites that together make a representative
5688 image of the given terrain type. Suitable for use as an icon and in list
5691 NB: The 'layer' argument is NOT a LAYER_* value, but rather one of 0, 1, 2.
5692 Using other values for 'layer' here will result in undefined behaviour. ;)
5693 ****************************************************************************/
5694 int fill_basic_terrain_layer_sprite_array(struct tileset
*t
,
5695 struct drawn_sprite
*sprs
,
5697 struct terrain
*pterrain
)
5699 struct drawn_sprite
*save_sprs
= sprs
;
5700 struct drawing_data
*draw
= t
->sprites
.drawing
[terrain_index(pterrain
)];
5702 struct terrain
*tterrain_near
[8];
5703 bv_special tspecial_near
[8];
5705 struct tile dummy_tile
; /* :( */
5710 memset(&dummy_tile
, 0, sizeof(struct tile
));
5712 for (i
= 0; i
< 8; i
++) {
5713 tterrain_near
[i
] = pterrain
;
5714 BV_CLR_ALL(tspecial_near
[i
]);
5717 i
= draw
->is_reversed
? draw
->num_layers
- layer
- 1 : layer
;
5718 sprs
+= fill_terrain_sprite_array(t
, sprs
, i
, &dummy_tile
,
5719 pterrain
, tterrain_near
, draw
);
5721 return sprs
- save_sprs
;
5724 /****************************************************************************
5725 Return the sprite for the given resource type.
5726 ****************************************************************************/
5727 struct sprite
*get_resource_sprite(const struct tileset
*t
,
5728 const struct resource
*presource
)
5730 if (presource
== NULL
) {
5734 return t
->sprites
.resource
[resource_index(presource
)];
5737 /****************************************************************************
5738 Return a representative sprite for the mine special type (S_MINE).
5739 ****************************************************************************/
5740 struct sprite
*get_basic_mine_sprite(const struct tileset
*t
)
5742 struct drawing_data
*draw
;
5745 tm
= terrain_by_rule_name("mountains");
5747 draw
= t
->sprites
.drawing
[terrain_index(tm
)];
5748 if (draw
->mine
!= NULL
) {
5753 terrain_type_iterate(pterrain
) {
5754 draw
= t
->sprites
.drawing
[terrain_index(pterrain
)];
5755 if (draw
->mine
!= NULL
) {
5758 } terrain_type_iterate_end
;
5763 /****************************************************************************
5764 Return a representative sprite for the given special type.
5766 NB: This does not include generic base specials (S_FORTRESS and
5767 S_AIRBASE). Use fill_basic_base_sprite_array and the base type for that.
5768 ****************************************************************************/
5769 struct sprite
*get_basic_special_sprite(const struct tileset
*t
,
5770 enum tile_special_type special
)
5774 return t
->sprites
.tx
.irrigation
[0];
5777 return get_basic_mine_sprite(t
);
5780 return t
->sprites
.tx
.pollution
;
5783 return t
->sprites
.tx
.village
;
5786 return t
->sprites
.tx
.farmland
[0];
5789 return t
->sprites
.tx
.fallout
;
5798 /****************************************************************************
5799 Fills the sprite array with sprites that together make a representative
5800 image of the given road type. The image is suitable for use as an icon
5801 for the road type, for example.
5802 ****************************************************************************/
5803 int fill_basic_road_sprite_array(const struct tileset
*t
,
5804 struct drawn_sprite
*sprs
,
5805 const struct road_type
*proad
)
5807 struct drawn_sprite
*saved_sprs
= sprs
;
5810 enum roadstyle_id roadstyle
;
5812 if (!t
|| !sprs
|| !proad
) {
5816 index
= road_index(proad
);
5818 if (!(0 <= index
&& index
< game
.control
.num_road_types
)) {
5822 roadstyle
= t
->sprites
.roads
[index
].roadstyle
;
5824 if (roadstyle
== RSTYLE_RIVER
) {
5825 ADD_SPRITE_SIMPLE(t
->sprites
.roads
[index
].u
.rivers
.spec
[0]);
5827 for (i
= 0; i
< t
->num_valid_tileset_dirs
; i
++) {
5828 if (!t
->valid_tileset_dirs
[i
]) {
5831 if (roadstyle
== RSTYLE_ALL_SEPARATE
) {
5832 ADD_SPRITE_SIMPLE(t
->sprites
.roads
[index
].u
.dir
[i
]);
5833 } else if (roadstyle
== RSTYLE_PARITY_COMBINED
) {
5835 ADD_SPRITE_SIMPLE(t
->sprites
.roads
[index
].u
.combo
.even
[1 << (i
/ 2)]);
5837 } else if (roadstyle
== RSTYLE_ALL_COMBINED
) {
5838 ADD_SPRITE_SIMPLE(t
->sprites
.roads
[index
].u
.total
[1 << i
]);
5843 return sprs
- saved_sprs
;
5846 /****************************************************************************
5847 Fills the sprite array with sprites that together make a representative
5848 image of the given base type. The image is suitable for use as an icon
5849 for the base type, for example.
5850 ****************************************************************************/
5851 int fill_basic_base_sprite_array(const struct tileset
*t
,
5852 struct drawn_sprite
*sprs
,
5853 const struct base_type
*pbase
)
5855 struct drawn_sprite
*saved_sprs
= sprs
;
5858 if (!t
|| !sprs
|| !pbase
) {
5862 index
= base_index(pbase
);
5864 if (!(0 <= index
&& index
< game
.control
.num_base_types
)) {
5868 #define ADD_SPRITE_IF_NOT_NULL(x) do {\
5870 ADD_SPRITE_FULL(x);\
5874 /* Corresponds to LAYER_SPECIAL{1,2,3} order. */
5875 ADD_SPRITE_IF_NOT_NULL(t
->sprites
.bases
[index
].background
);
5876 ADD_SPRITE_IF_NOT_NULL(t
->sprites
.bases
[index
].middleground
);
5877 ADD_SPRITE_IF_NOT_NULL(t
->sprites
.bases
[index
].foreground
);
5879 #undef ADD_SPRITE_IF_NOT_NULL
5881 return sprs
- saved_sprs
;
5884 /****************************************************************************
5885 Setup tiles for one player using the player color.
5886 ****************************************************************************/
5887 void tileset_player_init(struct tileset
*t
, struct player
*pplayer
)
5891 fc_assert_ret(pplayer
!= NULL
);
5892 fc_assert_ret(pplayer
->rgb
!= NULL
);
5894 /* Free all data before recreating it. */
5895 tileset_player_free(t
, pplayer
);
5897 plrid
= player_index(pplayer
);
5899 t
->sprites
.player
[plrid
].color
5900 = create_plr_sprite(ensure_color(pplayer
->rgb
));
5901 t
->sprites
.player
[plrid
].background
5902 = crop_sprite(t
->sprites
.player
[plrid
].color
, 0, 0,
5903 t
->normal_tile_width
, t
->normal_tile_height
,
5904 t
->sprites
.mask
.tile
, 0, 0);
5906 for (i
= 0; i
< EDGE_COUNT
; i
++) {
5907 for (j
= 0; j
< 2; j
++) {
5910 if (t
->sprites
.player
[plrid
].color
5911 && t
->sprites
.grid
.borders
[i
][j
]) {
5912 s
= crop_sprite(t
->sprites
.player
[plrid
].color
, 0, 0,
5913 t
->normal_tile_width
, t
->normal_tile_height
,
5914 t
->sprites
.grid
.borders
[i
][j
], 0, 0);
5916 s
= t
->sprites
.grid
.borders
[i
][j
];
5918 t
->sprites
.player
[plrid
].grid_borders
[i
][j
] = s
;
5923 /****************************************************************************
5924 Free tiles for one player using the player color.
5925 ****************************************************************************/
5926 void tileset_player_free(struct tileset
*t
, struct player
*pplayer
)
5930 fc_assert_ret(pplayer
!= NULL
);
5932 plrid
= player_index(pplayer
);
5934 if (t
->sprites
.player
[plrid
].color
) {
5935 free_sprite(t
->sprites
.player
[plrid
].color
);
5936 t
->sprites
.player
[plrid
].color
= NULL
;
5938 if (t
->sprites
.player
[plrid
].background
) {
5939 free_sprite(t
->sprites
.player
[plrid
].background
);
5940 t
->sprites
.player
[plrid
].background
= NULL
;
5943 for (i
= 0; i
< EDGE_COUNT
; i
++) {
5944 for (j
= 0; j
< 2; j
++) {
5945 if (t
->sprites
.player
[plrid
].grid_borders
[i
][j
]) {
5946 free_sprite(t
->sprites
.player
[plrid
].grid_borders
[i
][j
]);
5947 t
->sprites
.player
[plrid
].grid_borders
[i
][j
] = NULL
;
5953 /****************************************************************************
5954 Setup tiles for the background.
5955 ****************************************************************************/
5956 void tileset_background_init(struct tileset
*t
)
5958 /* Free all data before recreating it. */
5959 tileset_background_free(t
);
5961 /* generate background color */
5962 t
->sprites
.background
.color
5963 = create_plr_sprite(ensure_color(game
.plr_bg_color
));
5965 /* Chop up and build the background graphics. */
5966 t
->sprites
.background
.graphic
5967 = crop_sprite(t
->sprites
.background
.color
, 0, 0,
5968 t
->normal_tile_width
, t
->normal_tile_height
,
5969 t
->sprites
.mask
.tile
, 0, 0);
5972 /****************************************************************************
5973 Free tiles for the background.
5974 ****************************************************************************/
5975 void tileset_background_free(struct tileset
*t
)
5977 if (t
->sprites
.background
.color
) {
5978 free_sprite(t
->sprites
.background
.color
);
5979 t
->sprites
.background
.color
= NULL
;
5982 if (t
->sprites
.background
.graphic
) {
5983 free_sprite(t
->sprites
.background
.graphic
);
5984 t
->sprites
.background
.graphic
= NULL
;
5988 /****************************************************************************
5989 Reset tileset data specific to ruleset.
5990 ****************************************************************************/
5991 void tileset_ruleset_reset(struct tileset
*t
)
5993 if (t
->rivers
!= NULL
) {
5994 road_type_list_destroy(t
->rivers
);
5996 t
->rivers
= road_type_list_new();