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"
33 #include "deprecations.h"
40 #include "string_vector.h"
46 #include "game.h" /* game.control.styles_count */
47 #include "government.h"
53 #include "specialist.h"
58 #include "dialogs_g.h"
59 #include "graphics_g.h"
60 #include "gui_main_g.h"
61 #include "mapview_g.h" /* for update_map_canvas_visible */
66 #include "citydlg_common.h" /* for generate_citydlg_dimensions() */
67 #include "client_main.h"
68 #include "climap.h" /* for client_tile_get_known() */
69 #include "colors_common.h"
70 #include "control.h" /* for fill_xxx */
74 #include "options.h" /* for fill_xxx */
75 #include "themes_common.h"
79 #define TILESPEC_CAPSTR "+Freeciv-2.6-tilespec duplicates_ok"
81 * Tilespec capabilities acceptable to this program:
83 * +Freeciv-2.4-tilespec
84 * - basic format for Freeciv versions 2.4.x; required
86 * +Freeciv-tilespec-Devel-YYYY.MMM.DD
87 * - tilespec of the development version at the given data
90 * - we can handle existence of duplicate tags (lattermost tag which
91 * appears is used; tilesets which have duplicates should specify
95 #define SPEC_CAPSTR "+Freeciv-2.6-spec"
97 * Individual spec file capabilities acceptable to this program:
100 * - basic format for Freeciv versions 2.3.x; required
103 #define TILESPEC_SUFFIX ".tilespec"
104 #define TILE_SECTION_PREFIX "tile_"
106 /* This the way directional indices are now encoded: */
107 #define MAX_INDEX_CARDINAL 64
108 #define MAX_INDEX_HALF 16
109 #define MAX_INDEX_VALID 256
111 #define NUM_TILES_HP_BAR 11
112 #define NUM_TILES_DIGITS 10
113 #define NUM_TILES_SELECT 4
114 #define MAX_NUM_UPKEEP_SPRITES 10
116 #define SPECENUM_NAME extrastyle_id
117 #define SPECENUM_VALUE0 ESTYLE_ROAD_ALL_SEPARATE
118 #define SPECENUM_VALUE0NAME "RoadAllSeparate"
119 #define SPECENUM_VALUE1 ESTYLE_ROAD_PARITY_COMBINED
120 #define SPECENUM_VALUE1NAME "RoadParityCombined"
121 #define SPECENUM_VALUE2 ESTYLE_ROAD_ALL_COMBINED
122 #define SPECENUM_VALUE2NAME "RoadAllCombined"
123 #define SPECENUM_VALUE3 ESTYLE_RIVER
124 #define SPECENUM_VALUE3NAME "River"
125 #define SPECENUM_VALUE4 ESTYLE_SINGLE1
126 #define SPECENUM_VALUE4NAME "Single1"
127 #define SPECENUM_VALUE5 ESTYLE_SINGLE2
128 #define SPECENUM_VALUE5NAME "Single2"
129 #define SPECENUM_VALUE6 ESTYLE_3LAYER
130 #define SPECENUM_VALUE6NAME "3Layer"
131 #define SPECENUM_VALUE7 ESTYLE_CARDINALS
132 #define SPECENUM_VALUE7NAME "Cardinals"
133 #define SPECENUM_COUNT ESTYLE_COUNT
134 #include "specenum_gen.h"
136 /* This could be moved to common/map.h if there's more use for it. */
138 DIR4_NORTH
= 0, DIR4_SOUTH
, DIR4_EAST
, DIR4_WEST
140 static const char direction4letters
[4] = "udrl";
141 /* This must correspond to enum edge_type. */
142 static const char edge_name
[EDGE_COUNT
][3] = {"ns", "we", "ud", "lr"};
144 static const int DIR4_TO_DIR8
[4] =
145 { DIR8_NORTH
, DIR8_SOUTH
, DIR8_EAST
, DIR8_WEST
};
149 MATCH_SAME
, /* "boolean" match */
155 CELL_WHOLE
, /* entire tile */
156 CELL_CORNER
/* corner of tile */
159 struct drawing_data
{
164 int num_layers
; /* 1 thru MAX_NUM_LAYERS. */
165 #define MAX_NUM_LAYERS 3
167 struct drawing_layer
{
169 int offset_x
, offset_y
;
171 #define MAX_NUM_MATCH_WITH 8
172 enum match_style match_style
;
173 int match_index
[1 + MAX_NUM_MATCH_WITH
];
174 int match_indices
; /* 0 = no match_type, 1 = no match_with */
176 enum sprite_type sprite_type
;
178 struct sprite_vector base
;
179 struct sprite
*match
[MAX_INDEX_CARDINAL
];
180 struct sprite
**cells
;
182 /* List of those sprites in 'cells' that are allocated by some other
183 * means than load_sprite() and thus are not freed by unload_all_sprites(). */
184 struct sprite_vector allocated
;
185 } layer
[MAX_NUM_LAYERS
];
189 int blending
; /* layer, 0 = none */
190 struct sprite
*blender
;
191 struct sprite
*blend
[4]; /* indexed by a direction4 */
194 struct city_style_threshold
{
195 struct sprite
*sprite
;
200 int land_num_thresholds
;
201 struct city_style_threshold
*land_thresholds
;
206 struct river_sprites
{
208 *spec
[MAX_INDEX_CARDINAL
],
209 *outlet
[MAX_INDEX_CARDINAL
];
212 struct named_sprites
{
214 *indicator
[INDICATOR_COUNT
][NUM_TILES_PROGRESS
],
215 *treaty_thumb
[2], /* 0=disagree, 1=agree */
216 *arrow
[ARROW_LAST
], /* 0=right arrow, 1=plus, 2=minus */
222 /* The panel sprites for showing tax % allocations. */
223 *tax_luxury
, *tax_science
, *tax_gold
,
224 *dither_tile
; /* only used for isometric view */
233 struct sprite
*tech
[A_LAST
];
234 struct sprite
*building
[B_LAST
];
235 struct sprite
*government
[G_LAST
];
238 struct sprite
*icon
[U_LAST
];
239 struct sprite
*facing
[U_LAST
][DIR8_MAGIC_MAX
];
240 unsigned int default_dir_seed
[U_LAST
];
243 struct sprite
*resource
[MAX_NUM_RESOURCES
];
245 struct sprite_vector nation_flag
;
246 struct sprite_vector nation_shield
;
248 struct citizen_graphic
{
249 /* Each citizen type has up to MAX_NUM_CITIZEN_SPRITES different
250 * sprites, as defined by the tileset. */
252 struct sprite
*sprite
[MAX_NUM_CITIZEN_SPRITES
];
253 } citizen
[CITIZEN_LAST
], specialist
[SP_MAX
];
254 struct sprite
*spaceship
[SPACESHIP_COUNT
];
257 struct sprite
*frame
[NUM_CURSOR_FRAMES
];
258 } cursor
[CURSOR_LAST
];
260 struct sprite_vector unit
;
265 *hp_bar
[NUM_TILES_HP_BAR
],
266 *vet_lev
[MAX_VET_LEVELS
],
267 *select
[NUM_TILES_SELECT
],
273 *go_to
, /* goto is a C keyword :-) */
284 *battlegroup
[MAX_NUM_BATTLEGROUPS
],
290 *unhappy
[MAX_NUM_UPKEEP_SPRITES
],
291 *output
[O_LAST
][MAX_NUM_UPKEEP_SPRITES
];
296 *size
[NUM_TILES_DIGITS
],
297 *size_tens
[NUM_TILES_DIGITS
],
298 *size_hundreds
[NUM_TILES_DIGITS
],
299 *tile_foodnum
[NUM_TILES_DIGITS
],
300 *tile_shieldnum
[NUM_TILES_DIGITS
],
301 *tile_tradenum
[NUM_TILES_DIGITS
];
305 *wall
[NUM_WALL_TYPES
],
307 struct sprite_vector worked_tile_overlay
;
308 struct sprite_vector unworked_tile_overlay
;
310 struct citybar_sprites citybar
;
311 struct editor_sprites editor
;
314 struct sprite
*specific
;
315 struct sprite
*turns
[NUM_TILES_DIGITS
];
316 struct sprite
*turns_tens
[NUM_TILES_DIGITS
];
317 struct sprite
*turns_hundreds
[NUM_TILES_DIGITS
];
319 struct sprite
*waypoint
;
322 struct sprite
*attention
;
328 *darkness
[MAX_INDEX_CARDINAL
]; /* first unused */
329 } tx
; /* terrain extra */
334 enum extrastyle_id extrastyle
;
336 struct sprite
*single
;
337 struct sprite
*cardinals
[MAX_INDEX_CARDINAL
];
346 /* for extrastyles ESTYLE_ROAD_ALL_SEPARATE and ESTYLE_ROAD_PARITY_COMBINED */
348 *corner
[8]; /* Indexed by direction; only non-cardinal dirs used. */
350 /* for ESTYLE_ROAD_ALL_SEPARATE */
351 struct sprite
*dir
[8]; /* all entries used */
352 /* ESTYLE_ROAD_PARITY_COMBINED */
355 *even
[MAX_INDEX_HALF
], /* first unused */
356 *odd
[MAX_INDEX_HALF
]; /* first unused */
358 /* ESTYLE_ALL_SEPARATE */
359 struct sprite
*total
[MAX_INDEX_VALID
];
360 struct river_sprites rivers
;
364 } extras
[MAX_EXTRA_TYPES
];
372 *selected
[EDGE_COUNT
],
373 *coastline
[EDGE_COUNT
],
374 *borders
[EDGE_COUNT
][2];
377 struct sprite_vector overlays
;
380 struct sprite
*color
; /* Generic background color */
381 struct sprite
*graphic
; /* Generic background graphic */
384 struct sprite
*grid_borders
[EDGE_COUNT
][2];
385 struct sprite
*color
;
386 struct sprite
*background
;
387 } player
[MAX_NUM_PLAYER_SLOTS
];
389 struct drawing_data
*drawing
[MAX_NUM_ITEMS
];
393 struct sprite
*big_sprite
;
397 #define SPECLIST_TAG specfile
398 #define SPECLIST_TYPE struct specfile
399 #include "speclist.h"
401 #define specfile_list_iterate(list, pitem) \
402 TYPED_LIST_ITERATE(struct specfile, list, pitem)
403 #define specfile_list_iterate_end LIST_ITERATE_END
406 * Information about an individual sprite. All fields except 'sprite' are
407 * filled at the time of the scan of the specfile. 'Sprite' is
408 * set/cleared on demand in load_sprite/unload_sprite.
410 struct small_sprite
{
413 /* The sprite is in this file. */
416 /* Or, the sprite is in this file at the location. */
418 int x
, y
, width
, height
;
420 /* A little more (optional) data. */
423 struct sprite
*sprite
;
426 /* 'struct small_sprite_list' and related functions. */
427 #define SPECLIST_TAG small_sprite
428 #define SPECLIST_TYPE struct small_sprite
429 #include "speclist.h"
430 #define small_sprite_list_iterate(list, pitem) \
431 TYPED_LIST_ITERATE(struct small_sprite, list, pitem)
432 #define small_sprite_list_iterate_end LIST_ITERATE_END
434 /* 'struct sprite_hash' and related functions. */
435 #define SPECHASH_TAG sprite
436 #define SPECHASH_ASTR_KEY_TYPE
437 #define SPECHASH_IDATA_TYPE struct small_sprite *
438 #include "spechash.h"
439 #define sprite_hash_iterate(hash, tag_name, sprite) \
440 TYPED_HASH_ITERATE(const char *, struct small_sprite *, \
441 hash, tag_name, sprite)
442 #define sprite_hash_iterate_end HASH_ITERATE_END
444 /* 'struct drawing_hash' and related functions. */
445 static void drawing_data_destroy(struct drawing_data
*draw
);
447 #define SPECHASH_TAG drawing
448 #define SPECHASH_CSTR_KEY_TYPE
449 #define SPECHASH_IDATA_TYPE struct drawing_data *
450 #define SPECHASH_IDATA_FREE drawing_data_destroy
451 #include "spechash.h"
453 #define SPECHASH_TAG estyle
454 #define SPECHASH_ASTR_KEY_TYPE
455 #define SPECHASH_ENUM_DATA_TYPE extrastyle_id
456 #include "spechash.h"
460 char given_name
[MAX_LEN_NAME
];
461 char version
[MAX_LEN_NAME
];
469 int hex_width
, hex_height
;
472 int normal_tile_width
, normal_tile_height
;
473 int full_tile_width
, full_tile_height
;
474 int unit_tile_width
, unit_tile_height
;
475 int small_sprite_width
, small_sprite_height
;
477 int max_upkeep_height
;
479 char *main_intro_filename
;
480 char *minimap_intro_filename
;
482 int city_names_font_size
, city_productions_font_size
;
484 enum fog_style fogstyle
;
485 enum darkness_style darkness_style
;
488 int unit_flag_offset_x
, unit_flag_offset_y
;
489 int city_flag_offset_x
, city_flag_offset_y
;
490 int unit_offset_x
, unit_offset_y
;
491 int city_offset_x
, city_offset_y
;
493 int citybar_offset_y
;
494 int tilelabel_offset_y
;
495 int activity_offset_x
;
496 int activity_offset_y
;
497 int occupied_offset_x
;
498 int occupied_offset_y
;
499 int unit_upkeep_offset_y
;
500 int unit_upkeep_small_offset_y
;
502 #define NUM_CORNER_DIRS 4
503 #define TILES_PER_CORNER 4
504 int num_valid_tileset_dirs
, num_cardinal_tileset_dirs
;
505 int num_index_valid
, num_index_cardinal
;
506 enum direction8 valid_tileset_dirs
[8], cardinal_tileset_dirs
[8];
508 struct tileset_layer
{
511 } layers
[MAX_NUM_LAYERS
];
513 struct specfile_list
*specfiles
;
514 struct small_sprite_list
*small_sprites
;
516 /* This hash table maps tilespec tags to struct small_sprites. */
517 struct sprite_hash
*sprite_hash
;
519 /* This hash table maps terrain graphic strings to drawing data. */
520 struct drawing_hash
*tile_hash
;
522 struct estyle_hash
*estyle_hash
;
524 struct named_sprites sprites
;
526 struct color_system
*color_system
;
528 struct extra_type_list
*style_lists
[ESTYLE_COUNT
];
530 struct extra_type_list
*flagged_bases_list
;
532 int num_preferred_themes
;
533 char** preferred_themes
;
536 struct tileset
*tileset
;
538 int focus_unit_state
= 0;
540 static bool tileset_update
= FALSE
;
543 static int fill_unit_type_sprite_array(const struct tileset
*t
,
544 struct drawn_sprite
*sprs
,
545 const struct unit_type
*putype
,
546 enum direction8 facing
);
547 static int fill_unit_sprite_array(const struct tileset
*t
,
548 struct drawn_sprite
*sprs
,
549 const struct unit
*punit
,
550 bool stack
, bool backdrop
);
551 static bool load_river_sprites(struct tileset
*t
,
552 struct river_sprites
*store
, const char *tag_pfx
);
554 static void tileset_setup_base(struct tileset
*t
,
555 const struct extra_type
*pextra
);
556 static void tileset_setup_road(struct tileset
*t
,
557 struct extra_type
*pextra
);
559 static bool is_extra_drawing_enabled(struct extra_type
*pextra
);
561 static int fill_basic_road_sprite_array(const struct tileset
*t
,
562 struct drawn_sprite
*sprs
,
563 const struct extra_type
*pextra
);
564 static int fill_basic_base_sprite_array(const struct tileset
*t
,
565 struct drawn_sprite
*sprs
,
566 const struct extra_type
*pextra
);
568 static void tileset_player_free(struct tileset
*t
, int plrid
);
570 /****************************************************************************
571 Called when ever there's problem in ruleset/tileset compatibility
572 ****************************************************************************/
573 void tileset_error(enum log_level level
, const char *format
, ...)
578 va_start(args
, format
);
579 fc_vsnprintf(buf
, sizeof(buf
), format
, args
);
582 log_base(level
, "%s", buf
);
584 if (level
<= LOG_NORMAL
) {
585 show_tileset_error(buf
);
588 if (level
== LOG_FATAL
) {
593 /****************************************************************************
594 Create a new drawing data.
595 ****************************************************************************/
596 static struct drawing_data
*drawing_data_new(void)
598 struct drawing_data
*draw
= fc_calloc(1, sizeof(*draw
));
605 /****************************************************************************
607 ****************************************************************************/
608 static void drawing_data_destroy(struct drawing_data
*draw
)
612 fc_assert_ret(NULL
!= draw
);
614 if (draw
->name
!= NULL
) {
617 for (i
= 0; i
< 4; i
++) {
618 if (draw
->blend
[i
]) {
619 free_sprite(draw
->blend
[i
]);
622 for (i
= 0; i
< draw
->num_layers
; i
++) {
623 int vec_size
= sprite_vector_size(&draw
->layer
[i
].allocated
);
626 for (j
= 0; j
< vec_size
; j
++) {
627 free_sprite(draw
->layer
[i
].allocated
.p
[j
]);
630 sprite_vector_free(&draw
->layer
[i
].base
);
631 sprite_vector_free(&draw
->layer
[i
].allocated
);
632 free(draw
->layer
[i
].cells
);
637 /****************************************************************************
638 Return the name of the given tileset.
639 ****************************************************************************/
640 const char *tileset_basename(const struct tileset
*t
)
645 /****************************************************************************
646 Return whether the current tileset is isometric.
647 ****************************************************************************/
648 bool tileset_is_isometric(const struct tileset
*t
)
650 return t
->type
== TS_ISOMETRIC
;
653 /****************************************************************************
654 Return the hex_width of the current tileset. For iso-hex tilesets this
655 value will be > 0 and is_isometric will be set.
656 ****************************************************************************/
657 int tileset_hex_width(const struct tileset
*t
)
662 /****************************************************************************
663 Return the hex_height of the current tileset. For hex tilesets this
664 value will be > 0 and is_isometric will be set.
665 ****************************************************************************/
666 int tileset_hex_height(const struct tileset
*t
)
668 return t
->hex_height
;
671 /****************************************************************************
672 Return the tile width of the current tileset. This is the tesselation
673 width of the tiled plane. This means it's the width of the bounding box
674 of the basic map tile.
677 - The value should be even (or a multiple of 4 in iso-view).
678 - In iso-view, the width should be twice the height (to give a
679 perspective of 30 degrees above the horizon).
680 - In non-iso-view, width and height should be equal (overhead
682 - In hex or iso-hex view, remember this is the tesselation vector.
683 hex_width and hex_height then give the size of the side of the
684 hexagon. Calculating the dimensions of a "regular" hexagon or
685 iso-hexagon may be tricky.
686 However these requirements are not absolute and callers should not
687 depend on them (although some do).
688 ****************************************************************************/
689 int tileset_tile_width(const struct tileset
*t
)
691 return t
->normal_tile_width
;
694 /****************************************************************************
695 Return the tile height of the current tileset. This is the tesselation
696 height of the tiled plane. This means it's the height of the bounding box
697 of the basic map tile.
699 See also tileset_tile_width.
700 ****************************************************************************/
701 int tileset_tile_height(const struct tileset
*t
)
703 return t
->normal_tile_height
;
706 /****************************************************************************
707 Return the full tile width of the current tileset. This is the maximum
708 width that any mapview sprite will have.
710 Note: currently this is always equal to the tile width.
711 ****************************************************************************/
712 int tileset_full_tile_width(const struct tileset
*t
)
714 return t
->full_tile_width
;
717 /****************************************************************************
718 Return the full tile height of the current tileset. This is the maximum
719 height that any mapview sprite will have. This may be greater than the
720 tile width in which case the extra area is above the "normal" tile.
722 Some callers assume the full height is 50% larger than the height in
723 iso-view, and equal in non-iso view.
724 ****************************************************************************/
725 int tileset_full_tile_height(const struct tileset
*t
)
727 return t
->full_tile_height
;
730 /****************************************************************************
731 Return the unit tile width of the current tileset.
732 ****************************************************************************/
733 int tileset_unit_width(const struct tileset
*t
)
735 return t
->unit_tile_width
;
738 /****************************************************************************
739 Return the unit tile height of the current tileset.
740 ****************************************************************************/
741 int tileset_unit_height(const struct tileset
*t
)
743 return t
->unit_tile_height
;
746 /****************************************************************************
747 Calculate the height of a unit upkeep icons.
748 ****************************************************************************/
749 static int calculate_max_upkeep_height(const struct tileset
*t
)
754 for (i
= 0; i
< MAX_NUM_UPKEEP_SPRITES
; i
++) {
755 if (t
->sprites
.upkeep
.unhappy
[i
] != NULL
) {
758 /* TODO: We want only height, getting the width might waste CPU
759 * depending on gui-specific implementation. */
760 get_sprite_dimensions(t
->sprites
.upkeep
.unhappy
[i
], &width
, &height
);
762 max
= MAX(max
, height
);
766 output_type_iterate(o
) {
767 for (i
= 0; i
< MAX_NUM_UPKEEP_SPRITES
; i
++) {
768 if (t
->sprites
.upkeep
.output
[o
][i
] != NULL
) {
771 /* TODO: We want only height, getting the width might waste CPU
772 * depending on gui-specific implementation. */
773 get_sprite_dimensions(t
->sprites
.upkeep
.output
[o
][i
], &width
, &height
);
775 max
= MAX(max
, height
);
778 } output_type_iterate_end
;
783 /****************************************************************************
784 Get the height of a unit upkeep icons.
785 ****************************************************************************/
786 static int tileset_upkeep_height(const struct tileset
*t
)
788 /* Return cached value */
789 return t
->max_upkeep_height
;
792 /****************************************************************************
793 Suitable canvas height for a unit icon that includes upkeep sprites.
794 ****************************************************************************/
795 int tileset_unit_with_upkeep_height(const struct tileset
*t
)
797 int uk_bottom
= tileset_unit_layout_offset_y(tileset
) + tileset_upkeep_height(tileset
);
798 int u_bottom
= tileset_unit_height(tileset
);
800 return MAX(uk_bottom
, u_bottom
);
803 /****************************************************************************
804 Suitable canvas height for a unit icon that includes upkeep sprites,
805 using small space layout.
806 ****************************************************************************/
807 int tileset_unit_with_small_upkeep_height(const struct tileset
*t
)
809 return tileset_unit_layout_small_offset_y(tileset
) + tileset_upkeep_height(tileset
);
812 /****************************************************************************
813 Offset to layout extra unit sprites, such as upkeep.
814 ****************************************************************************/
815 int tileset_unit_layout_offset_y(const struct tileset
*t
)
817 return t
->unit_upkeep_offset_y
;
820 /****************************************************************************
821 Offset to layout extra unit sprites, such as upkeep, requesting small
823 ****************************************************************************/
824 int tileset_unit_layout_small_offset_y(const struct tileset
*t
)
826 return t
->unit_upkeep_small_offset_y
;
829 /****************************************************************************
830 Return the small sprite width of the current tileset. The small sprites
831 are used for various theme graphics (e.g., citymap citizens/specialists
832 as well as panel indicator icons).
833 ****************************************************************************/
834 int tileset_small_sprite_width(const struct tileset
*t
)
836 return t
->small_sprite_width
;
839 /****************************************************************************
840 Return the offset from the origin of the city tile at which to place the
842 ****************************************************************************/
843 int tileset_citybar_offset_y(const struct tileset
*t
)
845 return t
->citybar_offset_y
;
848 /****************************************************************************
849 Return the offset from the origin of the tile at which to place the
851 ****************************************************************************/
852 int tileset_tilelabel_offset_y(const struct tileset
*t
)
854 return t
->tilelabel_offset_y
;
857 /****************************************************************************
858 Returns tileset scale
859 ****************************************************************************/
860 float tileset_scale(const struct tileset
*t
)
862 return tileset
->scale
;
865 /****************************************************************************
866 Return the small sprite height of the current tileset. The small sprites
867 are used for various theme graphics (e.g., citymap citizens/specialists
868 as well as panel indicator icons).
869 ****************************************************************************/
870 int tileset_small_sprite_height(const struct tileset
*t
)
872 return t
->small_sprite_height
;
875 /****************************************************************************
876 Return the path within the data directories where the main intro graphics
877 file can be found. (It is left up to the GUI code to load and unload this
879 ****************************************************************************/
880 const char *tileset_main_intro_filename(const struct tileset
*t
)
882 return t
->main_intro_filename
;
885 /****************************************************************************
886 Return the path within the data directories where the mini intro graphics
887 file can be found. (It is left up to the GUI code to load and unload this
889 ****************************************************************************/
890 const char *tileset_mini_intro_filename(const struct tileset
*t
)
892 return t
->minimap_intro_filename
;
895 /****************************************************************************
896 Return the number of possible colors for city overlays.
897 ****************************************************************************/
898 int tileset_num_city_colors(const struct tileset
*t
)
900 return t
->sprites
.city
.worked_tile_overlay
.size
;
903 /****************************************************************************
904 Return TRUE if the client will use the code to generate the fog.
905 ****************************************************************************/
906 bool tileset_use_hard_coded_fog(const struct tileset
*t
)
908 return FOG_AUTO
== t
->fogstyle
;
911 /**************************************************************************
913 **************************************************************************/
914 static struct tileset
*tileset_new(void)
916 struct tileset
*t
= fc_calloc(1, sizeof(*t
));
918 t
->specfiles
= specfile_list_new();
919 t
->small_sprites
= small_sprite_list_new();
923 /**************************************************************************
924 Return the tileset name of the direction. This is similar to
925 dir_get_name but you shouldn't change this or all tilesets will break.
926 **************************************************************************/
927 static const char *dir_get_tileset_name(enum direction8 dir
)
947 log_error("Wrong direction8 variant: %d.", dir
);
951 /****************************************************************************
952 Return TRUE iff the dir is valid in this tileset.
953 ****************************************************************************/
954 static bool is_valid_tileset_dir(const struct tileset
*t
,
957 if (t
->hex_width
> 0) {
958 return dir
!= DIR8_NORTHEAST
&& dir
!= DIR8_SOUTHWEST
;
959 } else if (t
->hex_height
> 0) {
960 return dir
!= DIR8_NORTHWEST
&& dir
!= DIR8_SOUTHEAST
;
966 /****************************************************************************
967 Return TRUE iff the dir is cardinal in this tileset.
969 "Cardinal", in this sense, means that a tile will share a border with
970 another tile in the direction rather than sharing just a single vertex.
971 ****************************************************************************/
972 static bool is_cardinal_tileset_dir(const struct tileset
*t
,
975 if (t
->hex_width
> 0 || t
->hex_height
> 0) {
976 return is_valid_tileset_dir(t
, dir
);
978 return (dir
== DIR8_NORTH
|| dir
== DIR8_EAST
979 || dir
== DIR8_SOUTH
|| dir
== DIR8_WEST
);
983 /**********************************************************************
984 Convert properties of the actual topology to an index of different
985 tileset topology types.
986 ***********************************************************************/
987 static int ts_topology_index(int actual_topology
)
991 if ((actual_topology
& TF_HEX
)
992 && (actual_topology
& TF_ISO
)) {
993 idx
= TS_TOPO_ISOHEX
;
994 } else if (actual_topology
& TF_ISO
) {
996 } else if (actual_topology
& TF_HEX
) {
999 idx
= TS_TOPO_OVERHEAD
;
1005 /**********************************************************************
1006 Returns a static list of tilesets available on the system by
1007 searching all data directories for files matching TILESPEC_SUFFIX.
1008 ***********************************************************************/
1009 const struct strvec
*get_tileset_list(const struct option
*poption
)
1011 static struct strvec
*tilesets
[4] = { NULL
, NULL
, NULL
, NULL
};
1012 int topo
= option_get_cb_data(poption
);
1015 idx
= ts_topology_index(topo
);
1017 fc_assert_ret_val(idx
< ARRAY_SIZE(tilesets
), NULL
);
1019 if (tilesets
[idx
] == NULL
) {
1020 /* Note: this means you must restart the client after installing a new
1022 struct strvec
*list
= fileinfolist(get_data_dirs(), TILESPEC_SUFFIX
);
1024 tilesets
[idx
] = strvec_new();
1025 strvec_iterate(list
, file
) {
1026 struct tileset
*t
= tileset_read_toplevel(file
, FALSE
, topo
, 1.0f
);
1029 strvec_append(tilesets
[idx
], file
);
1032 } strvec_iterate_end
;
1033 strvec_destroy(list
);
1036 return tilesets
[idx
];
1039 /**********************************************************************
1040 Gets full filename for tilespec file, based on input name.
1041 Returned data is allocated, and freed by user as required.
1042 Input name may be null, in which case uses default.
1043 Falls back to default if can't find specified name;
1044 dies if can't find default.
1045 ***********************************************************************/
1046 static char *tilespec_fullname(const char *tileset_name
)
1049 char fname
[strlen(tileset_name
) + strlen(TILESPEC_SUFFIX
) + 1];
1052 fc_snprintf(fname
, sizeof(fname
),
1053 "%s%s", tileset_name
, TILESPEC_SUFFIX
);
1055 dname
= fileinfoname(get_data_dirs(), fname
);
1058 return fc_strdup(dname
);
1065 /**********************************************************************
1066 Checks options in filename match what we require and support.
1068 'which' should be "tilespec" or "spec".
1069 ***********************************************************************/
1070 static bool check_tilespec_capabilities(struct section_file
*file
,
1072 const char *us_capstr
,
1073 const char *filename
,
1076 enum log_level level
= verbose
? LOG_ERROR
: LOG_DEBUG
;
1078 const char *file_capstr
= secfile_lookup_str(file
, "%s.options", which
);
1080 if (NULL
== file_capstr
) {
1081 log_base(level
, "\"%s\": %s file doesn't have a capability string",
1085 if (!has_capabilities(us_capstr
, file_capstr
)) {
1086 log_base(level
, "\"%s\": %s file appears incompatible:",
1088 log_base(level
, " datafile options: %s", file_capstr
);
1089 log_base(level
, " supported options: %s", us_capstr
);
1092 if (!has_capabilities(file_capstr
, us_capstr
)) {
1093 log_base(level
, "\"%s\": %s file requires option(s) "
1094 "that client doesn't support:", filename
, which
);
1095 log_base(level
, " datafile options: %s", file_capstr
);
1096 log_base(level
, " supported options: %s", us_capstr
);
1103 /**********************************************************************
1104 Frees the tilespec toplevel data, in preparation for re-reading it.
1106 See tilespec_read_toplevel().
1107 ***********************************************************************/
1108 static void tileset_free_toplevel(struct tileset
*t
)
1112 if (t
->main_intro_filename
) {
1113 free(t
->main_intro_filename
);
1114 t
->main_intro_filename
= NULL
;
1116 if (t
->minimap_intro_filename
) {
1117 free(t
->minimap_intro_filename
);
1118 t
->minimap_intro_filename
= NULL
;
1121 if (t
->preferred_themes
) {
1122 for (i
= 0; i
< t
->num_preferred_themes
; i
++) {
1123 free(t
->preferred_themes
[i
]);
1125 free(t
->preferred_themes
);
1126 t
->preferred_themes
= NULL
;
1128 t
->num_preferred_themes
= 0;
1131 drawing_hash_destroy(t
->tile_hash
);
1132 t
->tile_hash
= NULL
; /* Helpful for sanity. */
1134 if (t
->estyle_hash
) {
1135 estyle_hash_destroy(t
->estyle_hash
);
1136 t
->estyle_hash
= NULL
;
1138 for (i
= 0; i
< ESTYLE_COUNT
; i
++) {
1139 if (t
->style_lists
[i
] != NULL
) {
1140 extra_type_list_destroy(t
->style_lists
[i
]);
1141 t
->style_lists
[i
] = NULL
;
1145 if (t
->flagged_bases_list
!= NULL
) {
1146 extra_type_list_destroy(t
->flagged_bases_list
);
1147 t
->flagged_bases_list
= NULL
;
1150 for (i
= 0; i
< MAX_NUM_LAYERS
; i
++) {
1151 struct tileset_layer
*tslp
= &t
->layers
[i
];
1153 if (tslp
->match_types
) {
1154 for (j
= 0; j
< tslp
->match_count
; j
++) {
1155 free(tslp
->match_types
[j
]);
1157 free(tslp
->match_types
);
1158 tslp
->match_types
= NULL
;
1162 if (t
->color_system
) {
1163 color_system_free(t
->color_system
);
1164 t
->color_system
= NULL
;
1167 if (t
->summary
!= NULL
) {
1171 if (t
->description
!= NULL
) {
1172 free(t
->description
);
1173 t
->description
= NULL
;
1177 /**************************************************************************
1179 **************************************************************************/
1180 void tileset_free(struct tileset
*t
)
1184 tileset_free_tiles(t
);
1185 tileset_free_toplevel(t
);
1186 for (i
= 0; i
< ARRAY_SIZE(t
->sprites
.player
); i
++) {
1187 tileset_player_free(t
, i
);
1189 specfile_list_destroy(t
->specfiles
);
1190 small_sprite_list_destroy(t
->small_sprites
);
1194 /**********************************************************************
1195 Read a new tilespec in when first starting the game.
1197 Call this function with the (guessed) name of the tileset, when
1198 starting the client.
1199 ***********************************************************************/
1200 void tilespec_try_read(const char *tileset_name
, bool verbose
, int topo_id
,
1201 bool global_default
)
1203 if (tileset_name
== NULL
1204 || !(tileset
= tileset_read_toplevel(tileset_name
, verbose
,
1206 struct strvec
*list
= fileinfolist(get_data_dirs(), TILESPEC_SUFFIX
);
1208 strvec_iterate(list
, file
) {
1209 struct tileset
*t
= tileset_read_toplevel(file
, FALSE
, topo_id
, 1.0f
);
1214 } else if (t
->priority
> tileset
->priority
1216 && tileset_topo_index(tileset
) != tileset_topo_index(t
))) {
1217 tileset_free(tileset
);
1223 } strvec_iterate_end
;
1224 strvec_destroy(list
);
1227 tileset_error(LOG_FATAL
, _("No usable default tileset found, aborting!"));
1230 log_verbose("Trying tileset \"%s\".", tileset
->name
);
1232 option_set_default_ts(tileset
);
1234 if (global_default
) {
1235 sz_strlcpy(gui_options
.default_tileset_name
, tileset_basename(tileset
));
1239 /**********************************************************************
1240 Read a new tilespec in from scratch.
1242 Unlike the initial reading code, which reads pieces one at a time,
1243 this gets rid of the old data and reads in the new all at once. If the
1244 new tileset fails to load the old tileset may be reloaded; otherwise the
1245 client will exit. If a NULL name is given the current tileset will be
1248 It will also call the necessary functions to redraw the graphics.
1249 ***********************************************************************/
1250 void tilespec_reread(const char *new_tileset_name
,
1251 bool game_fully_initialized
, float scale
)
1254 struct tile
*center_tile
;
1255 enum client_states state
= client_state();
1256 const char *name
= new_tileset_name
? new_tileset_name
: tileset
->name
;
1257 char tileset_name
[strlen(name
) + 1], old_name
[strlen(tileset
->name
) + 1];
1259 /* Make local copies since these values may be freed down below */
1260 sz_strlcpy(tileset_name
, name
);
1261 sz_strlcpy(old_name
, tileset
->name
);
1263 log_normal(_("Loading tileset \"%s\"."), tileset_name
);
1265 /* Step 0: Record old data.
1267 * We record the current mapcanvas center, etc.
1269 center_tile
= get_center_tile_mapcanvas();
1273 * We free all old data in preparation for re-reading it.
1275 tileset_free(tileset
);
1279 * We read in the new tileset. This should be pretty straightforward.
1281 if (!(tileset
= tileset_read_toplevel(tileset_name
, FALSE
, -1, scale
))) {
1282 if (!(tileset
= tileset_read_toplevel(old_name
, FALSE
, -1, scale
))) {
1284 fc_assert_exit_msg(NULL
!= tileset
,
1285 "Failed to re-read the currently loaded tileset.");
1288 tileset_load_tiles(tileset
);
1289 if (game_fully_initialized
) {
1290 tileset_use_preferred_theme(tileset
);
1293 if (game_fully_initialized
) {
1294 tileset_background_init(tileset
);
1295 players_iterate(pplayer
) {
1296 tileset_player_init(tileset
, pplayer
);
1297 } players_iterate_end
;
1298 boot_help_texts(); /* "About Current Tileset" */
1303 * This is a seriously sticky problem. On startup, we build a hash
1304 * from all the sprite data. Then, when we connect to a server, the
1305 * server sends us ruleset data a piece at a time and we use this data
1306 * to assemble the sprite structures. But if we change while connected
1307 * we have to reassemble all of these. This should just involve
1308 * calling tilespec_setup_*** on everything. But how do we tell what
1311 * The below code just does things straightforwardly, by setting up
1312 * each possible sprite again. Hopefully it catches everything, and
1313 * doesn't mess up too badly if we change tilesets while not connected
1316 if (!game
.client
.ruleset_ready
) {
1317 /* The ruleset data is not sent until this point. */
1321 if (!tileset_map_topo_compatible(game
.map
.topology_id
, tileset
)) {
1322 tileset_error(LOG_NORMAL
, _("Map topology and tileset incompatible."));
1325 terrain_type_iterate(pterrain
) {
1326 tileset_setup_tile_type(tileset
, pterrain
);
1327 } terrain_type_iterate_end
;
1328 resource_type_iterate(presource
) {
1329 tileset_setup_resource(tileset
, presource
);
1330 } resource_type_iterate_end
;
1331 unit_type_iterate(punittype
) {
1332 tileset_setup_unit_type(tileset
, punittype
);
1333 } unit_type_iterate_end
;
1334 governments_iterate(gov
) {
1335 tileset_setup_government(tileset
, gov
);
1336 } governments_iterate_end
;
1337 extra_type_iterate(pextra
) {
1338 tileset_setup_extra(tileset
, pextra
);
1339 } extra_type_iterate_end
;
1340 nations_iterate(pnation
) {
1341 tileset_setup_nation_flag(tileset
, pnation
);
1342 } nations_iterate_end
;
1343 improvement_iterate(pimprove
) {
1344 tileset_setup_impr_type(tileset
, pimprove
);
1345 } improvement_iterate_end
;
1346 advance_iterate(A_FIRST
, padvance
) {
1347 tileset_setup_tech_type(tileset
, padvance
);
1348 } advance_iterate_end
;
1349 specialist_type_iterate(sp
) {
1350 tileset_setup_specialist_type(tileset
, sp
);
1351 } specialist_type_iterate_end
;
1353 for (id
= 0; id
< game
.control
.styles_count
; id
++) {
1354 tileset_setup_city_tiles(tileset
, id
);
1357 if (state
< C_S_RUNNING
) {
1358 /* Below redraws do not apply before this. */
1364 * Do any necessary redraws.
1366 generate_citydlg_dimensions();
1369 center_tile_mapcanvas(center_tile
);
1370 /* update_map_canvas_visible forces a full redraw. Otherwise with fast
1371 * drawing we might not get one. Of course this is slower. */
1372 update_map_canvas_visible();
1376 /**************************************************************************
1377 This is merely a wrapper for tilespec_reread (above) for use in
1378 options.c and the client local options dialog.
1379 **************************************************************************/
1380 void tilespec_reread_callback(struct option
*poption
)
1382 const char *tileset_name
;
1383 enum client_states state
= client_state();
1385 if ((state
== C_S_RUNNING
|| state
== C_S_OVER
)
1386 && option_get_cb_data(poption
) != (game
.map
.topology_id
& (TF_ISO
| TF_HEX
))) {
1387 /* Changed option was not for current topology */
1391 tileset_name
= option_str_get(poption
);
1393 /* As it's going to be 'current' tileset, make it global default if
1395 sz_strlcpy(gui_options
.default_tileset_name
, tileset_name
);
1397 fc_assert_ret(NULL
!= tileset_name
&& tileset_name
[0] != '\0');
1398 tileset_update
= TRUE
;
1399 tilespec_reread(tileset_name
, client
.conn
.established
, 1.0f
);
1400 tileset_update
= FALSE
;
1404 /**************************************************************************
1406 **************************************************************************/
1407 void tilespec_reread_frozen_refresh(const char *tname
)
1409 tileset_update
= TRUE
;
1410 tilespec_reread(tname
, TRUE
, 1.0f
);
1411 tileset_update
= FALSE
;
1415 /**************************************************************************
1416 Loads the given graphics file (found in the data path) into a newly
1418 **************************************************************************/
1419 static struct sprite
*load_gfx_file(const char *gfx_filename
)
1421 const char **gfx_fileexts
= gfx_fileextensions(), *gfx_fileext
;
1424 /* Try out all supported file extensions to find one that works. */
1425 while ((gfx_fileext
= *gfx_fileexts
++)) {
1426 const char *real_full_name
;
1427 char full_name
[strlen(gfx_filename
) + strlen(".")
1428 + strlen(gfx_fileext
) + 1];
1430 sprintf(full_name
, "%s.%s", gfx_filename
, gfx_fileext
);
1431 if ((real_full_name
= fileinfoname(get_data_dirs(), full_name
))) {
1432 log_debug("trying to load gfx file \"%s\".", real_full_name
);
1433 s
= load_gfxfile(real_full_name
);
1440 log_error("Could not load gfx file \"%s\".", gfx_filename
);
1444 /**************************************************************************
1445 Ensure that the big sprite of the given spec file is loaded.
1446 **************************************************************************/
1447 static void ensure_big_sprite(struct specfile
*sf
)
1449 struct section_file
*file
;
1450 const char *gfx_filename
;
1452 if (sf
->big_sprite
) {
1453 /* Looks like it's already loaded. */
1457 /* Otherwise load it. The big sprite will sometimes be freed and will have
1458 * to be reloaded, but most of the time it's just loaded once, the small
1459 * sprites are extracted, and then it's freed. */
1460 if (!(file
= secfile_load(sf
->file_name
, TRUE
))) {
1461 tileset_error(LOG_FATAL
, _("Could not open '%s':\n%s"), sf
->file_name
, secfile_error());
1464 if (!check_tilespec_capabilities(file
, "spec",
1465 SPEC_CAPSTR
, sf
->file_name
, TRUE
)) {
1466 tileset_error(LOG_FATAL
, _("Incompatible tileset capabilities"));
1469 gfx_filename
= secfile_lookup_str(file
, "file.gfx");
1471 sf
->big_sprite
= load_gfx_file(gfx_filename
);
1473 if (!sf
->big_sprite
) {
1474 tileset_error(LOG_FATAL
, _("Could not load gfx file for the spec file \"%s\"."),
1477 secfile_destroy(file
);
1480 /**************************************************************************
1481 Scan all sprites declared in the given specfile. This means that the
1482 positions of the sprites in the big_sprite are saved in the
1483 small_sprite structs.
1484 **************************************************************************/
1485 static void scan_specfile(struct tileset
*t
, struct specfile
*sf
,
1488 struct section_file
*file
;
1489 struct section_list
*sections
;
1492 if (!(file
= secfile_load(sf
->file_name
, TRUE
))) {
1493 tileset_error(LOG_FATAL
, _("Could not open '%s':\n%s"), sf
->file_name
, secfile_error());
1495 if (!check_tilespec_capabilities(file
, "spec",
1496 SPEC_CAPSTR
, sf
->file_name
, TRUE
)) {
1497 tileset_error(LOG_FATAL
, _("Specfile %s has incompatible capabilities"), sf
->file_name
);
1500 /* Currently unused */
1501 (void) secfile_entry_lookup(file
, "info.artists");
1504 (void) secfile_entry_lookup(file
, "file.gfx");
1506 if ((sections
= secfile_sections_by_name_prefix(file
, "grid_"))) {
1507 section_list_iterate(sections
, psection
) {
1509 int x_top_left
, y_top_left
, dx
, dy
;
1512 const char *sec_name
= section_name(psection
);
1514 pixel_border_x
= secfile_lookup_int_default(file
, 0, "%s.pixel_border",
1516 pixel_border_y
= secfile_lookup_int_default(file
, pixel_border_x
, "%s.pixel_border_y",
1518 pixel_border_x
= secfile_lookup_int_default(file
, pixel_border_x
, "%s.pixel_border_x",
1520 if (!secfile_lookup_int(file
, &x_top_left
, "%s.x_top_left", sec_name
)
1521 || !secfile_lookup_int(file
, &y_top_left
,
1522 "%s.y_top_left", sec_name
)
1523 || !secfile_lookup_int(file
, &dx
, "%s.dx", sec_name
)
1524 || !secfile_lookup_int(file
, &dy
, "%s.dy", sec_name
)) {
1525 log_error("Grid \"%s\" invalid: %s", sec_name
, secfile_error());
1530 while (NULL
!= secfile_entry_lookup(file
, "%s.tiles%d.tag",
1532 struct small_sprite
*ss
;
1539 if (!secfile_lookup_int(file
, &row
, "%s.tiles%d.row", sec_name
, j
)
1540 || !secfile_lookup_int(file
, &column
, "%s.tiles%d.column",
1542 || !(tags
= secfile_lookup_str_vec(file
, &num_tags
,
1545 log_error("Small sprite \"%s.tiles%d\" invalid: %s",
1546 sec_name
, j
, secfile_error());
1549 hot_x
= secfile_lookup_int_default(file
, 0, "%s.tiles%d.hot_x",
1551 hot_y
= secfile_lookup_int_default(file
, 0, "%s.tiles%d.hot_y",
1554 /* there must be at least 1 because of the while(): */
1555 fc_assert_action(num_tags
> 0, continue);
1557 xr
= x_top_left
+ (dx
+ pixel_border_x
) * column
;
1558 yb
= y_top_left
+ (dy
+ pixel_border_y
) * row
;
1560 ss
= fc_malloc(sizeof(*ss
));
1572 small_sprite_list_prepend(t
->small_sprites
, ss
);
1574 if (!duplicates_ok
) {
1575 for (k
= 0; k
< num_tags
; k
++) {
1576 if (!sprite_hash_insert(t
->sprite_hash
, tags
[k
], ss
)) {
1577 log_error("warning: already have a sprite for \"%s\".",
1582 for (k
= 0; k
< num_tags
; k
++) {
1583 (void) sprite_hash_replace(t
->sprite_hash
, tags
[k
], ss
);
1590 } section_list_iterate_end
;
1591 section_list_destroy(sections
);
1594 /* Load "extra" sprites. Each sprite is one file. */
1596 while (NULL
!= secfile_entry_lookup(file
, "extra.sprites%d.tag", ++i
)) {
1597 struct small_sprite
*ss
;
1599 const char *filename
;
1603 if (!(tags
= secfile_lookup_str_vec(file
, &num_tags
,
1604 "extra.sprites%d.tag", i
))
1605 || !(filename
= secfile_lookup_str(file
,
1606 "extra.sprites%d.file", i
))) {
1607 log_error("Extra sprite \"extra.sprites%d\" invalid: %s",
1608 i
, secfile_error());
1611 hot_x
= secfile_lookup_int_default(file
, 0, "extra.sprites%d.hot_x", i
);
1612 hot_y
= secfile_lookup_int_default(file
, 0, "extra.sprites%d.hot_y", i
);
1614 ss
= fc_malloc(sizeof(*ss
));
1616 ss
->file
= fc_strdup(filename
);
1622 small_sprite_list_prepend(t
->small_sprites
, ss
);
1624 if (!duplicates_ok
) {
1625 for (k
= 0; k
< num_tags
; k
++) {
1626 if (!sprite_hash_insert(t
->sprite_hash
, tags
[k
], ss
)) {
1627 log_error("warning: already have a sprite for \"%s\".", tags
[k
]);
1631 for (k
= 0; k
< num_tags
; k
++) {
1632 (void) sprite_hash_replace(t
->sprite_hash
, tags
[k
], ss
);
1638 secfile_check_unused(file
);
1639 secfile_destroy(file
);
1642 /**********************************************************************
1643 Returns the correct name of the gfx file (with path and extension)
1644 Must be free'd when no longer used
1645 ***********************************************************************/
1646 static char *tilespec_gfx_filename(const char *gfx_filename
)
1648 const char *gfx_current_fileext
;
1649 const char **gfx_fileexts
= gfx_fileextensions();
1651 while ((gfx_current_fileext
= *gfx_fileexts
++)) {
1652 const char *real_full_name
;
1654 fc_malloc(strlen(gfx_filename
) + strlen(".")
1655 + strlen(gfx_current_fileext
) + 1);
1657 sprintf(full_name
, "%s.%s", gfx_filename
, gfx_current_fileext
);
1659 real_full_name
= fileinfoname(get_data_dirs(), full_name
);
1661 if (real_full_name
) {
1662 return fc_strdup(real_full_name
);
1666 tileset_error(LOG_FATAL
, _("Couldn't find a supported gfx file extension for \"%s\"."),
1672 /**********************************************************************
1673 Determine the sprite_type string.
1674 ***********************************************************************/
1675 static int check_sprite_type(const char *sprite_type
, const char *tile_section
)
1677 if (fc_strcasecmp(sprite_type
, "corner") == 0) {
1680 if (fc_strcasecmp(sprite_type
, "single") == 0) {
1683 if (fc_strcasecmp(sprite_type
, "whole") == 0) {
1686 log_error("[%s] unknown sprite_type \"%s\".", tile_section
, sprite_type
);
1690 /**********************************************************************
1691 Finds and reads the toplevel tilespec file based on given name.
1692 Sets global variables, including tile sizes and full names for
1694 topology_id of -1 means any topology is acceptable.
1695 ***********************************************************************/
1696 struct tileset
*tileset_read_toplevel(const char *tileset_name
, bool verbose
,
1697 int topology_id
, float scale
)
1699 struct section_file
*file
;
1703 size_t num_spec_files
;
1704 const char **spec_filenames
;
1705 size_t num_preferred_themes
;
1706 struct section_list
*sections
= NULL
;
1707 const char *file_capstr
;
1708 bool duplicates_ok
, is_hex
;
1709 enum direction8 dir
;
1710 struct tileset
*t
= NULL
;
1711 const char *extraname
;
1715 fname
= tilespec_fullname(tileset_name
);
1718 log_error("Can't find tileset \"%s\".", tileset_name
);
1722 log_verbose("tilespec file is \"%s\".", fname
);
1724 if (!(file
= secfile_load(fname
, TRUE
))) {
1725 log_error("Could not open '%s':\n%s", fname
, secfile_error());
1730 if (!check_tilespec_capabilities(file
, "tilespec",
1731 TILESPEC_CAPSTR
, fname
, verbose
)) {
1732 secfile_destroy(file
);
1739 file_capstr
= secfile_lookup_str(file
, "%s.options", "tilespec");
1740 duplicates_ok
= (NULL
!= file_capstr
1741 && has_capabilities("+duplicates_ok", file_capstr
));
1743 tstr
= secfile_lookup_str(file
, "tilespec.name");
1744 /* Tileset name found */
1745 sz_strlcpy(t
->given_name
, tstr
);
1746 tstr
= secfile_lookup_str_default(file
, "", "tilespec.version");
1747 if (tstr
[0] != '\0') {
1748 /* Tileset version found */
1749 sz_strlcpy(t
->version
, tstr
);
1751 /* No version information */
1752 t
->version
[0] = '\0';
1755 tstr
= secfile_lookup_str_default(file
, "", "tilespec.summary");
1756 if (tstr
[0] != '\0') {
1759 /* Tileset summary found */
1761 t
->summary
= fc_malloc(len
+ 1);
1762 fc_strlcpy(t
->summary
, tstr
, len
+ 1);
1765 if (t
->summary
!= NULL
) {
1771 tstr
= secfile_lookup_str_default(file
, "", "tilespec.description");
1772 if (tstr
[0] != '\0') {
1775 /* Tileset description found */
1777 t
->description
= fc_malloc(len
+ 1);
1778 fc_strlcpy(t
->description
, tstr
, len
+ 1);
1780 /* No description */
1781 if (t
->description
!= NULL
) {
1782 free(t
->description
);
1783 t
->description
= NULL
;
1787 sz_strlcpy(t
->name
, tileset_name
);
1788 if (!secfile_lookup_int(file
, &t
->priority
, "tilespec.priority")
1789 || !secfile_lookup_bool(file
, &is_hex
, "tilespec.is_hex")) {
1790 log_error("Tileset \"%s\" invalid: %s", t
->name
, secfile_error());
1794 tstr
= secfile_lookup_str(file
, "tilespec.type");
1796 log_error("Tileset \"%s\": no tileset type", t
->name
);
1800 t
->type
= ts_type_by_name(tstr
, fc_strcasecmp
);
1801 if (!ts_type_is_valid(t
->type
)) {
1802 log_error("Tileset \"%s\": unknown tileset type \"%s\"", t
->name
, tstr
);
1806 if (t
->type
== TS_ISOMETRIC
) {
1812 if (t
->type
== TS_ISOMETRIC
) {
1818 /* Read hex-tileset information. */
1819 t
->hex_width
= t
->hex_height
= 0;
1823 if (!secfile_lookup_int(file
, &hex_side
, "tilespec.hex_side")) {
1824 log_error("Tileset \"%s\" invalid: %s", t
->name
, secfile_error());
1827 hex_side
= hex_side
* t
->scale
;
1828 if (t
->type
== TS_ISOMETRIC
) {
1829 t
->hex_width
= hex_side
;
1831 t
->hex_height
= hex_side
;
1836 /* Hex tilesets are drawn the same as isometric. */
1837 /* FIXME: There will be other legal values to be used with hex
1838 * tileset in the future, and this would just overwrite it. */
1839 t
->type
= TS_ISOMETRIC
;
1842 if (topology_id
>= 0 && topo
!= (topology_id
& (TF_ISO
| TF_HEX
))) {
1843 /* Not of requested topology */
1847 t
->ts_topo_idx
= ts_topology_index(topo
);
1849 if (!is_view_supported(t
->type
)) {
1850 log_normal(_("Client does not support %s tilesets."),
1851 _(ts_type_name(t
->type
)));
1852 log_normal(_("Using default tileset instead."));
1853 fc_assert(tileset_name
!= NULL
);
1857 /* Create arrays of valid and cardinal tileset dirs. These depend
1858 * entirely on the tileset, not the topology. They are also in clockwise
1859 * rotational ordering. */
1860 t
->num_valid_tileset_dirs
= t
->num_cardinal_tileset_dirs
= 0;
1863 if (is_valid_tileset_dir(t
, dir
)) {
1864 t
->valid_tileset_dirs
[t
->num_valid_tileset_dirs
] = dir
;
1865 t
->num_valid_tileset_dirs
++;
1867 if (is_cardinal_tileset_dir(t
, dir
)) {
1868 t
->cardinal_tileset_dirs
[t
->num_cardinal_tileset_dirs
] = dir
;
1869 t
->num_cardinal_tileset_dirs
++;
1873 } while (dir
!= DIR8_NORTH
);
1874 fc_assert(t
->num_valid_tileset_dirs
% 2 == 0); /* Assumed elsewhere. */
1875 t
->num_index_valid
= 1 << t
->num_valid_tileset_dirs
;
1876 t
->num_index_cardinal
= 1 << t
->num_cardinal_tileset_dirs
;
1878 if (!secfile_lookup_int(file
, &t
->normal_tile_width
,
1879 "tilespec.normal_tile_width")
1880 || !secfile_lookup_int(file
, &t
->normal_tile_height
,
1881 "tilespec.normal_tile_height")) {
1882 log_error("Tileset \"%s\" invalid: %s", t
->name
, secfile_error());
1885 t
->normal_tile_width
= ceil(t
->scale
* t
->normal_tile_width
);
1886 // Adjust width to be multiple of 8
1887 if (scale
!= 1.0f
) {
1888 i
= t
->normal_tile_width
;
1889 while (i
% 8 != 0) {
1892 t
->scale
= (t
->scale
* i
) / t
->normal_tile_width
;
1893 t
->normal_tile_width
= i
;
1895 t
->normal_tile_height
= ceil(t
->scale
* t
->normal_tile_height
);
1896 if (t
->type
== TS_ISOMETRIC
) {
1897 t
->full_tile_width
= t
->normal_tile_width
;
1898 if (tileset_hex_height(t
) > 0) {
1899 t
->full_tile_height
= t
->normal_tile_height
;
1901 t
->full_tile_height
= 3 * t
->normal_tile_height
/ 2;
1904 t
->full_tile_width
= t
->normal_tile_width
;
1905 t
->full_tile_height
= t
->normal_tile_height
;
1908 = secfile_lookup_int_default(file
, t
->full_tile_width
, "tilespec.unit_width");
1910 = secfile_lookup_int_default(file
, t
->full_tile_height
, "tilespec.unit_height");
1911 if (!secfile_lookup_int(file
, &t
->small_sprite_width
,
1912 "tilespec.small_tile_width")
1913 || !secfile_lookup_int(file
, &t
->small_sprite_height
,
1914 "tilespec.small_tile_height")) {
1915 log_error("Tileset \"%s\" invalid: %s", t
->name
, secfile_error());
1918 if (t
->unit_tile_width
!= t
->full_tile_width
&& t
->scale
!= 1.0f
) {
1919 t
->unit_tile_width
= ceil(t
->unit_tile_width
* t
->scale
);
1921 if (t
->unit_tile_height
!= t
->full_tile_height
&& t
->scale
!= 1.0f
) {
1922 t
->unit_tile_height
= ceil(t
->unit_tile_height
* t
->scale
);
1924 t
->small_sprite_width
= t
->small_sprite_width
* t
->scale
;
1925 t
->small_sprite_height
= t
->small_sprite_height
* t
->scale
;
1926 log_verbose("tile sizes %dx%d, %d%d unit, %d%d small",
1927 t
->normal_tile_width
, t
->normal_tile_height
,
1928 t
->full_tile_width
, t
->full_tile_height
,
1929 t
->small_sprite_width
, t
->small_sprite_height
);
1931 tstr
= secfile_lookup_str(file
, "tilespec.fog_style");
1933 log_error("Tileset \"%s\": no fog_style", t
->name
);
1937 t
->fogstyle
= fog_style_by_name(tstr
, fc_strcasecmp
);
1938 if (!fog_style_is_valid(t
->fogstyle
)) {
1939 log_error("Tileset \"%s\": unknown fog_style \"%s\"", t
->name
, tstr
);
1943 tstr
= secfile_lookup_str(file
, "tilespec.darkness_style");
1945 log_error("Tileset \"%s\": no darkness_style", t
->name
);
1949 t
->darkness_style
= darkness_style_by_name(tstr
, fc_strcasecmp
);
1950 if (!darkness_style_is_valid(t
->darkness_style
)) {
1951 log_error("Tileset \"%s\": unknown darkness_style \"%s\"", t
->name
, tstr
);
1955 if (t
->darkness_style
== DARKNESS_ISORECT
1956 && (t
->type
== TS_OVERHEAD
|| t
->hex_width
> 0 || t
->hex_height
> 0)) {
1957 log_error("Invalid darkness style set in tileset \"%s\".", t
->name
);
1960 t
->darkness_layer
= secfile_lookup_int_default(file
, 0, "tilespec.darkness_layer");
1961 if (t
->darkness_layer
< 0 || t
->darkness_layer
>= TERRAIN_LAYER_COUNT
) {
1962 tileset_error(LOG_ERROR
, "Invalid darkness layer %d in tileset \"%s\"",
1963 t
->darkness_layer
, t
->name
);
1967 if (!secfile_lookup_int(file
, &t
->unit_flag_offset_x
,
1968 "tilespec.unit_flag_offset_x")
1969 || !secfile_lookup_int(file
, &t
->unit_flag_offset_y
,
1970 "tilespec.unit_flag_offset_y")
1971 || !secfile_lookup_int(file
, &t
->city_flag_offset_x
,
1972 "tilespec.city_flag_offset_x")
1973 || !secfile_lookup_int(file
, &t
->city_flag_offset_y
,
1974 "tilespec.city_flag_offset_y")
1975 || !secfile_lookup_int(file
, &t
->unit_offset_x
,
1976 "tilespec.unit_offset_x")
1977 || !secfile_lookup_int(file
, &t
->unit_offset_y
,
1978 "tilespec.unit_offset_y")
1979 || !secfile_lookup_int(file
, &t
->activity_offset_x
,
1980 "tilespec.activity_offset_x")
1981 || !secfile_lookup_int(file
, &t
->activity_offset_y
,
1982 "tilespec.activity_offset_y")
1983 || !secfile_lookup_int(file
, &t
->city_offset_x
,
1984 "tilespec.city_offset_x")
1985 || !secfile_lookup_int(file
, &t
->city_offset_y
,
1986 "tilespec.city_offset_y")
1987 || !secfile_lookup_int(file
, &t
->citybar_offset_y
,
1988 "tilespec.citybar_offset_y")
1989 || !secfile_lookup_int(file
, &t
->tilelabel_offset_y
,
1990 "tilespec.tilelabel_offset_y")
1991 || !secfile_lookup_int(file
, &t
->occupied_offset_x
,
1992 "tilespec.occupied_offset_x")
1993 || !secfile_lookup_int(file
, &t
->occupied_offset_y
,
1994 "tilespec.occupied_offset_y")
1995 || !secfile_lookup_int(file
, &t
->city_names_font_size
,
1996 "tilespec.city_names_font_size")
1997 || !secfile_lookup_int(file
, &t
->city_productions_font_size
,
1998 "tilespec.city_productions_font_size")) {
1999 log_error("Tileset \"%s\" invalid: %s", t
->name
, secfile_error());
2003 t
->unit_upkeep_offset_y
= secfile_lookup_int_default(file
, tileset_tile_height(t
),
2004 "tilespec.unit_upkeep_offset_y");
2005 t
->unit_upkeep_small_offset_y
= secfile_lookup_int_default(file
, t
->unit_upkeep_offset_y
,
2006 "tilespec.unit_upkeep_small_offset_y");
2007 t
->unit_flag_offset_x
= t
->scale
* t
->unit_flag_offset_x
;
2008 t
->unit_flag_offset_y
= t
->scale
* t
->unit_flag_offset_y
;
2009 t
->city_flag_offset_x
= t
->scale
* t
->city_flag_offset_x
;
2010 t
->city_flag_offset_y
= t
->scale
* t
->city_flag_offset_y
;
2011 t
->unit_offset_x
= t
->scale
* t
->unit_offset_x
;
2012 t
->unit_offset_y
= t
->scale
* t
->unit_offset_y
;
2013 t
->activity_offset_x
= t
->scale
* t
->activity_offset_x
;
2014 t
->activity_offset_y
= t
->scale
* t
->activity_offset_y
;
2015 t
->city_offset_x
= t
->scale
* t
->city_offset_x
;
2016 t
->city_offset_y
= t
->scale
* t
->city_offset_y
;
2017 t
->citybar_offset_y
= t
->scale
* t
->citybar_offset_y
;
2018 t
->tilelabel_offset_y
= t
->scale
* t
->tilelabel_offset_y
;
2019 t
->occupied_offset_x
= t
->scale
* t
->occupied_offset_x
;
2020 t
->occupied_offset_y
= t
->scale
* t
->occupied_offset_y
;
2021 if (t
->scale
!= 1.0f
2022 && t
->unit_upkeep_offset_y
!= tileset_tile_height(t
)) {
2023 t
->unit_upkeep_offset_y
= t
->scale
* t
->unit_upkeep_offset_y
;
2025 if (t
->scale
!= 1.0f
2026 && t
->unit_upkeep_small_offset_y
!= t
->unit_upkeep_offset_y
) {
2027 t
->unit_upkeep_small_offset_y
= t
->scale
* t
->unit_upkeep_small_offset_y
;
2029 set_city_names_font_sizes(t
->city_names_font_size
,
2030 t
->city_productions_font_size
);
2032 c
= secfile_lookup_str(file
, "tilespec.main_intro_file");
2033 t
->main_intro_filename
= tilespec_gfx_filename(c
);
2034 log_debug("intro file %s", t
->main_intro_filename
);
2036 c
= secfile_lookup_str_default(file
, NULL
, "tilespec.minimap_intro_file");
2038 t
->minimap_intro_filename
= NULL
;
2040 t
->minimap_intro_filename
= tilespec_gfx_filename(c
);
2041 log_debug("radar file %s", t
->minimap_intro_filename
);
2044 /* Terrain layer info. */
2045 for (i
= 0; i
< MAX_NUM_LAYERS
; i
++) {
2046 struct tileset_layer
*tslp
= &t
->layers
[i
];
2050 (char **) secfile_lookup_str_vec(file
, &tslp
->match_count
,
2051 "layer%d.match_types", i
);
2052 for (j
= 0; j
< tslp
->match_count
; j
++) {
2053 tslp
->match_types
[j
] = fc_strdup(tslp
->match_types
[j
]);
2055 for (k
= 0; k
< j
; k
++) {
2056 if (tslp
->match_types
[k
][0] == tslp
->match_types
[j
][0]) {
2057 tileset_error(LOG_FATAL
, _("[layer%d] match_types: \"%s\" initial "
2058 "('%c') is not unique."),
2059 i
, tslp
->match_types
[j
], tslp
->match_types
[j
][0]);
2060 /* FIXME: Returns NULL. */
2066 /* Tile drawing info. */
2067 sections
= secfile_sections_by_name_prefix(file
, TILE_SECTION_PREFIX
);
2068 if (NULL
== sections
|| 0 == section_list_size(sections
)) {
2069 tileset_error(LOG_ERROR
, _("No [%s] sections supported by tileset \"%s\"."),
2070 TILE_SECTION_PREFIX
, fname
);
2074 fc_assert(t
->tile_hash
== NULL
);
2075 t
->tile_hash
= drawing_hash_new();
2077 section_list_iterate(sections
, psection
) {
2078 const char *sec_name
= section_name(psection
);
2079 struct drawing_data
*draw
= drawing_data_new();
2080 const char *sprite_type
;
2082 const char *terrain_name
;
2084 terrain_name
= secfile_lookup_str(file
, "%s.tag", sec_name
);
2086 if (terrain_name
!= NULL
) {
2087 draw
->name
= fc_strdup(terrain_name
);
2089 tileset_error(LOG_ERROR
, _("No terrain tag given in section [%s]."), sec_name
);
2090 drawing_data_destroy(draw
);
2094 draw
->blending
= secfile_lookup_int_default(file
, 0, "%s.blend_layer",
2096 draw
->blending
= CLIP(0, draw
->blending
, MAX_NUM_LAYERS
);
2098 draw
->is_reversed
= secfile_lookup_bool_default(file
, FALSE
,
2101 draw
->num_layers
= secfile_lookup_int_default(file
, 0, "%s.num_layers",
2103 draw
->num_layers
= CLIP(1, draw
->num_layers
, MAX_NUM_LAYERS
);
2105 for (l
= 0; l
< draw
->num_layers
; l
++) {
2106 struct drawing_layer
*dlp
= &draw
->layer
[l
];
2107 struct tileset_layer
*tslp
= &t
->layers
[l
];
2108 const char *match_type
;
2109 const char **match_with
;
2113 = secfile_lookup_bool_default(file
, FALSE
, "%s.layer%d_is_tall",
2116 = secfile_lookup_int_default(file
, 0, "%s.layer%d_offset_x",
2119 = secfile_lookup_int_default(file
, 0, "%s.layer%d_offset_y",
2121 dlp
->offset_x
= ceil(t
->scale
* dlp
->offset_x
);
2122 dlp
->offset_y
= ceil(t
->scale
* dlp
->offset_y
);
2124 match_type
= secfile_lookup_str_default(file
, NULL
,
2125 "%s.layer%d_match_type",
2130 /* Determine our match_type. */
2131 for (j
= 0; j
< tslp
->match_count
; j
++) {
2132 if (fc_strcasecmp(tslp
->match_types
[j
], match_type
) == 0) {
2136 if (j
>= tslp
->match_count
) {
2137 log_error("[%s] invalid match_type \"%s\".", sec_name
, match_type
);
2139 dlp
->match_index
[dlp
->match_indices
++] = j
;
2143 match_with
= secfile_lookup_str_vec(file
, &count
,
2144 "%s.layer%d_match_with",
2149 if (count
> MAX_NUM_MATCH_WITH
) {
2150 log_error("[%s] match_with has too many types (%d, max %d)",
2151 sec_name
, (int) count
, MAX_NUM_MATCH_WITH
);
2152 count
= MAX_NUM_MATCH_WITH
;
2155 if (1 < dlp
->match_indices
) {
2156 log_error("[%s] previous match_with ignored.", sec_name
);
2157 dlp
->match_indices
= 1;
2158 } else if (1 > dlp
->match_indices
) {
2159 log_error("[%s] missing match_type, using \"%s\".",
2160 sec_name
, tslp
->match_types
[0]);
2161 dlp
->match_index
[0] = 0;
2162 dlp
->match_indices
= 1;
2165 for (k
= 0; k
< count
; k
++) {
2166 for (j
= 0; j
< tslp
->match_count
; j
++) {
2167 if (fc_strcasecmp(tslp
->match_types
[j
], match_with
[k
]) == 0) {
2171 if (j
>= tslp
->match_count
) {
2172 log_error("[%s] layer%d_match_with: invalid \"%s\".",
2173 sec_name
, l
, match_with
[k
]);
2174 } else if (1 < count
) {
2177 for (m
= 0; m
< dlp
->match_indices
; m
++) {
2178 if (dlp
->match_index
[m
] == j
) {
2179 log_error("[%s] layer%d_match_with: duplicate \"%s\".",
2180 sec_name
, l
, match_with
[k
]);
2184 if (m
>= dlp
->match_indices
) {
2185 dlp
->match_index
[dlp
->match_indices
++] = j
;
2188 dlp
->match_index
[dlp
->match_indices
++] = j
;
2195 /* Check match_indices */
2196 switch (dlp
->match_indices
) {
2199 dlp
->match_style
= MATCH_NONE
;
2202 if (dlp
->match_index
[0] == dlp
->match_index
[1] ) {
2203 dlp
->match_style
= MATCH_SAME
;
2205 dlp
->match_style
= MATCH_PAIR
;
2209 dlp
->match_style
= MATCH_FULL
;
2214 = secfile_lookup_str_default(file
, "whole", "%s.layer%d_sprite_type",
2216 dlp
->sprite_type
= check_sprite_type(sprite_type
, sec_name
);
2218 switch (dlp
->sprite_type
) {
2220 /* OK, no problem */
2224 || dlp
->offset_x
> 0
2225 || dlp
->offset_y
> 0) {
2226 log_error("[%s] layer %d: you cannot have tall terrain or\n"
2227 "a sprite offset with a cell-based drawing method.",
2229 dlp
->is_tall
= FALSE
;
2230 dlp
->offset_x
= dlp
->offset_y
= 0;
2236 if (!drawing_hash_insert(t
->tile_hash
, draw
->name
, draw
)) {
2237 log_error("warning: multiple tile sections containing terrain tag \"%s\".",
2241 } section_list_iterate_end
;
2242 section_list_destroy(sections
);
2245 t
->estyle_hash
= estyle_hash_new();
2247 for (i
= 0; i
< ESTYLE_COUNT
; i
++) {
2248 t
->style_lists
[i
] = extra_type_list_new();
2250 t
->flagged_bases_list
= extra_type_list_new();
2252 for (i
= 0; (extraname
= secfile_lookup_str_default(file
, NULL
,
2253 "extras.styles%d.name",
2255 const char *style_name
;
2256 enum extrastyle_id style
;
2258 style_name
= secfile_lookup_str_default(file
, "Single1",
2259 "extras.styles%d.style", i
);
2260 style
= extrastyle_id_by_name(style_name
, fc_strcasecmp
);
2261 if (!extrastyle_id_is_valid(style
)) {
2262 log_error("Unknown extra style \"%s\" for road \"%s\"",
2263 style_name
, extraname
);
2267 if (!estyle_hash_insert(t
->estyle_hash
, extraname
, style
)) {
2268 log_error("warning: duplicate extrastyle entry [%s].", extraname
);
2273 spec_filenames
= secfile_lookup_str_vec(file
, &num_spec_files
,
2275 if (NULL
== spec_filenames
|| 0 == num_spec_files
) {
2276 log_error("No tile graphics files specified in \"%s\"", fname
);
2280 fc_assert(t
->sprite_hash
== NULL
);
2281 t
->sprite_hash
= sprite_hash_new();
2282 for (i
= 0; i
< num_spec_files
; i
++) {
2283 struct specfile
*sf
= fc_malloc(sizeof(*sf
));
2286 log_debug("spec file %s", spec_filenames
[i
]);
2288 sf
->big_sprite
= NULL
;
2289 dname
= fileinfoname(get_data_dirs(), spec_filenames
[i
]);
2292 log_error("Can't find spec file \"%s\".", spec_filenames
[i
]);
2296 sf
->file_name
= fc_strdup(dname
);
2297 scan_specfile(t
, sf
, duplicates_ok
);
2299 specfile_list_prepend(t
->specfiles
, sf
);
2301 free(spec_filenames
);
2303 t
->color_system
= color_system_read(file
);
2305 /* FIXME: remove this hack. */
2306 t
->preferred_themes
=
2307 (char **) secfile_lookup_str_vec(file
, &num_preferred_themes
,
2308 "tilespec.preferred_themes");
2309 if (num_preferred_themes
<= 0) {
2310 t
->preferred_themes
=
2311 (char **) secfile_lookup_str_vec(file
, &num_preferred_themes
,
2312 "tilespec.prefered_themes");
2313 if (num_preferred_themes
> 0) {
2314 log_deprecation("Entry tilespec.prefered_themes in tilespec."
2315 " Use correct spelling tilespec.preferred_themes instead");
2318 t
->num_preferred_themes
= num_preferred_themes
;
2319 for (i
= 0; i
< t
->num_preferred_themes
; i
++) {
2320 t
->preferred_themes
[i
] = fc_strdup(t
->preferred_themes
[i
]);
2323 secfile_check_unused(file
);
2324 secfile_destroy(file
);
2325 log_verbose("finished reading \"%s\".", fname
);
2331 secfile_destroy(file
);
2334 if (NULL
!= sections
) {
2335 section_list_destroy(sections
);
2340 /**********************************************************************
2341 Returns a text name for the citizen, as used in the tileset.
2342 ***********************************************************************/
2343 static const char *citizen_rule_name(enum citizen_category citizen
)
2345 /* These strings are used in reading the tileset. Do not
2350 case CITIZEN_CONTENT
:
2352 case CITIZEN_UNHAPPY
:
2359 log_error("Unknown citizen type: %d.", (int) citizen
);
2363 /****************************************************************************
2364 Return a directional string for the cardinal directions. Normally the
2365 binary value 1000 will be converted into "n1e0s0w0". This is in a
2367 ****************************************************************************/
2368 static const char *cardinal_index_str(const struct tileset
*t
, int idx
)
2374 for (i
= 0; i
< t
->num_cardinal_tileset_dirs
; i
++) {
2375 int value
= (idx
>> i
) & 1;
2377 cat_snprintf(c
, sizeof(c
), "%s%d",
2378 dir_get_tileset_name(t
->cardinal_tileset_dirs
[i
]), value
);
2384 /****************************************************************************
2385 Do the same thing as cardinal_str, except including all valid directions.
2386 The returned string is a pointer to static memory.
2387 ****************************************************************************/
2388 static char *valid_index_str(const struct tileset
*t
, int idx
)
2394 for (i
= 0; i
< t
->num_valid_tileset_dirs
; i
++) {
2395 int value
= (idx
>> i
) & 1;
2397 cat_snprintf(c
, sizeof(c
), "%s%d",
2398 dir_get_tileset_name(t
->valid_tileset_dirs
[i
]), value
);
2404 /**************************************************************************
2405 Loads the sprite. If the sprite is already loaded a reference
2406 counter is increased. Can return NULL if the sprite couldn't be
2408 Scale means if sprite should be scaled, smooth if scaling might use
2409 other scaling algorithm than nearest neighbor.
2410 **************************************************************************/
2411 static struct sprite
*load_sprite(struct tileset
*t
, const char *tag_name
,
2412 bool scale
, bool smooth
)
2414 struct small_sprite
*ss
;
2415 float sprite_scale
= 1.0f
;
2417 log_debug("load_sprite(tag='%s')", tag_name
);
2418 /* Lookup information about where the sprite is found. */
2419 if (!sprite_hash_lookup(t
->sprite_hash
, tag_name
, &ss
)) {
2423 fc_assert(ss
->ref_count
>= 0);
2426 /* If the sprite hasn't been loaded already, then load it. */
2427 fc_assert(ss
->ref_count
== 0);
2433 s
= load_gfx_file(ss
->file
);
2434 get_sprite_dimensions(s
, &w
, &h
);
2435 ss
->sprite
= crop_sprite(s
, 0, 0, w
,
2436 h
, NULL
, -1, -1, t
->scale
, smooth
);
2439 ss
->sprite
= load_gfx_file(ss
->file
);
2442 tileset_error(LOG_FATAL
, _("Couldn't load gfx file \"%s\" for sprite '%s'."),
2443 ss
->file
, tag_name
);
2448 ensure_big_sprite(ss
->sf
);
2449 get_sprite_dimensions(ss
->sf
->big_sprite
, &sf_w
, &sf_h
);
2450 if (ss
->x
< 0 || ss
->x
+ ss
->width
> sf_w
2451 || ss
->y
< 0 || ss
->y
+ ss
->height
> sf_h
) {
2452 tileset_error(LOG_ERROR
, _("Sprite '%s' in file \"%s\" isn't within the image!"),
2453 tag_name
, ss
->sf
->file_name
);
2457 sprite_scale
= t
->scale
;
2459 ss
->sprite
= crop_sprite(ss
->sf
->big_sprite
, ss
->x
, ss
->y
, ss
->width
,
2460 ss
->height
, NULL
, -1, -1, sprite_scale
,
2465 /* Track the reference count so we know when to free the sprite. */
2471 /**************************************************************************
2472 Create a sprite with the given color and tag.
2473 **************************************************************************/
2474 static struct sprite
*create_plr_sprite(struct color
*pcolor
)
2476 struct sprite
*sprite
;
2478 fc_assert_ret_val(pcolor
!= NULL
, NULL
);
2480 sprite
= create_sprite(128, 64, pcolor
);
2485 /**************************************************************************
2486 Unloads the sprite. Decrease the reference counter. If the last
2487 reference is removed the sprite is freed.
2488 **************************************************************************/
2489 static void unload_sprite(struct tileset
*t
, const char *tag_name
)
2491 struct small_sprite
*ss
;
2493 sprite_hash_lookup(t
->sprite_hash
, tag_name
, &ss
);
2495 fc_assert_ret(ss
->ref_count
>= 1);
2496 fc_assert_ret(ss
->sprite
);
2500 if (ss
->ref_count
== 0) {
2501 /* Nobody's using the sprite anymore, so we should free it. We know
2502 * where to find it if we need it again. */
2503 log_debug("freeing sprite '%s'.", tag_name
);
2504 free_sprite(ss
->sprite
);
2509 /**************************************************************************
2510 Return TRUE iff the specified sprite exists in the tileset (whether
2511 or not it is currently loaded).
2512 **************************************************************************/
2513 static bool sprite_exists(const struct tileset
*t
, const char *tag_name
)
2515 /* Lookup information about where the sprite is found. */
2516 return sprite_hash_lookup(t
->sprite_hash
, tag_name
, NULL
);
2519 /* Not very safe, but convenient: */
2520 #define SET_SPRITE(field, tag) \
2522 t->sprites.field = load_sprite(t, tag, TRUE, TRUE); \
2523 if (t->sprites.field == NULL) { \
2524 tileset_error(LOG_FATAL, _("Sprite for tag '%s' missing."), tag); \
2528 #define SET_SPRITE_NOTSMOOTH(field, tag) \
2530 t->sprites.field = load_sprite(t, tag, TRUE, FALSE); \
2531 if (t->sprites.field == NULL) { \
2532 tileset_error(LOG_FATAL, _("Sprite for tag '%s' missing."), tag); \
2536 #define SET_SPRITE_UNSCALED(field, tag) \
2538 t->sprites.field = load_sprite(t, tag, FALSE, FALSE); \
2539 if (t->sprites.field == NULL) { \
2540 tileset_error(LOG_FATAL, _("Sprite for tag '%s' missing."), tag); \
2544 /* Sets sprites.field to tag or (if tag isn't available) to alt */
2545 #define SET_SPRITE_ALT(field, tag, alt) \
2547 t->sprites.field = load_sprite(t, tag, TRUE, TRUE); \
2548 if (!t->sprites.field) { \
2549 t->sprites.field = load_sprite(t, alt, TRUE, TRUE); \
2551 if (t->sprites.field == NULL) { \
2552 tileset_error(LOG_FATAL, _("Sprite for tags '%s' and alternate '%s' are " \
2553 "both missing."), tag, alt); \
2557 /* Sets sprites.field to tag, or NULL if not available */
2558 #define SET_SPRITE_OPT(field, tag) \
2559 t->sprites.field = load_sprite(t, tag, TRUE, TRUE)
2561 #define SET_SPRITE_ALT_OPT(field, tag, alt) \
2563 t->sprites.field = tiles_lookup_sprite_tag_alt(t, LOG_VERBOSE, tag, alt,\
2564 "sprite", #field, TRUE); \
2567 /****************************************************************************
2568 Setup the graphics for specialist types.
2569 ****************************************************************************/
2570 void tileset_setup_specialist_type(struct tileset
*t
, Specialist_type_id id
)
2572 /* Load the specialist sprite graphics. */
2575 const char *name
= specialist_rule_name(specialist_by_number(id
));
2576 const char *graphic_alt
= specialist_by_number(id
)->graphic_alt
;
2578 for (j
= 0; j
< MAX_NUM_CITIZEN_SPRITES
; j
++) {
2579 /* Try rule name + index number */
2580 fc_snprintf(buffer
, sizeof(buffer
), "specialist.%s_%d", name
, j
);
2581 t
->sprites
.specialist
[id
].sprite
[j
] = load_sprite(t
, buffer
, FALSE
,
2584 /* Break if no more index specific sprites are defined */
2585 if (!t
->sprites
.specialist
[id
].sprite
[j
]) {
2590 /* Nothing? Try the alt tag */
2592 t
->sprites
.specialist
[id
].sprite
[j
] = load_sprite(t
, graphic_alt
, FALSE
,
2595 if (t
->sprites
.specialist
[id
].sprite
[j
]) {
2600 t
->sprites
.specialist
[id
].count
= j
;
2602 /* Still nothing? Give up. */
2604 tileset_error(LOG_FATAL
, _("No graphics for specialist \"%s\"."), name
);
2608 /****************************************************************************
2609 Setup the graphics for (non-specialist) citizen types.
2610 ****************************************************************************/
2611 static void tileset_setup_citizen_types(struct tileset
*t
)
2616 /* Load the citizen sprite graphics, no specialist. */
2617 for (i
= 0; i
< CITIZEN_LAST
; i
++) {
2618 const char *name
= citizen_rule_name(i
);
2620 for (j
= 0; j
< MAX_NUM_CITIZEN_SPRITES
; j
++) {
2621 fc_snprintf(buffer
, sizeof(buffer
), "citizen.%s_%d", name
, j
);
2622 t
->sprites
.citizen
[i
].sprite
[j
] = load_sprite(t
, buffer
, FALSE
, FALSE
);
2623 if (!t
->sprites
.citizen
[i
].sprite
[j
]) {
2627 t
->sprites
.citizen
[i
].count
= j
;
2629 tileset_error(LOG_FATAL
, _("No graphics for citizen \"%s\"."), name
);
2634 /****************************************************************************
2635 Return the sprite in the city_sprite listing that corresponds to this
2636 city - based on city style and size.
2638 See also load_city_sprite, free_city_sprite.
2639 ****************************************************************************/
2640 static struct sprite
*get_city_sprite(const struct city_sprite
*city_sprite
,
2641 const struct city
*pcity
)
2643 /* get style and match the best tile based on city size */
2644 int style
= style_of_city(pcity
);
2646 struct city_style_threshold
*thresholds
;
2649 fc_assert_ret_val(style
< city_sprite
->num_styles
, NULL
);
2651 num_thresholds
= city_sprite
->styles
[style
].land_num_thresholds
;
2652 thresholds
= city_sprite
->styles
[style
].land_thresholds
;
2654 if (num_thresholds
== 0) {
2658 /* Get the sprite with the index defined by the effects. */
2659 img_index
= pcity
->client
.city_image
;
2660 if (img_index
== -100) {
2661 /* Server doesn't know right value as this is from old savegame.
2662 * Guess here based on *client* side information as was done in
2663 * versions where information was not saved to savegame - this should
2664 * give us right answer of what city looked like by the time it was
2666 img_index
= get_city_bonus(pcity
, EFT_CITY_IMAGE
);
2668 img_index
= CLIP(0, img_index
, num_thresholds
- 1);
2670 return thresholds
[img_index
].sprite
;
2673 /****************************************************************************
2674 Allocates one threshold set for city sprite
2675 ****************************************************************************/
2676 static int load_city_thresholds_sprites(struct tileset
*t
, const char *tag
,
2677 char *graphic
, char *graphic_alt
,
2678 struct city_style_threshold
**thresholds
)
2681 char *gfx_in_use
= graphic
;
2682 int num_thresholds
= 0;
2683 struct sprite
*sprite
;
2688 for (size
= 0; size
< MAX_CITY_SIZE
; size
++) {
2689 fc_snprintf(buffer
, sizeof(buffer
), "%s_%s_%d",
2690 gfx_in_use
, tag
, size
);
2691 if ((sprite
= load_sprite(t
, buffer
, TRUE
, TRUE
))) {
2693 *thresholds
= fc_realloc(*thresholds
, num_thresholds
* sizeof(**thresholds
));
2694 (*thresholds
)[num_thresholds
- 1].sprite
= sprite
;
2695 } else if (size
== 0) {
2696 if (gfx_in_use
== graphic
) {
2697 /* Try again with graphic_alt. */
2699 gfx_in_use
= graphic_alt
;
2701 /* Don't load any others if the 0 element isn't there. */
2707 return num_thresholds
;
2710 /****************************************************************************
2711 Allocates and loads a new city sprite from the given sprite tags.
2715 See also get_city_sprite, free_city_sprite.
2716 ****************************************************************************/
2717 static struct city_sprite
*load_city_sprite(struct tileset
*t
,
2720 struct city_sprite
*city_sprite
= fc_malloc(sizeof(*city_sprite
));
2723 /* Store number of styles we have allocated memory for.
2724 * game.control.styles_count might change if client disconnects from
2725 * server and connects new one. */
2726 city_sprite
->num_styles
= game
.control
.styles_count
;
2727 city_sprite
->styles
= fc_malloc(city_sprite
->num_styles
2728 * sizeof(*city_sprite
->styles
));
2730 for (style
= 0; style
< city_sprite
->num_styles
; style
++) {
2731 city_sprite
->styles
[style
].land_num_thresholds
=
2732 load_city_thresholds_sprites(t
, tag
, city_styles
[style
].graphic
,
2733 city_styles
[style
].graphic_alt
,
2734 &city_sprite
->styles
[style
].land_thresholds
);
2740 /****************************************************************************
2741 Frees a city sprite.
2743 See also get_city_sprite, load_city_sprite.
2744 ****************************************************************************/
2745 static void free_city_sprite(struct city_sprite
*city_sprite
)
2752 for (style
= 0; style
< city_sprite
->num_styles
; style
++) {
2753 if (city_sprite
->styles
[style
].land_thresholds
) {
2754 free(city_sprite
->styles
[style
].land_thresholds
);
2757 free(city_sprite
->styles
);
2761 /**********************************************************************
2762 Initialize 'sprites' structure based on hardwired tags which
2763 freeciv always requires.
2764 ***********************************************************************/
2765 static void tileset_lookup_sprite_tags(struct tileset
*t
)
2767 char buffer
[512], buffer2
[512];
2768 const int W
= t
->normal_tile_width
, H
= t
->normal_tile_height
;
2771 fc_assert_ret(t
->sprite_hash
!= NULL
);
2773 SET_SPRITE_UNSCALED(treaty_thumb
[0], "treaty.disagree_thumb_down");
2774 SET_SPRITE_UNSCALED(treaty_thumb
[1], "treaty.agree_thumb_up");
2776 for (j
= 0; j
< INDICATOR_COUNT
; j
++) {
2777 const char *names
[] = {"science_bulb", "warming_sun", "cooling_flake"};
2779 for (i
= 0; i
< NUM_TILES_PROGRESS
; i
++) {
2780 fc_snprintf(buffer
, sizeof(buffer
), "s.%s_%d", names
[j
], i
);
2781 SET_SPRITE_UNSCALED(indicator
[j
][i
], buffer
);
2785 SET_SPRITE(arrow
[ARROW_RIGHT
], "s.right_arrow");
2786 SET_SPRITE(arrow
[ARROW_PLUS
], "s.plus");
2787 SET_SPRITE(arrow
[ARROW_MINUS
], "s.minus");
2788 if (t
->type
== TS_ISOMETRIC
) {
2789 SET_SPRITE(dither_tile
, "t.dither_tile");
2792 if (tileset_is_isometric(tileset
)) {
2793 SET_SPRITE_NOTSMOOTH(mask
.tile
, "mask.tile");
2795 SET_SPRITE(mask
.tile
, "mask.tile");
2797 SET_SPRITE(mask
.worked_tile
, "mask.worked_tile");
2798 SET_SPRITE(mask
.unworked_tile
, "mask.unworked_tile");
2800 SET_SPRITE_UNSCALED(tax_luxury
, "s.tax_luxury");
2801 SET_SPRITE_UNSCALED(tax_science
, "s.tax_science");
2802 SET_SPRITE_UNSCALED(tax_gold
, "s.tax_gold");
2804 tileset_setup_citizen_types(t
);
2806 for (i
= 0; i
< SPACESHIP_COUNT
; i
++) {
2807 const char *names
[SPACESHIP_COUNT
]
2808 = {"solar_panels", "life_support", "habitation",
2809 "structural", "fuel", "propulsion", "exhaust"};
2811 fc_snprintf(buffer
, sizeof(buffer
), "spaceship.%s", names
[i
]);
2812 SET_SPRITE(spaceship
[i
], buffer
);
2815 for (i
= 0; i
< CURSOR_LAST
; i
++) {
2816 for (f
= 0; f
< NUM_CURSOR_FRAMES
; f
++) {
2817 const char *names
[CURSOR_LAST
] =
2818 {"goto", "patrol", "paradrop", "nuke", "select",
2819 "invalid", "attack", "edit_paint", "edit_add", "wait"};
2820 struct small_sprite
*ss
;
2822 fc_assert(ARRAY_SIZE(names
) == CURSOR_LAST
);
2823 fc_snprintf(buffer
, sizeof(buffer
), "cursor.%s%d", names
[i
], f
);
2824 SET_SPRITE(cursor
[i
].frame
[f
], buffer
);
2825 if (sprite_hash_lookup(t
->sprite_hash
, buffer
, &ss
)) {
2826 t
->sprites
.cursor
[i
].hot_x
= ss
->hot_x
;
2827 t
->sprites
.cursor
[i
].hot_y
= ss
->hot_y
;
2832 for (i
= 0; i
< ICON_COUNT
; i
++) {
2833 const char *names
[ICON_COUNT
] = {"freeciv", "citydlg"};
2835 fc_snprintf(buffer
, sizeof(buffer
), "icon.%s", names
[i
]);
2836 SET_SPRITE(icon
[i
], buffer
);
2839 for (i
= 0; i
< E_COUNT
; i
++) {
2840 const char *tag
= get_event_tag(i
);
2842 SET_SPRITE(events
[i
], tag
);
2845 SET_SPRITE(explode
.nuke
, "explode.nuke");
2847 sprite_vector_init(&t
->sprites
.explode
.unit
);
2848 for (i
= 0; ; i
++) {
2849 struct sprite
*sprite
;
2851 fc_snprintf(buffer
, sizeof(buffer
), "explode.unit_%d", i
);
2852 sprite
= load_sprite(t
, buffer
, TRUE
, TRUE
);
2856 sprite_vector_append(&t
->sprites
.explode
.unit
, sprite
);
2859 SET_SPRITE(unit
.auto_attack
, "unit.auto_attack");
2860 SET_SPRITE(unit
.auto_settler
, "unit.auto_settler");
2861 SET_SPRITE(unit
.auto_explore
, "unit.auto_explore");
2862 SET_SPRITE(unit
.fortified
, "unit.fortified");
2863 SET_SPRITE(unit
.fortifying
, "unit.fortifying");
2864 SET_SPRITE(unit
.go_to
, "unit.goto");
2865 SET_SPRITE(unit
.irrigate
, "unit.irrigate");
2866 SET_SPRITE(unit
.plant
, "unit.plant");
2867 SET_SPRITE(unit
.pillage
, "unit.pillage");
2868 SET_SPRITE(unit
.sentry
, "unit.sentry");
2869 SET_SPRITE(unit
.convert
, "unit.convert");
2870 SET_SPRITE(unit
.stack
, "unit.stack");
2871 SET_SPRITE(unit
.loaded
, "unit.loaded");
2872 SET_SPRITE(unit
.transform
, "unit.transform");
2873 SET_SPRITE(unit
.connect
, "unit.connect");
2874 SET_SPRITE(unit
.patrol
, "unit.patrol");
2875 for (i
= 0; i
< MAX_NUM_BATTLEGROUPS
; i
++) {
2876 fc_snprintf(buffer
, sizeof(buffer
), "unit.battlegroup_%d", i
);
2877 fc_snprintf(buffer2
, sizeof(buffer2
), "city.size_%d", i
+ 1);
2878 fc_assert(MAX_NUM_BATTLEGROUPS
< NUM_TILES_DIGITS
);
2879 SET_SPRITE_ALT(unit
.battlegroup
[i
], buffer
, buffer2
);
2881 SET_SPRITE(unit
.lowfuel
, "unit.lowfuel");
2882 SET_SPRITE(unit
.tired
, "unit.tired");
2884 for(i
=0; i
<NUM_TILES_HP_BAR
; i
++) {
2885 fc_snprintf(buffer
, sizeof(buffer
), "unit.hp_%d", i
*10);
2886 SET_SPRITE(unit
.hp_bar
[i
], buffer
);
2889 for (i
= 0; i
< MAX_VET_LEVELS
; i
++) {
2890 /* Veteran level sprites are optional. For instance "green" units
2891 * usually have no special graphic. */
2892 fc_snprintf(buffer
, sizeof(buffer
), "unit.vet_%d", i
);
2893 t
->sprites
.unit
.vet_lev
[i
] = load_sprite(t
, buffer
, TRUE
, TRUE
);
2896 t
->sprites
.unit
.select
[0] = NULL
;
2897 if (sprite_exists(t
, "unit.select0")) {
2898 for (i
= 0; i
< NUM_TILES_SELECT
; i
++) {
2899 fc_snprintf(buffer
, sizeof(buffer
), "unit.select%d", i
);
2900 SET_SPRITE(unit
.select
[i
], buffer
);
2904 SET_SPRITE(citybar
.shields
, "citybar.shields");
2905 SET_SPRITE(citybar
.food
, "citybar.food");
2906 SET_SPRITE(citybar
.trade
, "citybar.trade");
2907 SET_SPRITE(citybar
.occupied
, "citybar.occupied");
2908 SET_SPRITE(citybar
.background
, "citybar.background");
2909 sprite_vector_init(&t
->sprites
.citybar
.occupancy
);
2910 for (i
= 0; ; i
++) {
2911 struct sprite
*sprite
;
2913 fc_snprintf(buffer
, sizeof(buffer
), "citybar.occupancy_%d", i
);
2914 sprite
= load_sprite(t
, buffer
, TRUE
, TRUE
);
2918 sprite_vector_append(&t
->sprites
.citybar
.occupancy
, sprite
);
2920 if (t
->sprites
.citybar
.occupancy
.size
< 2) {
2921 tileset_error(LOG_FATAL
, _("Missing necessary citybar.occupancy_N sprites."));
2924 #define SET_EDITOR_SPRITE(x) SET_SPRITE(editor.x, "editor." #x)
2925 SET_EDITOR_SPRITE(erase
);
2926 SET_EDITOR_SPRITE(brush
);
2927 SET_EDITOR_SPRITE(copy
);
2928 SET_EDITOR_SPRITE(paste
);
2929 SET_EDITOR_SPRITE(copypaste
);
2930 SET_EDITOR_SPRITE(startpos
);
2931 SET_EDITOR_SPRITE(terrain
);
2932 SET_EDITOR_SPRITE(terrain_resource
);
2933 SET_EDITOR_SPRITE(terrain_special
);
2934 SET_EDITOR_SPRITE(unit
);
2935 SET_EDITOR_SPRITE(city
);
2936 SET_EDITOR_SPRITE(vision
);
2937 SET_EDITOR_SPRITE(territory
);
2938 SET_EDITOR_SPRITE(properties
);
2939 SET_EDITOR_SPRITE(road
);
2940 SET_EDITOR_SPRITE(military_base
);
2941 #undef SET_EDITOR_SPRITE
2943 SET_SPRITE(city
.disorder
, "city.disorder");
2945 /* Fallbacks for goto path turn numbers:
2946 * path.step_%d, path.exhausted_mp_%d
2948 * --> city.size_%d */
2949 #define SET_GOTO_TURN_SPRITE(state, state_name, factor, factor_name) \
2950 fc_snprintf(buffer, sizeof(buffer), "path." state_name "_%d" #factor, i); \
2951 SET_SPRITE_OPT(path.s[state].turns ## factor_name [i], buffer); \
2952 if (t->sprites.path.s[state].turns ## factor_name [i] == NULL) { \
2953 t->sprites.path.s[state].turns ## factor_name [i] = \
2954 t->sprites.path.s[GTS_MP_LEFT].turns ## factor_name [i]; \
2956 for(i
=0; i
<NUM_TILES_DIGITS
; i
++) {
2957 fc_snprintf(buffer
, sizeof(buffer
), "city.size_%d", i
);
2958 SET_SPRITE(city
.size
[i
], buffer
);
2959 fc_snprintf(buffer2
, sizeof(buffer2
), "path.turns_%d", i
);
2960 SET_SPRITE_ALT(path
.s
[GTS_MP_LEFT
].turns
[i
], buffer2
, buffer
);
2961 SET_GOTO_TURN_SPRITE(GTS_TURN_STEP
, "step",,);
2962 SET_GOTO_TURN_SPRITE(GTS_EXHAUSTED_MP
, "exhausted_mp",,);
2964 fc_snprintf(buffer
, sizeof(buffer
), "city.size_%d0", i
);
2965 SET_SPRITE(city
.size_tens
[i
], buffer
);
2966 fc_snprintf(buffer2
, sizeof(buffer2
), "path.turns_%d0", i
);
2967 SET_SPRITE_ALT(path
.s
[GTS_MP_LEFT
].turns_tens
[i
], buffer2
, buffer
);
2968 SET_GOTO_TURN_SPRITE(GTS_TURN_STEP
, "step", 0, _tens
);
2969 SET_GOTO_TURN_SPRITE(GTS_EXHAUSTED_MP
, "exhausted_mp", 0, _tens
);
2971 fc_snprintf(buffer
, sizeof(buffer
), "city.size_%d00", i
);
2972 SET_SPRITE_OPT(city
.size_hundreds
[i
], buffer
);
2973 fc_snprintf(buffer2
, sizeof(buffer2
), "path.turns_%d00", i
);
2974 SET_SPRITE_ALT_OPT(path
.s
[GTS_MP_LEFT
].turns_hundreds
[i
], buffer2
,
2976 SET_GOTO_TURN_SPRITE(GTS_TURN_STEP
, "step", 00, _hundreds
);
2977 SET_GOTO_TURN_SPRITE(GTS_EXHAUSTED_MP
, "exhausted_mp", 00, _hundreds
);
2979 fc_snprintf(buffer
, sizeof(buffer
), "city.t_food_%d", i
);
2980 SET_SPRITE(city
.tile_foodnum
[i
], buffer
);
2981 fc_snprintf(buffer
, sizeof(buffer
), "city.t_shields_%d", i
);
2982 SET_SPRITE(city
.tile_shieldnum
[i
], buffer
);
2983 fc_snprintf(buffer
, sizeof(buffer
), "city.t_trade_%d", i
);
2984 SET_SPRITE(city
.tile_tradenum
[i
], buffer
);
2986 #undef SET_GOTO_TURN_SPRITE
2988 /* Must have at least one upkeep sprite per output type (and unhappy) */
2989 /* The rest are optional; we copy the previous sprite for unspecified ones */
2990 fc_strlcpy(buffer
, "upkeep.unhappy", sizeof(buffer
));
2991 SET_SPRITE(upkeep
.unhappy
[0], buffer
);
2992 for(i
=1; i
<MAX_NUM_UPKEEP_SPRITES
; i
++) {
2993 fc_snprintf(buffer2
, sizeof(buffer2
), "upkeep.unhappy%d", i
+1);
2994 if (sprite_exists(t
, buffer2
)) {
2995 SET_SPRITE(upkeep
.unhappy
[i
], buffer2
);
2996 fc_strlcpy(buffer
, buffer2
, sizeof(buffer
));
2998 SET_SPRITE(upkeep
.unhappy
[i
], buffer
);
3001 output_type_iterate(o
) {
3002 fc_snprintf(buffer
, sizeof(buffer
),
3003 "upkeep.%s", get_output_identifier(o
));
3004 SET_SPRITE_OPT(upkeep
.output
[o
][0], buffer
);
3005 for(i
=1; i
<MAX_NUM_UPKEEP_SPRITES
; i
++) {
3006 fc_snprintf(buffer2
, sizeof(buffer2
),
3007 "upkeep.%s%d", get_output_identifier(o
), i
+1);
3008 if (sprite_exists(t
, buffer2
)) {
3009 SET_SPRITE(upkeep
.output
[o
][i
], buffer2
);
3010 fc_strlcpy(buffer
, buffer2
, sizeof(buffer
));
3012 /* Optional, as maybe the upkeep 1 sprite didn't exist either */
3013 SET_SPRITE_OPT(upkeep
.output
[o
][i
], buffer
);
3016 } output_type_iterate_end
;
3018 t
->max_upkeep_height
= calculate_max_upkeep_height(t
);
3020 SET_SPRITE(user
.attention
, "user.attention");
3022 SET_SPRITE_OPT(path
.s
[GTS_MP_LEFT
].specific
, "path.normal");
3023 SET_SPRITE_OPT(path
.s
[GTS_EXHAUSTED_MP
].specific
, "path.exhausted_mp");
3024 SET_SPRITE_OPT(path
.s
[GTS_TURN_STEP
].specific
, "path.step");
3025 SET_SPRITE(path
.waypoint
, "path.waypoint");
3027 SET_SPRITE_NOTSMOOTH(tx
.fog
, "tx.fog");
3029 sprite_vector_init(&t
->sprites
.colors
.overlays
);
3030 for (i
= 0; ; i
++) {
3031 struct sprite
*sprite
;
3033 fc_snprintf(buffer
, sizeof(buffer
), "colors.overlay_%d", i
);
3034 sprite
= load_sprite(t
, buffer
, TRUE
, TRUE
);
3038 sprite_vector_append(&t
->sprites
.colors
.overlays
, sprite
);
3041 tileset_error(LOG_FATAL
, _("Missing overlay-color sprite colors.overlay_0."));
3044 /* Chop up and build the overlay graphics. */
3045 sprite_vector_reserve(&t
->sprites
.city
.worked_tile_overlay
,
3046 sprite_vector_size(&t
->sprites
.colors
.overlays
));
3047 sprite_vector_reserve(&t
->sprites
.city
.unworked_tile_overlay
,
3048 sprite_vector_size(&t
->sprites
.colors
.overlays
));
3049 for (i
= 0; i
< sprite_vector_size(&t
->sprites
.colors
.overlays
); i
++) {
3050 struct sprite
*color
, *color_mask
;
3051 struct sprite
*worked
, *unworked
;
3053 color
= *sprite_vector_get(&t
->sprites
.colors
.overlays
, i
);
3054 color_mask
= crop_sprite(color
, 0, 0, W
, H
, t
->sprites
.mask
.tile
, 0, 0,
3056 worked
= crop_sprite(color_mask
, 0, 0, W
, H
,
3057 t
->sprites
.mask
.worked_tile
, 0, 0, 1.0f
, FALSE
);
3058 unworked
= crop_sprite(color_mask
, 0, 0, W
, H
,
3059 t
->sprites
.mask
.unworked_tile
, 0, 0, 1.0f
, FALSE
);
3060 free_sprite(color_mask
);
3061 t
->sprites
.city
.worked_tile_overlay
.p
[i
] = worked
;
3062 t
->sprites
.city
.unworked_tile_overlay
.p
[i
] = unworked
;
3067 SET_SPRITE(grid
.unavailable
, "grid.unavailable");
3068 SET_SPRITE_OPT(grid
.nonnative
, "grid.nonnative");
3070 for (i
= 0; i
< EDGE_COUNT
; i
++) {
3073 if (i
== EDGE_UD
&& t
->hex_width
== 0) {
3075 } else if (i
== EDGE_LR
&& t
->hex_height
== 0) {
3079 fc_snprintf(buffer
, sizeof(buffer
), "grid.main.%s", edge_name
[i
]);
3080 SET_SPRITE(grid
.main
[i
], buffer
);
3082 fc_snprintf(buffer
, sizeof(buffer
), "grid.city.%s", edge_name
[i
]);
3083 SET_SPRITE(grid
.city
[i
], buffer
);
3085 fc_snprintf(buffer
, sizeof(buffer
), "grid.worked.%s", edge_name
[i
]);
3086 SET_SPRITE(grid
.worked
[i
], buffer
);
3088 fc_snprintf(buffer
, sizeof(buffer
), "grid.selected.%s", edge_name
[i
]);
3089 SET_SPRITE(grid
.selected
[i
], buffer
);
3091 fc_snprintf(buffer
, sizeof(buffer
), "grid.coastline.%s", edge_name
[i
]);
3092 SET_SPRITE(grid
.coastline
[i
], buffer
);
3094 for (be
= 0; be
< 2; be
++) {
3095 fc_snprintf(buffer
, sizeof(buffer
), "grid.borders.%c",
3097 SET_SPRITE(grid
.borders
[i
][be
], buffer
);
3102 switch (t
->darkness_style
) {
3106 case DARKNESS_ISORECT
:
3108 /* Isometric: take a single tx.darkness tile and split it into 4. */
3109 struct sprite
*darkness
= load_sprite(t
, "tx.darkness", TRUE
, FALSE
);
3110 const int ntw
= t
->normal_tile_width
, nth
= t
->normal_tile_height
;
3111 int offsets
[4][2] = {{ntw
/ 2, 0}, {0, nth
/ 2}, {ntw
/ 2, nth
/ 2}, {0, 0}};
3114 tileset_error(LOG_FATAL
, _("Sprite tx.darkness missing."));
3116 for (i
= 0; i
< 4; i
++) {
3117 t
->sprites
.tx
.darkness
[i
] = crop_sprite(darkness
, offsets
[i
][0],
3118 offsets
[i
][1], ntw
/ 2,
3119 nth
/ 2, NULL
, 0, 0, 1.0f
,
3124 case DARKNESS_CARD_SINGLE
:
3125 for (i
= 0; i
< t
->num_cardinal_tileset_dirs
; i
++) {
3126 enum direction8 dir
= t
->cardinal_tileset_dirs
[i
];
3128 fc_snprintf(buffer
, sizeof(buffer
), "tx.darkness_%s",
3129 dir_get_tileset_name(dir
));
3130 SET_SPRITE_NOTSMOOTH(tx
.darkness
[i
], buffer
);
3133 case DARKNESS_CARD_FULL
:
3134 for(i
= 1; i
< t
->num_index_cardinal
; i
++) {
3135 fc_snprintf(buffer
, sizeof(buffer
), "tx.darkness_%s",
3136 cardinal_index_str(t
, i
));
3137 SET_SPRITE_NOTSMOOTH(tx
.darkness
[i
], buffer
);
3140 case DARKNESS_CORNER
:
3141 t
->sprites
.tx
.fullfog
= fc_realloc(t
->sprites
.tx
.fullfog
,
3142 81 * sizeof(*t
->sprites
.tx
.fullfog
));
3143 for (i
= 0; i
< 81; i
++) {
3144 /* Unknown, fog, known. */
3145 char ids
[] = {'u', 'f', 'k'};
3146 char buf
[512] = "t.fog";
3147 int values
[4], vi
, k
= i
;
3149 for (vi
= 0; vi
< 4; vi
++) {
3153 cat_snprintf(buf
, sizeof(buf
), "_%c", ids
[values
[vi
]]);
3157 t
->sprites
.tx
.fullfog
[i
] = load_sprite(t
, buf
, TRUE
, FALSE
);
3162 /* no other place to initialize these variables */
3163 sprite_vector_init(&t
->sprites
.nation_flag
);
3164 sprite_vector_init(&t
->sprites
.nation_shield
);
3167 /**************************************************************************
3168 Load sprites of one river type.
3169 **************************************************************************/
3170 static bool load_river_sprites(struct tileset
*t
,
3171 struct river_sprites
*store
, const char *tag_pfx
)
3176 for (i
= 0; i
< t
->num_index_cardinal
; i
++) {
3177 fc_snprintf(buffer
, sizeof(buffer
), "%s_s_%s",
3178 tag_pfx
, cardinal_index_str(t
, i
));
3179 store
->spec
[i
] = load_sprite(t
, buffer
, TRUE
, TRUE
);
3180 if (store
->spec
[i
] == NULL
) {
3185 for (i
= 0; i
< t
->num_cardinal_tileset_dirs
; i
++) {
3186 fc_snprintf(buffer
, sizeof(buffer
), "%s_outlet_%s",
3187 tag_pfx
, dir_get_tileset_name(t
->cardinal_tileset_dirs
[i
]));
3188 store
->outlet
[i
] = load_sprite(t
, buffer
, TRUE
, TRUE
);
3189 if (store
->outlet
[i
] == NULL
) {
3190 if (t
->cardinal_tileset_dirs
[i
] == DIR8_NORTHWEST
3191 || t
->cardinal_tileset_dirs
[i
] == DIR8_NORTHEAST
3192 || t
->cardinal_tileset_dirs
[i
] == DIR8_SOUTHEAST
3193 || t
->cardinal_tileset_dirs
[i
] == DIR8_SOUTHWEST
) {
3194 log_debug("Missing \"%s\", support for this is deprecated.", buffer
);
3204 /**************************************************************************
3205 Frees any internal buffers which are created by load_sprite. Should
3206 be called after the last (for a given period of time) load_sprite
3207 call. This saves a fair amount of memory, but it will take extra time
3208 the next time we start loading sprites again.
3209 **************************************************************************/
3210 void finish_loading_sprites(struct tileset
*t
)
3212 specfile_list_iterate(t
->specfiles
, sf
) {
3213 if (sf
->big_sprite
) {
3214 free_sprite(sf
->big_sprite
);
3215 sf
->big_sprite
= NULL
;
3217 } specfile_list_iterate_end
;
3220 /**********************************************************************
3221 Load the tiles; requires tilespec_read_toplevel() called previously.
3222 Leads to tile_sprites being allocated and filled with pointers
3223 to sprites. Also sets up and populates sprite_hash, and calls func
3224 to initialize 'sprites' structure.
3225 ***********************************************************************/
3226 void tileset_load_tiles(struct tileset
*t
)
3228 tileset_lookup_sprite_tags(t
);
3229 finish_loading_sprites(t
);
3232 /**********************************************************************
3233 Lookup sprite to match tag, or else to match alt if don't find,
3234 or else return NULL, and emit log message.
3235 ***********************************************************************/
3236 struct sprite
*tiles_lookup_sprite_tag_alt(struct tileset
*t
,
3237 enum log_level level
,
3238 const char *tag
, const char *alt
,
3245 /* (should get sprite_hash before connection) */
3246 fc_assert_ret_val_msg(NULL
!= t
->sprite_hash
, NULL
,
3247 "attempt to lookup for %s \"%s\" before "
3248 "sprite_hash setup", what
, name
);
3250 sp
= load_sprite(t
, tag
, scale
, TRUE
);
3253 sp
= load_sprite(t
, alt
, scale
, TRUE
);
3255 log_verbose("Using alternate graphic \"%s\" "
3256 "(instead of \"%s\") for %s \"%s\".",
3257 alt
, tag
, what
, name
);
3261 tileset_error(level
, _("Don't have graphics tags \"%s\" or \"%s\" for %s \"%s\"."),
3262 tag
, alt
, what
, name
);
3267 /**********************************************************************
3268 Helper function to load sprite for one unit orientation
3269 ***********************************************************************/
3270 static bool tileset_setup_unit_direction(struct tileset
*t
,
3272 const char *base_str
,
3273 enum direction8 dir
,
3274 const char *dirsuffix
)
3278 fc_snprintf(buf
, sizeof(buf
), "%s_%s", base_str
, dirsuffix
);
3280 /* We don't use _alt graphics here, as that could lead to loading
3281 * real icon gfx, but alternative orientation gfx. Tileset author
3282 * probably meant icon gfx to be used as fallback for all orientations */
3283 t
->sprites
.units
.facing
[uidx
][dir
] = load_sprite(t
, buf
, TRUE
, TRUE
);
3285 if (t
->sprites
.units
.facing
[uidx
][dir
] != NULL
) {
3292 /**********************************************************************
3293 Try to setup all unit type sprites from single tag
3294 ***********************************************************************/
3295 bool static tileset_setup_unit_type_from_tag(struct tileset
*t
,
3296 int uidx
, const char *tag
)
3298 bool facing_sprites
= TRUE
;
3300 t
->sprites
.units
.icon
[uidx
] = load_sprite(t
, tag
, TRUE
, TRUE
);
3302 #define LOAD_FACING_SPRITE(dir, dname) \
3303 if (!tileset_setup_unit_direction(t, uidx, tag, dir, dname)) { \
3304 facing_sprites = FALSE; \
3307 LOAD_FACING_SPRITE(DIR8_NORTHWEST
, "nw");
3308 LOAD_FACING_SPRITE(DIR8_NORTH
, "n");
3309 LOAD_FACING_SPRITE(DIR8_NORTHEAST
, "ne");
3310 LOAD_FACING_SPRITE(DIR8_WEST
, "w");
3311 LOAD_FACING_SPRITE(DIR8_EAST
, "e");
3312 LOAD_FACING_SPRITE(DIR8_SOUTHWEST
, "sw");
3313 LOAD_FACING_SPRITE(DIR8_SOUTH
, "s");
3314 LOAD_FACING_SPRITE(DIR8_SOUTHEAST
, "se");
3316 if (!facing_sprites
&& t
->sprites
.units
.icon
[uidx
] == NULL
) {
3317 /* Neither icon gfx or orientation sprites */
3321 /* Fix a random orientation for displaying unit type in help etc.
3322 * We don't necessarily know the map topology yet, so choose a seed
3323 * that can be used to pick a valid direction later (24 is lcm(6,8)).
3324 * See get_unittype_sprite(). */
3325 t
->sprites
.units
.default_dir_seed
[uidx
] = fc_rand(24);
3329 #undef LOAD_FACING_SPRITE
3332 /**********************************************************************
3333 Set unit_type sprite value; should only happen after
3334 tilespec_load_tiles().
3335 ***********************************************************************/
3336 void tileset_setup_unit_type(struct tileset
*t
, struct unit_type
*ut
)
3338 int uidx
= utype_index(ut
);
3340 if (!tileset_setup_unit_type_from_tag(t
, uidx
, ut
->graphic_str
)
3341 && !tileset_setup_unit_type_from_tag(t
, uidx
, ut
->graphic_alt
)) {
3342 tileset_error(LOG_FATAL
, _("Missing %s unit sprite for tags \"%s\" and alternative \"%s\"."),
3343 utype_rule_name(ut
), ut
->graphic_str
, ut
->graphic_alt
);
3347 /**********************************************************************
3348 Set improvement_type sprite value; should only happen after
3349 tilespec_load_tiles().
3350 ***********************************************************************/
3351 void tileset_setup_impr_type(struct tileset
*t
,
3352 struct impr_type
*pimprove
)
3354 t
->sprites
.building
[improvement_index(pimprove
)] =
3355 tiles_lookup_sprite_tag_alt(t
, LOG_VERBOSE
, pimprove
->graphic_str
,
3356 pimprove
->graphic_alt
, "improvement",
3357 improvement_rule_name(pimprove
), FALSE
);
3359 /* should maybe do something if NULL, eg generic default? */
3362 /**********************************************************************
3363 Set tech_type sprite value; should only happen after
3364 tilespec_load_tiles().
3365 ***********************************************************************/
3366 void tileset_setup_tech_type(struct tileset
*t
,
3367 struct advance
*padvance
)
3369 if (valid_advance(padvance
)) {
3370 t
->sprites
.tech
[advance_index(padvance
)] =
3371 tiles_lookup_sprite_tag_alt(t
, LOG_VERBOSE
, padvance
->graphic_str
,
3372 padvance
->graphic_alt
, "technology",
3373 advance_rule_name(padvance
), FALSE
);
3375 /* should maybe do something if NULL, eg generic default? */
3377 t
->sprites
.tech
[advance_index(padvance
)] = NULL
;
3381 /****************************************************************************
3382 Set resource sprite values; should only happen after
3383 tilespec_load_tiles().
3384 ****************************************************************************/
3385 void tileset_setup_resource(struct tileset
*t
,
3386 const struct resource
*presource
)
3388 fc_assert_ret(NULL
!= presource
);
3389 t
->sprites
.resource
[resource_index(presource
)] =
3390 tiles_lookup_sprite_tag_alt(t
, LOG_VERBOSE
, presource
->graphic_str
,
3391 presource
->graphic_alt
, "resource",
3392 resource_rule_name(presource
), TRUE
);
3395 /****************************************************************************
3396 Set extra sprite values; should only happen after
3397 tilespec_load_tiles().
3398 ****************************************************************************/
3399 void tileset_setup_extra(struct tileset
*t
,
3400 struct extra_type
*pextra
)
3402 const int id
= extra_index(pextra
);
3403 enum extrastyle_id extrastyle
;
3405 if (!fc_strcasecmp(pextra
->graphic_str
, "none")) {
3406 /* Extra without graphics */
3407 t
->sprites
.extras
[id
].extrastyle
= extrastyle_id_invalid();
3410 if (!estyle_hash_lookup(t
->estyle_hash
, pextra
->graphic_str
,
3412 && !estyle_hash_lookup(t
->estyle_hash
, pextra
->graphic_alt
,
3414 tileset_error(LOG_FATAL
, _("No extrastyle for \"%s\" or \"%s\"."),
3415 pextra
->graphic_str
,
3416 pextra
->graphic_alt
);
3419 t
->sprites
.extras
[id
].extrastyle
= extrastyle
;
3421 extra_type_list_append(t
->style_lists
[extrastyle
], pextra
);
3423 if (extra_has_flag(pextra
, EF_SHOW_FLAG
)) {
3424 extra_type_list_append(t
->flagged_bases_list
, pextra
);
3427 switch (extrastyle
) {
3429 tileset_setup_base(t
, pextra
);
3432 case ESTYLE_ROAD_ALL_SEPARATE
:
3433 case ESTYLE_ROAD_PARITY_COMBINED
:
3434 case ESTYLE_ROAD_ALL_COMBINED
:
3436 tileset_setup_road(t
, pextra
);
3439 case ESTYLE_SINGLE1
:
3440 case ESTYLE_SINGLE2
:
3441 SET_SPRITE_ALT(extras
[id
].u
.single
, pextra
->graphic_str
, pextra
->graphic_alt
);
3444 case ESTYLE_CARDINALS
:
3449 /* We use direction-specific irrigation and farmland graphics, if they
3450 * are available. If not, we just fall back to the basic irrigation
3452 for (i
= 0; i
< t
->num_index_cardinal
; i
++) {
3453 fc_snprintf(buffer
, sizeof(buffer
), "%s_%s",
3454 pextra
->graphic_str
, cardinal_index_str(t
, i
));
3455 t
->sprites
.extras
[id
].u
.cardinals
[i
] = load_sprite(t
, buffer
,
3457 if (!t
->sprites
.extras
[id
].u
.cardinals
[i
]) {
3458 t
->sprites
.extras
[id
].u
.cardinals
[i
] = load_sprite(t
,
3459 pextra
->graphic_str
, TRUE
,
3462 if (!t
->sprites
.extras
[id
].u
.cardinals
[i
]) {
3463 fc_snprintf(buffer
, sizeof(buffer
), "%s_%s",
3464 pextra
->graphic_alt
, cardinal_index_str(t
, i
));
3465 t
->sprites
.extras
[id
].u
.cardinals
[i
] = load_sprite(t
, buffer
,
3468 if (!t
->sprites
.extras
[id
].u
.cardinals
[i
]) {
3469 t
->sprites
.extras
[id
].u
.cardinals
[i
] = load_sprite(t
,
3470 pextra
->graphic_alt
, TRUE
,
3473 if (!t
->sprites
.extras
[id
].u
.cardinals
[i
]) {
3474 tileset_error(LOG_FATAL
, _("Sprite for tags '%s' and alternate '%s' are "
3476 pextra
->graphic_str
, pextra
->graphic_alt
);
3486 if (!fc_strcasecmp(pextra
->activity_gfx
, "none")) {
3487 t
->sprites
.extras
[id
].activity
= NULL
;
3489 t
->sprites
.extras
[id
].activity
= load_sprite(t
, pextra
->activity_gfx
,
3491 if (t
->sprites
.extras
[id
].activity
== NULL
) {
3492 t
->sprites
.extras
[id
].activity
= load_sprite(t
, pextra
->act_gfx_alt
,
3495 if (t
->sprites
.extras
[id
].activity
== NULL
) {
3496 t
->sprites
.extras
[id
].activity
= load_sprite(t
, pextra
->act_gfx_alt2
,
3499 if (t
->sprites
.extras
[id
].activity
== NULL
) {
3500 tileset_error(LOG_FATAL
, _("Missing %s building activity sprite for tags \"%s\" and alternatives \"%s\" and \"%s\"."),
3501 extra_rule_name(pextra
), pextra
->activity_gfx
,
3502 pextra
->act_gfx_alt
, pextra
->act_gfx_alt2
);
3506 if (!fc_strcasecmp(pextra
->rmact_gfx
, "none")) {
3507 t
->sprites
.extras
[id
].rmact
= NULL
;
3509 t
->sprites
.extras
[id
].rmact
= load_sprite(t
, pextra
->rmact_gfx
, TRUE
,
3511 if (t
->sprites
.extras
[id
].rmact
== NULL
) {
3512 t
->sprites
.extras
[id
].rmact
= load_sprite(t
, pextra
->rmact_gfx_alt
,
3514 if (t
->sprites
.extras
[id
].rmact
== NULL
) {
3515 tileset_error(LOG_FATAL
, _("Missing %s removal activity sprite for tags \"%s\" and alternative \"%s\"."),
3516 extra_rule_name(pextra
), pextra
->rmact_gfx
, pextra
->rmact_gfx_alt
);
3522 /****************************************************************************
3523 Set road sprite values; should only happen after
3524 tilespec_load_tiles().
3525 ****************************************************************************/
3526 static void tileset_setup_road(struct tileset
*t
,
3527 struct extra_type
*pextra
)
3529 char full_tag_name
[MAX_LEN_NAME
+ strlen("_isolated")];
3530 char full_alt_name
[MAX_LEN_NAME
+ strlen("_isolated")];
3531 const int id
= extra_index(pextra
);
3533 enum extrastyle_id extrastyle
= t
->sprites
.extras
[id
].extrastyle
;
3535 /* Isolated road graphics are used by ESTYLE_ROAD_ALL_SEPARATE and
3536 ESTYLE_ROAD_PARITY_COMBINED. */
3537 if (extrastyle
== ESTYLE_ROAD_ALL_SEPARATE
3538 || extrastyle
== ESTYLE_ROAD_PARITY_COMBINED
) {
3539 fc_snprintf(full_tag_name
, sizeof(full_tag_name
),
3540 "%s_isolated", pextra
->graphic_str
);
3541 fc_snprintf(full_alt_name
, sizeof(full_alt_name
),
3542 "%s_isolated", pextra
->graphic_alt
);
3544 SET_SPRITE_ALT(extras
[id
].u
.road
.isolated
, full_tag_name
, full_alt_name
);
3547 if (extrastyle
== ESTYLE_ROAD_ALL_SEPARATE
) {
3548 /* ESTYLE_ROAD_ALL_SEPARATE has just 8 additional sprites for each road type:
3549 * one going off in each direction. */
3550 for (i
= 0; i
< t
->num_valid_tileset_dirs
; i
++) {
3551 enum direction8 dir
= t
->valid_tileset_dirs
[i
];
3552 const char *dir_name
= dir_get_tileset_name(dir
);
3554 fc_snprintf(full_tag_name
, sizeof(full_tag_name
),
3555 "%s_%s", pextra
->graphic_str
, dir_name
);
3556 fc_snprintf(full_alt_name
, sizeof(full_alt_name
),
3557 "%s_%s", pextra
->graphic_alt
, dir_name
);
3559 SET_SPRITE_ALT(extras
[id
].u
.road
.ru
.dir
[i
], full_tag_name
, full_alt_name
);
3561 } else if (extrastyle
== ESTYLE_ROAD_PARITY_COMBINED
) {
3562 int num_index
= 1 << (t
->num_valid_tileset_dirs
/ 2), j
;
3564 /* ESTYLE_ROAD_PARITY_COMBINED has 32 additional sprites for each road type:
3565 * 16 each for cardinal and diagonal directions. Each set
3566 * of 16 provides a NSEW-indexed sprite to provide connectors for
3567 * all rails in the cardinal/diagonal directions. The 0 entry is
3568 * unused (the "isolated" sprite is used instead). */
3570 for (i
= 1; i
< num_index
; i
++) {
3571 char c
[64] = "", d
[64] = "";
3573 for (j
= 0; j
< t
->num_valid_tileset_dirs
/ 2; j
++) {
3574 int value
= (i
>> j
) & 1;
3576 cat_snprintf(c
, sizeof(c
), "%s%d",
3577 dir_get_tileset_name(t
->valid_tileset_dirs
[2 * j
]),
3579 cat_snprintf(d
, sizeof(d
), "%s%d",
3580 dir_get_tileset_name(t
->valid_tileset_dirs
[2 * j
+ 1]),
3584 fc_snprintf(full_tag_name
, sizeof(full_tag_name
),
3585 "%s_c_%s", pextra
->graphic_str
, c
);
3586 fc_snprintf(full_alt_name
, sizeof(full_alt_name
),
3587 "%s_c_%s", pextra
->graphic_alt
, c
);
3589 SET_SPRITE_ALT(extras
[id
].u
.road
.ru
.combo
.even
[i
], full_tag_name
, full_alt_name
);
3591 fc_snprintf(full_tag_name
, sizeof(full_tag_name
),
3592 "%s_d_%s", pextra
->graphic_str
, d
);
3593 fc_snprintf(full_alt_name
, sizeof(full_alt_name
),
3594 "%s_d_%s", pextra
->graphic_alt
, d
);
3596 SET_SPRITE_ALT(extras
[id
].u
.road
.ru
.combo
.odd
[i
], full_tag_name
, full_alt_name
);
3598 } else if (extrastyle
== ESTYLE_ROAD_ALL_COMBINED
) {
3599 /* ESTYLE_ROAD_ALL_COMBINED includes 256 sprites, one for every possibility.
3600 * Just go around clockwise, with all combinations. */
3601 for (i
= 0; i
< t
->num_index_valid
; i
++) {
3602 char *idx_str
= valid_index_str(t
, i
);
3604 fc_snprintf(full_tag_name
, sizeof(full_tag_name
),
3605 "%s_%s", pextra
->graphic_str
, idx_str
);
3606 fc_snprintf(full_alt_name
, sizeof(full_alt_name
),
3607 "%s_%s", pextra
->graphic_alt
, idx_str
);
3609 SET_SPRITE_ALT(extras
[id
].u
.road
.ru
.total
[i
], full_tag_name
, full_alt_name
);
3611 } else if (extrastyle
== ESTYLE_RIVER
) {
3612 if (!load_river_sprites(t
, &t
->sprites
.extras
[id
].u
.road
.ru
.rivers
,
3613 pextra
->graphic_str
)) {
3614 if (!load_river_sprites(t
, &t
->sprites
.extras
[id
].u
.road
.ru
.rivers
,
3615 pextra
->graphic_alt
)) {
3616 tileset_error(LOG_FATAL
, _("Cannot load river \"%s\" or \"%s\""),
3617 pextra
->graphic_str
, pextra
->graphic_alt
);
3624 /* Corner road graphics are used by ESTYLE_ROAD_ALL_SEPARATE and
3625 * ESTYLE_ROAD_PARITY_COMBINED. */
3626 if (extrastyle
== ESTYLE_ROAD_ALL_SEPARATE
3627 || extrastyle
== ESTYLE_ROAD_PARITY_COMBINED
) {
3628 for (i
= 0; i
< t
->num_valid_tileset_dirs
; i
++) {
3629 enum direction8 dir
= t
->valid_tileset_dirs
[i
];
3631 if (!is_cardinal_tileset_dir(t
, dir
)) {
3632 const char *dtn
= dir_get_tileset_name(dir
);
3634 fc_snprintf(full_tag_name
, sizeof(full_tag_name
),
3635 "%s_c_%s", pextra
->graphic_str
, dtn
);
3636 fc_snprintf(full_alt_name
, sizeof(full_alt_name
),
3637 "%s_c_%s", pextra
->graphic_alt
, dtn
);
3639 SET_SPRITE_ALT_OPT(extras
[id
].u
.road
.corner
[dir
], full_tag_name
, full_alt_name
);
3645 /****************************************************************************
3646 Set base sprite values; should only happen after
3647 tilespec_load_tiles().
3648 ****************************************************************************/
3649 static void tileset_setup_base(struct tileset
*t
,
3650 const struct extra_type
*pextra
)
3652 char full_tag_name
[MAX_LEN_NAME
+ strlen("_fg")];
3653 const int id
= extra_index(pextra
);
3655 fc_assert_ret(id
>= 0 && id
< extra_count());
3657 sz_strlcpy(full_tag_name
, pextra
->graphic_str
);
3658 strcat(full_tag_name
, "_bg");
3659 t
->sprites
.extras
[id
].u
.bmf
.background
= load_sprite(t
, full_tag_name
,
3662 sz_strlcpy(full_tag_name
, pextra
->graphic_str
);
3663 strcat(full_tag_name
, "_mg");
3664 t
->sprites
.extras
[id
].u
.bmf
.middleground
= load_sprite(t
, full_tag_name
,
3667 sz_strlcpy(full_tag_name
, pextra
->graphic_str
);
3668 strcat(full_tag_name
, "_fg");
3669 t
->sprites
.extras
[id
].u
.bmf
.foreground
= load_sprite(t
, full_tag_name
,
3672 if (t
->sprites
.extras
[id
].u
.bmf
.background
== NULL
3673 && t
->sprites
.extras
[id
].u
.bmf
.middleground
== NULL
3674 && t
->sprites
.extras
[id
].u
.bmf
.foreground
== NULL
) {
3675 /* No primary graphics at all. Try alternative */
3676 log_verbose("Using alternate graphic \"%s\" "
3677 "(instead of \"%s\") for extra \"%s\".",
3678 pextra
->graphic_alt
, pextra
->graphic_str
,
3679 extra_rule_name(pextra
));
3681 sz_strlcpy(full_tag_name
, pextra
->graphic_alt
);
3682 strcat(full_tag_name
, "_bg");
3683 t
->sprites
.extras
[id
].u
.bmf
.background
= load_sprite(t
, full_tag_name
,
3686 sz_strlcpy(full_tag_name
, pextra
->graphic_alt
);
3687 strcat(full_tag_name
, "_mg");
3688 t
->sprites
.extras
[id
].u
.bmf
.middleground
= load_sprite(t
, full_tag_name
,
3691 sz_strlcpy(full_tag_name
, pextra
->graphic_alt
);
3692 strcat(full_tag_name
, "_fg");
3693 t
->sprites
.extras
[id
].u
.bmf
.foreground
= load_sprite(t
, full_tag_name
,
3696 if (t
->sprites
.extras
[id
].u
.bmf
.background
== NULL
3697 && t
->sprites
.extras
[id
].u
.bmf
.middleground
== NULL
3698 && t
->sprites
.extras
[id
].u
.bmf
.foreground
== NULL
) {
3699 /* Cannot find alternative graphics either */
3700 tileset_error(LOG_FATAL
, _("No graphics for extra \"%s\" at all!"),
3701 extra_rule_name(pextra
));
3706 /**********************************************************************
3707 Set tile_type sprite values; should only happen after
3708 tilespec_load_tiles().
3709 ***********************************************************************/
3710 void tileset_setup_tile_type(struct tileset
*t
,
3711 const struct terrain
*pterrain
)
3713 struct drawing_data
*draw
;
3714 struct sprite
*sprite
;
3715 char buffer
[MAX_LEN_NAME
+ 20];
3718 if (0 == strlen(terrain_rule_name(pterrain
))) {
3722 if (!drawing_hash_lookup(t
->tile_hash
, pterrain
->graphic_str
, &draw
)
3723 && !drawing_hash_lookup(t
->tile_hash
, pterrain
->graphic_alt
, &draw
)) {
3724 tileset_error(LOG_FATAL
, _("Terrain \"%s\": no graphic tile \"%s\" or \"%s\"."),
3725 terrain_rule_name(pterrain
), pterrain
->graphic_str
,
3726 pterrain
->graphic_alt
);
3730 t
->sprites
.drawing
[terrain_index(pterrain
)] = draw
;
3734 /* Set up each layer of the drawing. */
3735 for (l
= 0; l
< draw
->num_layers
; l
++) {
3736 struct drawing_layer
*dlp
= &draw
->layer
[l
];
3737 struct tileset_layer
*tslp
= &t
->layers
[l
];
3738 sprite_vector_init(&dlp
->base
);
3739 sprite_vector_init(&dlp
->allocated
);
3741 switch (dlp
->sprite_type
) {
3743 switch (dlp
->match_style
) {
3745 /* Load whole sprites for this tile. */
3746 for (i
= 0; ; i
++) {
3747 fc_snprintf(buffer
, sizeof(buffer
), "t.l%d.%s%d",
3748 l
, draw
->name
, i
+ 1);
3749 sprite
= load_sprite(t
, buffer
, TRUE
, FALSE
);
3753 sprite_vector_reserve(&dlp
->base
, i
+ 1);
3754 dlp
->base
.p
[i
] = sprite
;
3756 /* check for base sprite, allowing missing sprites above base */
3757 if (0 == i
&& 0 == l
) {
3758 /* TRANS: 'base' means 'base of terrain gfx', not 'military base' */
3759 tileset_error(LOG_FATAL
, _("Missing base sprite for tag \"%s\"."), buffer
);
3763 /* Load 16 cardinally-matched sprites. */
3764 for (i
= 0; i
< t
->num_index_cardinal
; i
++) {
3765 fc_snprintf(buffer
, sizeof(buffer
), "t.l%d.%s_%s",
3766 l
, draw
->name
, cardinal_index_str(t
, i
));
3768 tiles_lookup_sprite_tag_alt(t
, LOG_FATAL
, buffer
, "",
3770 terrain_rule_name(pterrain
), TRUE
);
3775 fc_assert(FALSE
); /* not yet defined */
3781 const int count
= dlp
->match_indices
;
3782 int number
= NUM_CORNER_DIRS
;
3784 switch (dlp
->match_style
) {
3790 /* N directions (NSEW) * 3 dimensions of matching */
3791 fc_assert(count
== 2);
3792 number
= NUM_CORNER_DIRS
* 2 * 2 * 2;
3796 /* N directions (NSEW) * 3 dimensions of matching */
3797 /* could use exp() or expi() here? */
3798 number
= NUM_CORNER_DIRS
* count
* count
* count
;
3803 = fc_calloc(number
, sizeof(*dlp
->cells
));
3805 for (i
= 0; i
< number
; i
++) {
3806 enum direction4 dir
= i
% NUM_CORNER_DIRS
;
3807 int value
= i
/ NUM_CORNER_DIRS
;
3809 switch (dlp
->match_style
) {
3811 fc_snprintf(buffer
, sizeof(buffer
), "t.l%d.%s_cell_%c",
3812 l
, draw
->name
, direction4letters
[dir
]);
3814 tiles_lookup_sprite_tag_alt(t
, LOG_FATAL
, buffer
, "",
3816 terrain_rule_name(pterrain
), TRUE
);
3819 fc_snprintf(buffer
, sizeof(buffer
), "t.l%d.%s_cell_%c%d%d%d",
3820 l
, draw
->name
, direction4letters
[dir
],
3821 (value
) & 1, (value
>> 1) & 1, (value
>> 2) & 1);
3823 tiles_lookup_sprite_tag_alt(t
, LOG_FATAL
, buffer
, "",
3824 "same cell terrain",
3825 terrain_rule_name(pterrain
), TRUE
);
3828 fc_snprintf(buffer
, sizeof(buffer
), "t.l%d.%s_cell_%c_%c_%c_%c",
3829 l
, draw
->name
, direction4letters
[dir
],
3830 tslp
->match_types
[dlp
->match_index
[(value
) & 1]][0],
3831 tslp
->match_types
[dlp
->match_index
[(value
>> 1) & 1]][0],
3832 tslp
->match_types
[dlp
->match_index
[(value
>> 2) & 1]][0]);
3834 tiles_lookup_sprite_tag_alt(t
, LOG_FATAL
, buffer
, "",
3835 "cell pair terrain",
3836 terrain_rule_name(pterrain
), TRUE
);
3840 int this = dlp
->match_index
[0];
3844 v1
= dlp
->match_index
[value
% count
];
3846 v2
= dlp
->match_index
[value
% count
];
3848 v3
= dlp
->match_index
[value
% count
];
3850 fc_assert(v1
< count
&& v2
< count
&& v3
< count
);
3852 /* Assume merged cells. This should be a separate option. */
3873 default: /* avoid warnings */
3881 /* Use first character of match_types,
3882 * already checked for uniqueness. */
3883 fc_snprintf(buffer
, sizeof(buffer
),
3884 "t.l%d.cellgroup_%c_%c_%c_%c", l
,
3885 tslp
->match_types
[n
][0], tslp
->match_types
[e
][0],
3886 tslp
->match_types
[s
][0], tslp
->match_types
[w
][0]);
3887 sprite
= load_sprite(t
, buffer
, TRUE
, FALSE
);
3890 /* Crop the sprite to separate this cell. */
3891 int vec_size
= sprite_vector_size(&dlp
->allocated
);
3893 const int W
= t
->normal_tile_width
;
3894 const int H
= t
->normal_tile_height
;
3895 int x
[4] = {W
/ 4, W
/ 4, 0, W
/ 2};
3896 int y
[4] = {H
/ 2, 0, H
/ 4, H
/ 4};
3897 int xo
[4] = {0, 0, -W
/ 2, W
/ 2};
3898 int yo
[4] = {H
/ 2, -H
/ 2, 0, 0};
3900 sprite
= crop_sprite(sprite
, x
[dir
], y
[dir
], W
/ 2, H
/ 2,
3901 t
->sprites
.mask
.tile
, xo
[dir
], yo
[dir
], 1.0f
,
3903 /* We allocated new sprite with crop_sprite. Store its
3904 * address so we can free it. */
3905 sprite_vector_reserve(&dlp
->allocated
, vec_size
+ 1);
3906 dlp
->allocated
.p
[vec_size
] = sprite
;
3908 log_error("Terrain graphics sprite for tag \"%s\" missing.", buffer
);
3911 dlp
->cells
[i
] = sprite
;
3921 /* try an optional special name */
3922 fc_snprintf(buffer
, sizeof(buffer
), "t.blend.%s", draw
->name
);
3924 tiles_lookup_sprite_tag_alt(t
, LOG_VERBOSE
, buffer
, "",
3926 terrain_rule_name(pterrain
), TRUE
);
3928 if (draw
->blending
> 0) {
3929 const int bl
= draw
->blending
- 1;
3931 if (NULL
== draw
->blender
) {
3934 /* try an already loaded base */
3935 while (NULL
== draw
->blender
3936 && li
< draw
->blending
3937 && 0 < draw
->layer
[li
].base
.size
) {
3938 draw
->blender
= draw
->layer
[li
++].base
.p
[0];
3942 if (NULL
== draw
->blender
) {
3943 /* try an unloaded base name */
3944 fc_snprintf(buffer
, sizeof(buffer
), "t.l%d.%s1", bl
, draw
->name
);
3946 tiles_lookup_sprite_tag_alt(t
, LOG_FATAL
, buffer
, "",
3947 "base (blend) terrain",
3948 terrain_rule_name(pterrain
), TRUE
);
3952 if (NULL
!= draw
->blender
) {
3953 /* Set up blending sprites. This only works in iso-view! */
3954 const int W
= t
->normal_tile_width
;
3955 const int H
= t
->normal_tile_height
;
3956 const int offsets
[4][2] = {
3957 {W
/ 2, 0}, {0, H
/ 2}, {W
/ 2, H
/ 2}, {0, 0}
3959 enum direction4 dir
= 0;
3961 for (; dir
< 4; dir
++) {
3962 draw
->blend
[dir
] = crop_sprite(draw
->blender
, offsets
[dir
][0],
3963 offsets
[dir
][1], W
/ 2, H
/ 2,
3964 t
->sprites
.dither_tile
, 0, 0, 1.0f
,
3970 t
->sprites
.drawing
[terrain_index(pterrain
)] = draw
;
3973 /**********************************************************************
3974 Set government sprite value; should only happen after
3975 tilespec_load_tiles().
3976 ***********************************************************************/
3977 void tileset_setup_government(struct tileset
*t
,
3978 struct government
*gov
)
3980 t
->sprites
.government
[government_index(gov
)] =
3981 tiles_lookup_sprite_tag_alt(t
, LOG_FATAL
, gov
->graphic_str
,
3982 gov
->graphic_alt
, "government",
3983 government_rule_name(gov
), FALSE
);
3985 /* should probably do something if NULL, eg generic default? */
3988 /**********************************************************************
3989 Set nation flag sprite value; should only happen after
3990 tilespec_load_tiles().
3991 ***********************************************************************/
3992 void tileset_setup_nation_flag(struct tileset
*t
,
3993 struct nation_type
*nation
)
3995 char *tags
[] = {nation
->flag_graphic_str
,
3996 nation
->flag_graphic_alt
,
3999 struct sprite
*flag
= NULL
, *shield
= NULL
;
4002 for (i
= 0; tags
[i
] && !flag
; i
++) {
4003 fc_snprintf(buf
, sizeof(buf
), "f.%s", tags
[i
]);
4004 flag
= load_sprite(t
, buf
, TRUE
, TRUE
);
4006 for (i
= 0; tags
[i
] && !shield
; i
++) {
4007 fc_snprintf(buf
, sizeof(buf
), "f.shield.%s", tags
[i
]);
4008 shield
= load_sprite(t
, buf
, TRUE
, TRUE
);
4010 if (!flag
|| !shield
) {
4011 /* Should never get here because of the f.unknown fallback. */
4012 tileset_error(LOG_FATAL
, _("Nation %s: no national flag."), nation_rule_name(nation
));
4015 sprite_vector_reserve(&t
->sprites
.nation_flag
, nation_count());
4016 t
->sprites
.nation_flag
.p
[nation_index(nation
)] = flag
;
4018 sprite_vector_reserve(&t
->sprites
.nation_shield
, nation_count());
4019 t
->sprites
.nation_shield
.p
[nation_index(nation
)] = shield
;
4022 /**********************************************************************
4023 Return the flag graphic to be used by the city.
4024 ***********************************************************************/
4025 struct sprite
*get_city_flag_sprite(const struct tileset
*t
,
4026 const struct city
*pcity
)
4028 return get_nation_flag_sprite(t
, nation_of_city(pcity
));
4031 /**********************************************************************
4032 Return a sprite for the national flag for this unit.
4033 ***********************************************************************/
4034 static struct sprite
*get_unit_nation_flag_sprite(const struct tileset
*t
,
4035 const struct unit
*punit
)
4037 struct nation_type
*pnation
= nation_of_unit(punit
);
4039 if (gui_options
.draw_unit_shields
) {
4040 return t
->sprites
.nation_shield
.p
[nation_index(pnation
)];
4042 return t
->sprites
.nation_flag
.p
[nation_index(pnation
)];
4046 #define FULL_TILE_X_OFFSET ((t->normal_tile_width - t->full_tile_width) / 2)
4047 #define FULL_TILE_Y_OFFSET (t->normal_tile_height - t->full_tile_height)
4049 #define ADD_SPRITE(s, draw_fog, x_offset, y_offset) \
4050 (fc_assert(s != NULL), \
4052 sprs->foggable = (draw_fog && t->fogstyle == FOG_AUTO), \
4053 sprs->offset_x = x_offset, \
4054 sprs->offset_y = y_offset, \
4056 #define ADD_SPRITE_SIMPLE(s) ADD_SPRITE(s, TRUE, 0, 0)
4057 #define ADD_SPRITE_FULL(s) \
4058 ADD_SPRITE(s, TRUE, FULL_TILE_X_OFFSET, FULL_TILE_Y_OFFSET)
4060 /**************************************************************************
4061 Assemble some data that is used in building the tile sprite arrays.
4062 (map_x, map_y) : the (normalized) map position
4063 The values we fill in:
4064 tterrain_near : terrain types of all adjacent terrain
4065 tspecial_near : specials of all adjacent terrain
4066 **************************************************************************/
4067 static void build_tile_data(const struct tile
*ptile
,
4068 struct terrain
*pterrain
,
4069 struct terrain
**tterrain_near
,
4070 bv_extras
*textras_near
)
4072 enum direction8 dir
;
4074 /* Loop over all adjacent tiles. We should have an iterator for this. */
4075 for (dir
= 0; dir
< 8; dir
++) {
4076 struct tile
*tile1
= mapstep(ptile
, dir
);
4078 if (tile1
&& client_tile_get_known(tile1
) != TILE_UNKNOWN
) {
4079 struct terrain
*terrain1
= tile_terrain(tile1
);
4081 if (NULL
!= terrain1
) {
4082 tterrain_near
[dir
] = terrain1
;
4083 textras_near
[dir
] = *tile_extras(tile1
);
4086 log_error("build_tile_data() tile (%d,%d) has no terrain!",
4089 /* At the edges of the (known) map, pretend the same terrain continued
4090 * past the edge of the map. */
4091 tterrain_near
[dir
] = pterrain
;
4092 BV_CLR_ALL(textras_near
[dir
]);
4096 /**********************************************************************
4097 Fill in the sprite array for the unit type.
4098 ***********************************************************************/
4099 static int fill_unit_type_sprite_array(const struct tileset
*t
,
4100 struct drawn_sprite
*sprs
,
4101 const struct unit_type
*putype
,
4102 enum direction8 facing
)
4104 struct drawn_sprite
*save_sprs
= sprs
;
4105 struct sprite
*uspr
= get_unittype_sprite(t
, putype
, facing
, FALSE
);
4107 ADD_SPRITE(uspr
, TRUE
,
4108 FULL_TILE_X_OFFSET
+ t
->unit_offset_x
,
4109 FULL_TILE_Y_OFFSET
+ t
->unit_offset_y
);
4111 return sprs
- save_sprs
;
4114 /**********************************************************************
4115 Fill in the sprite array for the unit.
4116 ***********************************************************************/
4117 static int fill_unit_sprite_array(const struct tileset
*t
,
4118 struct drawn_sprite
*sprs
,
4119 const struct unit
*punit
,
4120 bool stack
, bool backdrop
)
4122 struct drawn_sprite
*save_sprs
= sprs
;
4124 struct unit_type
*ptype
= unit_type_get(punit
);
4127 if (!gui_options
.solid_color_behind_units
) {
4128 ADD_SPRITE(get_unit_nation_flag_sprite(t
, punit
), TRUE
,
4129 FULL_TILE_X_OFFSET
+ t
->unit_flag_offset_x
,
4130 FULL_TILE_Y_OFFSET
+ t
->unit_flag_offset_y
);
4132 /* Taken care of in the LAYER_BACKGROUND. */
4136 /* Add the sprite for the unit type. */
4137 sprs
+= fill_unit_type_sprite_array(t
, sprs
, ptype
,
4140 if (t
->sprites
.unit
.loaded
&& unit_transported(punit
)) {
4141 ADD_SPRITE_FULL(t
->sprites
.unit
.loaded
);
4144 if (punit
->activity
!= ACTIVITY_IDLE
) {
4145 struct sprite
*s
= NULL
;
4147 switch (punit
->activity
) {
4149 if (punit
->activity_target
== NULL
) {
4150 s
= t
->sprites
.unit
.plant
;
4152 s
= t
->sprites
.extras
[extra_index(punit
->activity_target
)].activity
;
4155 case ACTIVITY_IRRIGATE
:
4156 if (punit
->activity_target
== NULL
) {
4157 s
= t
->sprites
.unit
.irrigate
;
4159 s
= t
->sprites
.extras
[extra_index(punit
->activity_target
)].activity
;
4162 case ACTIVITY_POLLUTION
:
4163 case ACTIVITY_FALLOUT
:
4164 s
= t
->sprites
.extras
[extra_index(punit
->activity_target
)].rmact
;
4166 case ACTIVITY_PILLAGE
:
4167 s
= t
->sprites
.unit
.pillage
;
4169 case ACTIVITY_EXPLORE
:
4170 s
= t
->sprites
.unit
.auto_explore
;
4172 case ACTIVITY_FORTIFIED
:
4173 s
= t
->sprites
.unit
.fortified
;
4175 case ACTIVITY_FORTIFYING
:
4176 s
= t
->sprites
.unit
.fortifying
;
4178 case ACTIVITY_SENTRY
:
4179 s
= t
->sprites
.unit
.sentry
;
4182 s
= t
->sprites
.unit
.go_to
;
4184 case ACTIVITY_TRANSFORM
:
4185 s
= t
->sprites
.unit
.transform
;
4188 case ACTIVITY_GEN_ROAD
:
4189 s
= t
->sprites
.extras
[extra_index(punit
->activity_target
)].activity
;
4191 case ACTIVITY_CONVERT
:
4192 s
= t
->sprites
.unit
.convert
;
4199 ADD_SPRITE(s
, TRUE
, FULL_TILE_X_OFFSET
+ t
->activity_offset_x
,
4200 FULL_TILE_Y_OFFSET
+ t
->activity_offset_y
);
4204 if (punit
->ai_controlled
&& punit
->activity
!= ACTIVITY_EXPLORE
) {
4205 if (is_military_unit(punit
)) {
4206 ADD_SPRITE_FULL(t
->sprites
.unit
.auto_attack
);
4208 ADD_SPRITE_FULL(t
->sprites
.unit
.auto_settler
);
4212 if (unit_has_orders(punit
)) {
4213 if (punit
->orders
.repeat
) {
4214 ADD_SPRITE_FULL(t
->sprites
.unit
.patrol
);
4215 } else if (punit
->activity
!= ACTIVITY_IDLE
) {
4216 ADD_SPRITE_SIMPLE(t
->sprites
.unit
.connect
);
4218 ADD_SPRITE(t
->sprites
.unit
.go_to
, TRUE
, FULL_TILE_X_OFFSET
+ t
->activity_offset_x
,
4219 FULL_TILE_Y_OFFSET
+ t
->activity_offset_y
);
4223 if (punit
->battlegroup
!= BATTLEGROUP_NONE
) {
4224 ADD_SPRITE_FULL(t
->sprites
.unit
.battlegroup
[punit
->battlegroup
]);
4227 if (t
->sprites
.unit
.lowfuel
4228 && utype_fuel(ptype
)
4230 && punit
->moves_left
<= 2 * SINGLE_MOVE
) {
4231 /* Show a low-fuel graphic if the plane has 2 or fewer moves left. */
4232 ADD_SPRITE_FULL(t
->sprites
.unit
.lowfuel
);
4234 if (t
->sprites
.unit
.tired
4235 && punit
->moves_left
< SINGLE_MOVE
4236 && ptype
->move_rate
> 0) {
4237 /* Show a "tired" graphic if the unit has fewer than one move
4238 * remaining, except for units for which it's full movement. */
4239 ADD_SPRITE_FULL(t
->sprites
.unit
.tired
);
4242 if (stack
|| punit
->client
.occupied
) {
4243 ADD_SPRITE_FULL(t
->sprites
.unit
.stack
);
4246 if (t
->sprites
.unit
.vet_lev
[punit
->veteran
]) {
4247 ADD_SPRITE_FULL(t
->sprites
.unit
.vet_lev
[punit
->veteran
]);
4250 ihp
= ((NUM_TILES_HP_BAR
-1)*punit
->hp
) / ptype
->hp
;
4251 ihp
= CLIP(0, ihp
, NUM_TILES_HP_BAR
-1);
4252 ADD_SPRITE_FULL(t
->sprites
.unit
.hp_bar
[ihp
]);
4254 return sprs
- save_sprs
;
4257 /**************************************************************************
4258 Add any corner road sprites to the sprite array.
4259 **************************************************************************/
4260 static int fill_road_corner_sprites(const struct tileset
*t
,
4261 const struct extra_type
*pextra
,
4262 struct drawn_sprite
*sprs
,
4263 bool road
, bool *road_near
,
4264 bool hider
, bool *hider_near
)
4266 struct drawn_sprite
*saved_sprs
= sprs
;
4268 int extra_idx
= extra_index(pextra
);
4270 if (is_cardinal_only_road(pextra
)) {
4274 /* Roads going diagonally adjacent to this tile need to be
4275 * partly drawn on this tile. */
4277 /* Draw the corner sprite if:
4278 * - There is a diagonal road (not rail!) between two adjacent tiles.
4279 * - There is no diagonal road (not rail!) that intersects this road.
4280 * The logic is simple: roads are drawn underneath railrods, but are
4281 * not always covered by them (even in the corners!). But if a railroad
4282 * connects two tiles, only the railroad (no road) is drawn between
4285 for (i
= 0; i
< t
->num_valid_tileset_dirs
; i
++) {
4286 enum direction8 dir
= t
->valid_tileset_dirs
[i
];
4288 if (!is_cardinal_tileset_dir(t
, dir
)) {
4289 /* Draw corner sprites for this non-cardinal direction. */
4290 int cw
= (i
+ 1) % t
->num_valid_tileset_dirs
;
4292 = (i
+ t
->num_valid_tileset_dirs
- 1) % t
->num_valid_tileset_dirs
;
4293 enum direction8 cwdir
= t
->valid_tileset_dirs
[cw
];
4294 enum direction8 ccwdir
= t
->valid_tileset_dirs
[ccw
];
4296 if (t
->sprites
.extras
[extra_idx
].u
.road
.corner
[dir
]
4297 && (road_near
[cwdir
] && road_near
[ccwdir
]
4298 && !(hider_near
[cwdir
] && hider_near
[ccwdir
]))
4299 && !(road
&& road_near
[dir
] && !(hider
&& hider_near
[dir
]))) {
4300 ADD_SPRITE_SIMPLE(t
->sprites
.extras
[extra_idx
].u
.road
.corner
[dir
]);
4305 return sprs
- saved_sprs
;
4308 /**************************************************************************
4309 Fill all road and rail sprites into the sprite array.
4310 **************************************************************************/
4311 static int fill_road_sprite_array(const struct tileset
*t
,
4312 const struct extra_type
*pextra
,
4313 struct drawn_sprite
*sprs
,
4315 bv_extras
*textras_near
,
4316 struct terrain
*tterrain_near
[8],
4317 const struct city
*pcity
)
4319 struct drawn_sprite
*saved_sprs
= sprs
;
4320 bool road
, road_near
[8], hider
, hider_near
[8];
4321 bool land_near
[8], hland_near
[8];
4322 bool draw_road
[8], draw_single_road
;
4323 enum direction8 dir
;
4326 enum extrastyle_id extrastyle
;
4327 const struct road_type
*proad
= extra_road_get(pextra
);
4329 extra_idx
= extra_index(pextra
);
4331 extrastyle
= t
->sprites
.extras
[extra_idx
].extrastyle
;
4333 if (extra_has_flag(pextra
, EF_CONNECT_LAND
)) {
4338 for (i
= 0; i
< 8; i
++) {
4339 land_near
[i
] = FALSE
;
4343 /* Fill some data arrays. rail_near and road_near store whether road/rail
4344 * is present in the given direction. draw_rail and draw_road store
4345 * whether road/rail is to be drawn in that direction. draw_single_road
4346 * and draw_single_rail store whether we need an isolated road/rail to be
4348 road
= BV_ISSET(textras
, extra_idx
);
4351 extra_type_list_iterate(pextra
->hiders
, phider
) {
4352 if (BV_ISSET(textras
, extra_index(phider
))) {
4356 } extra_type_list_iterate_end
;
4358 if (road
&& (!pcity
|| !gui_options
.draw_cities
) && !hider
) {
4359 draw_single_road
= TRUE
;
4361 draw_single_road
= FALSE
;
4364 for (dir
= 0; dir
< 8; dir
++) {
4367 /* Check if there is adjacent road/rail. */
4368 if (!is_cardinal_only_road(pextra
)
4369 || is_cardinal_tileset_dir(t
, dir
)) {
4370 road_near
[dir
] = FALSE
;
4371 extra_type_list_iterate(proad
->integrators
, iextra
) {
4372 if (BV_ISSET(textras_near
[dir
], extra_index(iextra
))) {
4373 road_near
[dir
] = TRUE
;
4376 } extra_type_list_iterate_end
;
4378 land_near
[dir
] = (tterrain_near
[dir
] != T_UNKNOWN
4379 && terrain_type_terrain_class(tterrain_near
[dir
]) != TC_OCEAN
);
4382 road_near
[dir
] = FALSE
;
4383 land_near
[dir
] = FALSE
;
4386 /* Draw rail/road if there is a connection from this tile to the
4387 * adjacent tile. But don't draw road if there is also a rail
4389 roads_exist
= road
&& (road_near
[dir
] || land_near
[dir
]);
4390 draw_road
[dir
] = roads_exist
;
4391 hider_near
[dir
] = FALSE
;
4392 hland_near
[dir
] = tterrain_near
[dir
] != T_UNKNOWN
4393 && terrain_type_terrain_class(tterrain_near
[dir
]) != TC_OCEAN
;
4394 extra_type_list_iterate(pextra
->hiders
, phider
) {
4395 bool hider_dir
= FALSE
;
4396 bool land_dir
= FALSE
;
4398 if (!is_cardinal_only_road(phider
)
4399 || is_cardinal_tileset_dir(t
, dir
)) {
4400 if (BV_ISSET(textras_near
[dir
], extra_index(phider
))) {
4401 hider_near
[dir
] = TRUE
;
4405 && is_extra_caused_by(phider
, EC_ROAD
)
4406 && extra_has_flag(phider
, EF_CONNECT_LAND
)) {
4409 if (hider_dir
|| land_dir
) {
4410 if (BV_ISSET(textras
, extra_index(phider
))) {
4411 draw_road
[dir
] = FALSE
;
4415 } extra_type_list_iterate_end
;
4417 /* Don't draw an isolated road/rail if there's any connection.
4418 * draw_single_road would be true in the first place only if start tile has road,
4419 * so it will have road connection with any adjacent road tile. We check from real
4420 * existence of road (road_near[dir]) and not from whether road gets drawn (draw_road[dir])
4421 * as latter can be FALSE when road is simply hidden by another one, and we don't want to
4422 * draw single road in that case either. */
4423 if (draw_single_road
&& road_near
[dir
]) {
4424 draw_single_road
= FALSE
;
4428 /* Draw road corners */
4430 += fill_road_corner_sprites(t
, pextra
, sprs
, road
, road_near
, hider
, hider_near
);
4432 if (extrastyle
== ESTYLE_ROAD_ALL_SEPARATE
) {
4433 /* With ESTYLE_ROAD_ALL_SEPARATE, we simply draw one road for every connection.
4434 * This means we only need a few sprites, but a lot of drawing is
4435 * necessary and it generally doesn't look very good. */
4438 /* First draw roads under rails. */
4440 for (i
= 0; i
< t
->num_valid_tileset_dirs
; i
++) {
4441 if (draw_road
[t
->valid_tileset_dirs
[i
]]) {
4442 ADD_SPRITE_SIMPLE(t
->sprites
.extras
[extra_idx
].u
.road
.ru
.dir
[i
]);
4446 } else if (extrastyle
== ESTYLE_ROAD_PARITY_COMBINED
) {
4447 /* With ESTYLE_ROAD_PARITY_COMBINED, we draw one sprite for cardinal
4448 * road connections, one sprite for diagonal road connections.
4449 * This means we need about 4x more sprites than in style 0, but up to
4450 * 4x less drawing is needed. The drawing quality may also be
4453 /* First draw roads under rails. */
4455 int road_even_tileno
= 0, road_odd_tileno
= 0, i
;
4457 for (i
= 0; i
< t
->num_valid_tileset_dirs
/ 2; i
++) {
4458 enum direction8 even
= t
->valid_tileset_dirs
[2 * i
];
4459 enum direction8 odd
= t
->valid_tileset_dirs
[2 * i
+ 1];
4461 if (draw_road
[even
]) {
4462 road_even_tileno
|= 1 << i
;
4464 if (draw_road
[odd
]) {
4465 road_odd_tileno
|= 1 << i
;
4469 /* Draw the cardinal/even roads first. */
4470 if (road_even_tileno
!= 0) {
4471 ADD_SPRITE_SIMPLE(t
->sprites
.extras
[extra_idx
].u
.road
.ru
.combo
.even
[road_even_tileno
]);
4473 if (road_odd_tileno
!= 0) {
4474 ADD_SPRITE_SIMPLE(t
->sprites
.extras
[extra_idx
].u
.road
.ru
.combo
.odd
[road_odd_tileno
]);
4477 } else if (extrastyle
== ESTYLE_ROAD_ALL_COMBINED
) {
4478 /* RSTYLE_ALL_COMBINED is a very simple method that lets us simply retrieve
4479 * entire finished tiles, with a bitwise index of the presence of
4480 * roads in each direction. */
4482 /* Draw roads first */
4484 int road_tileno
= 0, i
;
4486 for (i
= 0; i
< t
->num_valid_tileset_dirs
; i
++) {
4487 enum direction8 vdir
= t
->valid_tileset_dirs
[i
];
4489 if (draw_road
[vdir
]) {
4490 road_tileno
|= 1 << i
;
4494 if (road_tileno
!= 0 || draw_single_road
) {
4495 ADD_SPRITE_SIMPLE(t
->sprites
.extras
[extra_idx
].u
.road
.ru
.total
[road_tileno
]);
4502 /* Draw isolated rail/road separately (ESTYLE_ROAD_ALL_SEPARATE and
4503 ESTYLE_ROAD_PARITY_COMBINED only). */
4504 if (extrastyle
== ESTYLE_ROAD_ALL_SEPARATE
4505 || extrastyle
== ESTYLE_ROAD_PARITY_COMBINED
) {
4506 if (draw_single_road
) {
4507 ADD_SPRITE_SIMPLE(t
->sprites
.extras
[extra_idx
].u
.road
.isolated
);
4511 return sprs
- saved_sprs
;
4514 /**************************************************************************
4515 Return the index of the sprite to be used for irrigation or farmland in
4518 We assume that the current tile has farmland or irrigation. We then
4519 choose a sprite (index) based upon which cardinally adjacent tiles have
4520 either farmland or irrigation (the two are considered interchangable for
4522 **************************************************************************/
4523 static int get_irrigation_index(const struct tileset
*t
,
4524 struct extra_type
*pextra
,
4525 bv_extras
*textras_near
)
4529 for (i
= 0; i
< t
->num_cardinal_tileset_dirs
; i
++) {
4530 enum direction8 dir
= t
->cardinal_tileset_dirs
[i
];
4532 if (BV_ISSET(textras_near
[dir
], extra_index(pextra
))) {
4540 /**************************************************************************
4541 Fill in the farmland/irrigation sprite for the tile.
4542 **************************************************************************/
4543 static int fill_irrigation_sprite_array(const struct tileset
*t
,
4544 struct drawn_sprite
*sprs
,
4546 bv_extras
*textras_near
,
4547 const struct city
*pcity
)
4549 struct drawn_sprite
*saved_sprs
= sprs
;
4551 /* We don't draw the irrigation if there's a city (it just gets overdrawn
4552 * anyway, and ends up looking bad). */
4553 if (!(pcity
&& gui_options
.draw_cities
)) {
4554 extra_type_list_iterate(t
->style_lists
[ESTYLE_CARDINALS
], pextra
) {
4555 if (is_extra_drawing_enabled(pextra
)) {
4556 int eidx
= extra_index(pextra
);
4558 if (BV_ISSET(textras
, eidx
)) {
4559 bool hidden
= FALSE
;
4561 extra_type_list_iterate(pextra
->hiders
, phider
) {
4562 if (BV_ISSET(textras
, extra_index(phider
))) {
4566 } extra_type_list_iterate_end
;
4569 int idx
= get_irrigation_index(t
, pextra
, textras_near
);
4571 ADD_SPRITE_SIMPLE(t
->sprites
.extras
[eidx
].u
.cardinals
[idx
]);
4575 } extra_type_list_iterate_end
;
4578 return sprs
- saved_sprs
;
4581 /**************************************************************************
4582 Fill in the city overlays for the tile. This includes the citymap
4583 overlays on the mapview as well as the tile output sprites.
4584 **************************************************************************/
4585 static int fill_city_overlays_sprite_array(const struct tileset
*t
,
4586 struct drawn_sprite
*sprs
,
4587 const struct tile
*ptile
,
4588 const struct city
*citymode
)
4590 const struct city
*pcity
;
4591 const struct city
*pwork
;
4592 struct unit
*psettler
;
4593 struct drawn_sprite
*saved_sprs
= sprs
;
4595 const int NUM_CITY_COLORS
= t
->sprites
.city
.worked_tile_overlay
.size
;
4597 if (NULL
== ptile
|| TILE_UNKNOWN
== client_tile_get_known(ptile
)) {
4600 pwork
= tile_worked(ptile
);
4605 pcity
= find_city_or_settler_near_tile(ptile
, &psettler
);
4608 /* Below code does not work if pcity is invisible.
4609 * Make sure it is not. */
4610 fc_assert_ret_val(pcity
== NULL
|| pcity
->tile
!= NULL
, 0);
4611 if (pcity
&& !pcity
->tile
) {
4615 if (pcity
&& city_base_to_city_map(&city_x
, &city_y
, pcity
, ptile
)) {
4616 /* FIXME: check elsewhere for valid tile (instead of above) */
4618 if (!citymode
&& pcity
->client
.colored
) {
4619 /* Add citymap overlay for a city. */
4620 int idx
= pcity
->client
.color_index
% NUM_CITY_COLORS
;
4622 if (NULL
!= pwork
&& pwork
== pcity
) {
4623 ADD_SPRITE_SIMPLE(t
->sprites
.city
.worked_tile_overlay
.p
[idx
]);
4624 } else if (city_can_work_tile(pcity
, ptile
)) {
4625 ADD_SPRITE_SIMPLE(t
->sprites
.city
.unworked_tile_overlay
.p
[idx
]);
4627 } else if (NULL
!= pwork
&& pwork
== pcity
4628 && (citymode
|| gui_options
.draw_city_output
)) {
4629 /* Add on the tile output sprites. */
4630 int food
= city_tile_output_now(pcity
, ptile
, O_FOOD
);
4631 int shields
= city_tile_output_now(pcity
, ptile
, O_SHIELD
);
4632 int trade
= city_tile_output_now(pcity
, ptile
, O_TRADE
);
4633 const int ox
= t
->type
== TS_ISOMETRIC
? t
->normal_tile_width
/ 3 : 0;
4634 const int oy
= t
->type
== TS_ISOMETRIC
? -t
->normal_tile_height
/ 3 : 0;
4636 food
= CLIP(0, food
, NUM_TILES_DIGITS
- 1);
4637 shields
= CLIP(0, shields
, NUM_TILES_DIGITS
- 1);
4638 trade
= CLIP(0, trade
, NUM_TILES_DIGITS
- 1);
4640 ADD_SPRITE(t
->sprites
.city
.tile_foodnum
[food
], TRUE
, ox
, oy
);
4641 ADD_SPRITE(t
->sprites
.city
.tile_shieldnum
[shields
], TRUE
, ox
, oy
);
4642 ADD_SPRITE(t
->sprites
.city
.tile_tradenum
[trade
], TRUE
, ox
, oy
);
4644 } else if (psettler
&& psettler
->client
.colored
) {
4645 /* Add citymap overlay for a unit. */
4646 int idx
= psettler
->client
.color_index
% NUM_CITY_COLORS
;
4648 ADD_SPRITE_SIMPLE(t
->sprites
.city
.unworked_tile_overlay
.p
[idx
]);
4651 return sprs
- saved_sprs
;
4654 /****************************************************************************
4655 Helper function for fill_terrain_sprite_layer.
4656 Fill in the sprite array for blended terrain.
4657 ****************************************************************************/
4658 static int fill_terrain_sprite_blending(const struct tileset
*t
,
4659 struct drawn_sprite
*sprs
,
4660 const struct tile
*ptile
,
4661 const struct terrain
*pterrain
,
4662 struct terrain
**tterrain_near
)
4664 struct drawn_sprite
*saved_sprs
= sprs
;
4665 const int W
= t
->normal_tile_width
, H
= t
->normal_tile_height
;
4666 const int offsets
[4][2] = {
4667 {W
/2, 0}, {0, H
/ 2}, {W
/ 2, H
/ 2}, {0, 0}
4669 enum direction4 dir
= 0;
4672 * We want to mark unknown tiles so that an unreal tile will be
4673 * given the same marking as our current tile - that way we won't
4674 * get the "unknown" dither along the edge of the map.
4676 for (; dir
< 4; dir
++) {
4677 struct tile
*tile1
= mapstep(ptile
, DIR4_TO_DIR8
[dir
]);
4678 struct terrain
*other
;
4681 || client_tile_get_known(tile1
) == TILE_UNKNOWN
4682 || pterrain
== (other
= tterrain_near
[DIR4_TO_DIR8
[dir
]])
4683 || (0 == t
->sprites
.drawing
[terrain_index(other
)]->blending
4684 && NULL
== t
->sprites
.drawing
[terrain_index(other
)]->blender
)) {
4688 ADD_SPRITE(t
->sprites
.drawing
[terrain_index(other
)]->blend
[dir
], TRUE
,
4689 offsets
[dir
][0], offsets
[dir
][1]);
4692 return sprs
- saved_sprs
;
4695 /****************************************************************************
4696 Add sprites for fog (and some forms of darkness).
4697 ****************************************************************************/
4698 static int fill_fog_sprite_array(const struct tileset
*t
,
4699 struct drawn_sprite
*sprs
,
4700 const struct tile
*ptile
,
4701 const struct tile_edge
*pedge
,
4702 const struct tile_corner
*pcorner
)
4704 struct drawn_sprite
*saved_sprs
= sprs
;
4706 if (t
->fogstyle
== FOG_SPRITE
&& gui_options
.draw_fog_of_war
4708 && TILE_KNOWN_UNSEEN
== client_tile_get_known(ptile
)) {
4709 /* With FOG_AUTO, fog is done this way. */
4710 ADD_SPRITE_SIMPLE(t
->sprites
.tx
.fog
);
4713 if (t
->darkness_style
== DARKNESS_CORNER
&& pcorner
4714 && gui_options
.draw_fog_of_war
) {
4717 for (i
= 3; i
>= 0; i
--) {
4718 const int unknown
= 0, fogged
= 1, known
= 2;
4721 if (!pcorner
->tile
[i
]) {
4724 switch (client_tile_get_known(pcorner
->tile
[i
])) {
4725 case TILE_KNOWN_SEEN
:
4728 case TILE_KNOWN_UNSEEN
:
4736 fc_assert(value
>= 0 && value
< 3);
4738 tileno
= tileno
* 3 + value
;
4741 if (t
->sprites
.tx
.fullfog
[tileno
]) {
4742 ADD_SPRITE_SIMPLE(t
->sprites
.tx
.fullfog
[tileno
]);
4746 return sprs
- saved_sprs
;
4749 /****************************************************************************
4750 Helper function for fill_terrain_sprite_layer.
4751 ****************************************************************************/
4752 static int fill_terrain_sprite_array(struct tileset
*t
,
4753 struct drawn_sprite
*sprs
,
4754 int l
, /* layer_num */
4755 const struct tile
*ptile
,
4756 const struct terrain
*pterrain
,
4757 struct terrain
**tterrain_near
,
4758 struct drawing_data
*draw
)
4760 struct drawn_sprite
*saved_sprs
= sprs
;
4761 struct drawing_layer
*dlp
= &draw
->layer
[l
];
4762 int this = dlp
->match_index
[0];
4763 int that
= dlp
->match_index
[1];
4764 int ox
= dlp
->offset_x
;
4765 int oy
= dlp
->offset_y
;
4768 #define MATCH(dir) \
4769 (t->sprites.drawing[terrain_index(tterrain_near[(dir)])]->num_layers > l \
4770 ? t->sprites.drawing[terrain_index(tterrain_near[(dir)])]->layer[l].match_index[0] \
4773 switch (dlp
->sprite_type
) {
4776 switch (dlp
->match_style
) {
4779 int count
= sprite_vector_size(&dlp
->base
);
4782 /* Pseudo-random reproducable algorithm to pick a sprite. Use modulo
4783 * to limit the number to a handleable size [0..32000). */
4784 count
= fc_randomly(tile_index(ptile
) % 32000, count
);
4787 ox
+= FULL_TILE_X_OFFSET
;
4788 oy
+= FULL_TILE_Y_OFFSET
;
4790 ADD_SPRITE(dlp
->base
.p
[count
], TRUE
, ox
, oy
);
4798 for (i
= 0; i
< t
->num_cardinal_tileset_dirs
; i
++) {
4799 enum direction8 dir
= t
->cardinal_tileset_dirs
[i
];
4801 if (MATCH(dir
) == this) {
4807 ox
+= FULL_TILE_X_OFFSET
;
4808 oy
+= FULL_TILE_Y_OFFSET
;
4810 ADD_SPRITE(dlp
->match
[tileno
], TRUE
, ox
, oy
);
4815 fc_assert(FALSE
); /* not yet defined */
4822 /* Divide the tile up into four rectangular cells. Each of these
4823 * cells covers one corner, and each is adjacent to 3 different
4824 * tiles. For each cell we pick a sprite based upon the adjacent
4825 * terrains at each of those tiles. Thus, we have 8 different sprites
4826 * for each of the 4 cells (32 sprites total).
4828 * These arrays correspond to the direction4 ordering. */
4829 const int W
= t
->normal_tile_width
;
4830 const int H
= t
->normal_tile_height
;
4831 const int iso_offsets
[4][2] = {
4832 {W
/ 4, 0}, {W
/ 4, H
/ 2}, {W
/ 2, H
/ 4}, {0, H
/ 4}
4834 const int noniso_offsets
[4][2] = {
4835 {0, 0}, {W
/ 2, H
/ 2}, {W
/ 2, 0}, {0, H
/ 2}
4838 /* put corner cells */
4839 for (i
= 0; i
< NUM_CORNER_DIRS
; i
++) {
4840 const int count
= dlp
->match_indices
;
4841 int array_index
= 0;
4842 enum direction8 dir
= dir_ccw(DIR4_TO_DIR8
[i
]);
4843 int x
= (t
->type
== TS_ISOMETRIC
? iso_offsets
[i
][0] : noniso_offsets
[i
][0]);
4844 int y
= (t
->type
== TS_ISOMETRIC
? iso_offsets
[i
][1] : noniso_offsets
[i
][1]);
4845 int m
[3] = {MATCH(dir_ccw(dir
)), MATCH(dir
), MATCH(dir_cw(dir
))};
4848 /* synthesize 4 dimensional array? */
4849 switch (dlp
->match_style
) {
4851 /* We have no need for matching, just plug the piece in place. */
4854 array_index
= array_index
* 2 + (m
[2] != this);
4855 array_index
= array_index
* 2 + (m
[1] != this);
4856 array_index
= array_index
* 2 + (m
[0] != this);
4859 array_index
= array_index
* 2 + (m
[2] == that
);
4860 array_index
= array_index
* 2 + (m
[1] == that
);
4861 array_index
= array_index
* 2 + (m
[0] == that
);
4868 for (; j
< 3; j
++) {
4870 for (; k
< count
; k
++) {
4871 n
[j
] = k
; /* default to last entry */
4872 if (m
[j
] == dlp
->match_index
[k
])
4878 array_index
= array_index
* count
+ n
[2];
4879 array_index
= array_index
* count
+ n
[1];
4880 array_index
= array_index
* count
+ n
[0];
4884 array_index
= array_index
* NUM_CORNER_DIRS
+ i
;
4886 s
= dlp
->cells
[array_index
];
4888 ADD_SPRITE(s
, TRUE
, x
, y
);
4896 return sprs
- saved_sprs
;
4899 /****************************************************************************
4900 Helper function for fill_terrain_sprite_layer.
4901 Fill in the sprite array of darkness.
4902 ****************************************************************************/
4903 static int fill_terrain_sprite_darkness(struct tileset
*t
,
4904 struct drawn_sprite
*sprs
,
4905 const struct tile
*ptile
,
4906 struct terrain
**tterrain_near
)
4908 struct drawn_sprite
*saved_sprs
= sprs
;
4910 struct tile
*adjc_tile
;
4912 #define UNKNOWN(dir) \
4913 ((adjc_tile = mapstep(ptile, (dir))) \
4914 && client_tile_get_known(adjc_tile) == TILE_UNKNOWN)
4916 switch (t
->darkness_style
) {
4919 case DARKNESS_ISORECT
:
4920 for (i
= 0; i
< 4; i
++) {
4921 const int W
= t
->normal_tile_width
, H
= t
->normal_tile_height
;
4922 int offsets
[4][2] = {{W
/ 2, 0}, {0, H
/ 2}, {W
/ 2, H
/ 2}, {0, 0}};
4924 if (UNKNOWN(DIR4_TO_DIR8
[i
])) {
4925 ADD_SPRITE(t
->sprites
.tx
.darkness
[i
], TRUE
,
4926 offsets
[i
][0], offsets
[i
][1]);
4930 case DARKNESS_CARD_SINGLE
:
4931 for (i
= 0; i
< t
->num_cardinal_tileset_dirs
; i
++) {
4932 if (UNKNOWN(t
->cardinal_tileset_dirs
[i
])) {
4933 ADD_SPRITE_SIMPLE(t
->sprites
.tx
.darkness
[i
]);
4937 case DARKNESS_CARD_FULL
:
4938 /* We're looking to find the INDEX_NSEW for the directions that
4939 * are unknown. We want to mark unknown tiles so that an unreal
4940 * tile will be given the same marking as our current tile - that
4941 * way we won't get the "unknown" dither along the edge of the
4944 for (i
= 0; i
< t
->num_cardinal_tileset_dirs
; i
++) {
4945 if (UNKNOWN(t
->cardinal_tileset_dirs
[i
])) {
4951 ADD_SPRITE_SIMPLE(t
->sprites
.tx
.darkness
[tileno
]);
4954 case DARKNESS_CORNER
:
4955 /* Handled separately. */
4960 return sprs
- saved_sprs
;
4963 /****************************************************************************
4964 Add sprites for the base tile to the sprite list. This doesn't
4965 include specials or rivers.
4966 ****************************************************************************/
4967 static int fill_terrain_sprite_layer(struct tileset
*t
,
4968 struct drawn_sprite
*sprs
,
4970 const struct tile
*ptile
,
4971 const struct terrain
*pterrain
,
4972 struct terrain
**tterrain_near
)
4974 struct sprite
*sprite
;
4975 struct drawn_sprite
*saved_sprs
= sprs
;
4976 struct drawing_data
*draw
= t
->sprites
.drawing
[terrain_index(pterrain
)];
4977 const int l
= (draw
->is_reversed
4978 ? (draw
->num_layers
- layer_num
- 1) : layer_num
);
4980 fc_assert(layer_num
< TERRAIN_LAYER_COUNT
);
4982 /* Skip the normal drawing process. */
4983 /* FIXME: this should avoid calling load_sprite since it's slow and
4984 * increases the refcount without limit. */
4985 if (ptile
->spec_sprite
&& (sprite
= load_sprite(t
, ptile
->spec_sprite
,
4988 ADD_SPRITE_SIMPLE(sprite
);
4995 if (l
< draw
->num_layers
) {
4996 sprs
+= fill_terrain_sprite_array(t
, sprs
, l
, ptile
, pterrain
, tterrain_near
, draw
);
4998 if ((l
+ 1) == draw
->blending
) {
4999 sprs
+= fill_terrain_sprite_blending(t
, sprs
, ptile
, pterrain
, tterrain_near
);
5003 /* Add darkness on top of the designed terrain layer. Note that darkness is always
5004 * drawn, even in citymode, etc. */
5005 if (layer_num
== t
->darkness_layer
) {
5006 sprs
+= fill_terrain_sprite_darkness(t
, sprs
, ptile
, tterrain_near
);
5009 return sprs
- saved_sprs
;
5012 /****************************************************************************
5013 Indicate whether a unit is to be drawn with a surrounding city outline
5014 under current conditions.
5015 (This includes being in focus, but if the caller has already checked that,
5016 they can bypass this slightly expensive check with check_focus == FALSE.)
5017 ****************************************************************************/
5018 bool unit_drawn_with_city_outline(const struct unit
*punit
, bool check_focus
)
5020 /* Display an outline for city-builder type units if they are selected,
5021 * and on a tile where a city can be built.
5022 * But suppress the outline if the unit has orders (likely it is in
5023 * transit to somewhere else and this will just slow down redraws). */
5024 return gui_options
.draw_city_outlines
5025 && unit_is_cityfounder(punit
)
5026 && !unit_has_orders(punit
)
5027 && (client_tile_get_known(unit_tile(punit
)) != TILE_UNKNOWN
5028 && city_can_be_built_here(unit_tile(punit
), punit
))
5029 && (!check_focus
|| unit_is_in_focus(punit
));
5032 /****************************************************************************
5033 Fill in the grid sprites for the given tile, city, and unit.
5034 ****************************************************************************/
5035 static int fill_grid_sprite_array(const struct tileset
*t
,
5036 struct drawn_sprite
*sprs
,
5037 const struct tile
*ptile
,
5038 const struct tile_edge
*pedge
,
5039 const struct tile_corner
*pcorner
,
5040 const struct unit
*punit
,
5041 const struct city
*pcity
,
5042 const struct city
*citymode
)
5044 struct drawn_sprite
*saved_sprs
= sprs
;
5047 bool known
[NUM_EDGE_TILES
], city
[NUM_EDGE_TILES
];
5048 bool unit
[NUM_EDGE_TILES
], worked
[NUM_EDGE_TILES
];
5050 struct unit_list
*pfocus_units
= get_units_in_focus();
5052 for (i
= 0; i
< NUM_EDGE_TILES
; i
++) {
5053 int dummy_x
, dummy_y
;
5054 const struct tile
*tile
= pedge
->tile
[i
];
5055 struct player
*powner
= tile
? tile_owner(tile
) : NULL
;
5057 known
[i
] = tile
&& client_tile_get_known(tile
) != TILE_UNKNOWN
;
5059 if (tile
&& !citymode
) {
5060 unit_list_iterate(pfocus_units
, pfocus_unit
) {
5061 if (unit_drawn_with_city_outline(pfocus_unit
, FALSE
)
5062 && city_tile_to_city_map(&dummy_x
, &dummy_y
,
5063 game
.info
.init_city_radius_sq
,
5064 unit_tile(pfocus_unit
), tile
)) {
5068 } unit_list_iterate_end
;
5073 && (NULL
== powner
|| NULL
== client
.conn
.playing
5074 || powner
== client
.conn
.playing
)
5075 && player_in_city_map(client
.conn
.playing
, tile
));
5078 /* In citymode, we only draw worked tiles for this city - other
5079 * tiles may be marked as unavailable. */
5080 worked
[i
] = (tile_worked(tile
) == citymode
);
5082 worked
[i
] = (NULL
!= tile_worked(tile
));
5087 if (mapdeco_is_highlight_set(pedge
->tile
[0])
5088 || mapdeco_is_highlight_set(pedge
->tile
[1])) {
5089 ADD_SPRITE_SIMPLE(t
->sprites
.grid
.selected
[pedge
->type
]);
5090 } else if (!gui_options
.draw_terrain
&& gui_options
.draw_coastline
5091 && pedge
->tile
[0] && pedge
->tile
[1]
5092 && known
[0] && known
[1]
5093 && (is_ocean_tile(pedge
->tile
[0])
5094 ^ is_ocean_tile(pedge
->tile
[1]))) {
5095 ADD_SPRITE_SIMPLE(t
->sprites
.grid
.coastline
[pedge
->type
]);
5097 if (gui_options
.draw_map_grid
) {
5098 if (worked
[0] || worked
[1]) {
5099 ADD_SPRITE_SIMPLE(t
->sprites
.grid
.worked
[pedge
->type
]);
5100 } else if (city
[0] || city
[1]) {
5101 ADD_SPRITE_SIMPLE(t
->sprites
.grid
.city
[pedge
->type
]);
5102 } else if (known
[0] || known
[1]) {
5103 ADD_SPRITE_SIMPLE(t
->sprites
.grid
.main
[pedge
->type
]);
5106 if (gui_options
.draw_city_outlines
) {
5107 if (XOR(city
[0], city
[1])) {
5108 ADD_SPRITE_SIMPLE(t
->sprites
.grid
.city
[pedge
->type
]);
5110 if (XOR(unit
[0], unit
[1])) {
5111 ADD_SPRITE_SIMPLE(t
->sprites
.grid
.worked
[pedge
->type
]);
5116 if (gui_options
.draw_borders
5117 && BORDERS_DISABLED
!= game
.info
.borders
5120 struct player
*owner0
= tile_owner(pedge
->tile
[0]);
5121 struct player
*owner1
= tile_owner(pedge
->tile
[1]);
5123 if (owner0
!= owner1
) {
5125 int plrid
= player_index(owner0
);
5126 ADD_SPRITE_SIMPLE(t
->sprites
.player
[plrid
].grid_borders
5130 int plrid
= player_index(owner1
);
5131 ADD_SPRITE_SIMPLE(t
->sprites
.player
[plrid
].grid_borders
5136 } else if (NULL
!= ptile
&& TILE_UNKNOWN
!= client_tile_get_known(ptile
)) {
5140 /* test to ensure valid coordinates? */
5141 && city_base_to_city_map(&cx
, &cy
, citymode
, ptile
)
5142 && !client_city_can_work_tile(citymode
, ptile
)) {
5143 ADD_SPRITE_SIMPLE(t
->sprites
.grid
.unavailable
);
5146 if (gui_options
.draw_native
&& citymode
== NULL
) {
5148 struct unit_list
*pfocus_units
= get_units_in_focus();
5150 unit_list_iterate(pfocus_units
, pfocus
) {
5151 if (!is_native_tile(unit_type_get(pfocus
), ptile
)) {
5155 } unit_list_iterate_end
;
5158 if (t
->sprites
.grid
.nonnative
!= NULL
) {
5159 ADD_SPRITE_SIMPLE(t
->sprites
.grid
.nonnative
);
5161 ADD_SPRITE_SIMPLE(t
->sprites
.grid
.unavailable
);
5167 return sprs
- saved_sprs
;
5170 /****************************************************************************
5171 Fill in the given sprite array with any needed goto sprites.
5172 ****************************************************************************/
5173 static int fill_goto_sprite_array(const struct tileset
*t
,
5174 struct drawn_sprite
*sprs
,
5175 const struct tile
*ptile
,
5176 const struct tile_edge
*pedge
,
5177 const struct tile_corner
*pcorner
)
5179 struct drawn_sprite
*saved_sprs
= sprs
;
5180 struct sprite
*sprite
;
5182 enum goto_tile_state state
;
5186 if (goto_tile_state(ptile
, &state
, &length
, &waypoint
)) {
5188 fc_assert(state
>= 0);
5189 fc_assert(state
< ARRAY_SIZE(t
->sprites
.path
.s
));
5191 sprite
= t
->sprites
.path
.s
[state
].specific
;
5192 if (sprite
!= NULL
) {
5193 ADD_SPRITE(sprite
, FALSE
, 0, 0);
5196 sprite
= t
->sprites
.path
.s
[state
].turns
[length
% 10];
5197 ADD_SPRITE_SIMPLE(sprite
);
5199 sprite
= t
->sprites
.path
.s
[state
].turns_tens
[(length
/ 10) % 10];
5200 ADD_SPRITE_SIMPLE(sprite
);
5201 if (length
>= 100) {
5202 sprite
= t
->sprites
.path
.s
[state
].turns_hundreds
[(length
/ 100)
5205 if (sprite
!= NULL
) {
5206 ADD_SPRITE_SIMPLE(sprite
);
5207 if (length
>= 1000) {
5218 ADD_SPRITE(t
->sprites
.path
.waypoint
, FALSE
, 0, 0);
5222 /* Warn only once by tileset. */
5223 static char last_reported
[256] = "";
5225 if (0 != strcmp(last_reported
, t
->name
)) {
5226 log_normal(_("Tileset \"%s\" doesn't support long goto paths, "
5227 "such as %d. Path not displayed as expected."),
5229 sz_strlcpy(last_reported
, t
->name
);
5234 return sprs
- saved_sprs
;
5237 /****************************************************************************
5238 Should the given extra be drawn
5239 ****************************************************************************/
5240 static bool is_extra_drawing_enabled(struct extra_type
*pextra
)
5242 bool no_disable
= TRUE
; /* Draw if matches no cause */
5244 if (is_extra_caused_by(pextra
, EC_IRRIGATION
)) {
5245 if (gui_options
.draw_irrigation
) {
5250 if (is_extra_caused_by(pextra
, EC_POLLUTION
)
5251 || is_extra_caused_by(pextra
, EC_FALLOUT
)) {
5252 if (gui_options
.draw_pollution
) {
5257 if (is_extra_caused_by(pextra
, EC_MINE
)) {
5258 if (gui_options
.draw_mines
) {
5263 if (is_extra_caused_by(pextra
, EC_HUT
)) {
5264 if (gui_options
.draw_huts
) {
5269 if (is_extra_caused_by(pextra
, EC_BASE
)) {
5270 if (gui_options
.draw_fortress_airbase
) {
5275 if (is_extra_caused_by(pextra
, EC_ROAD
)) {
5276 if (gui_options
.draw_roads_rails
) {
5285 /****************************************************************************
5286 Fill in the sprite array for the given tile, city, and unit.
5288 ptile, if specified, gives the tile. If specified the terrain and specials
5289 will be drawn for this tile. In this case (map_x,map_y) should give the
5290 location of the tile.
5292 punit, if specified, gives the unit. For tile drawing this should
5293 generally be get_drawable_unit(); otherwise it can be any unit.
5295 pcity, if specified, gives the city. For tile drawing this should
5296 generally be tile_city(ptile); otherwise it can be any city.
5298 citymode specifies whether this is part of a citydlg. If so some drawing
5299 is done differently.
5300 ****************************************************************************/
5301 int fill_sprite_array(struct tileset
*t
,
5302 struct drawn_sprite
*sprs
, enum mapview_layer layer
,
5303 const struct tile
*ptile
,
5304 const struct tile_edge
*pedge
,
5305 const struct tile_corner
*pcorner
,
5306 const struct unit
*punit
, const struct city
*pcity
,
5307 const struct city
*citymode
,
5308 const struct unit_type
*putype
)
5311 bv_extras textras_near
[8];
5313 struct terrain
*tterrain_near
[8];
5314 struct terrain
*pterrain
= NULL
;
5315 struct drawn_sprite
*save_sprs
= sprs
;
5316 struct player
*owner
= NULL
;
5317 /* Unit drawing is disabled when the view options are turned off,
5318 * but only where we're drawing on the mapview. */
5319 bool do_draw_unit
= (punit
&& (gui_options
.draw_units
|| !ptile
5320 || (gui_options
.draw_focus_unit
5321 && unit_is_in_focus(punit
))));
5322 bool solid_bg
= (gui_options
.solid_color_behind_units
5324 || (pcity
&& gui_options
.draw_cities
)
5325 || (ptile
&& !gui_options
.draw_terrain
)));
5328 int count
= 0, i
, cx
, cy
;
5329 const struct tile
*const *tiles
= NULL
;
5335 } else if (pcorner
) {
5336 tiles
= pcorner
->tile
;
5337 count
= NUM_CORNER_TILES
;
5339 tiles
= pedge
->tile
;
5340 count
= NUM_EDGE_TILES
;
5343 for (i
= 0; i
< count
; i
++) {
5344 if (tiles
[i
] && city_base_to_city_map(&cx
, &cy
, citymode
, tiles
[i
])) {
5354 if (ptile
&& client_tile_get_known(ptile
) != TILE_UNKNOWN
) {
5355 textras
= *tile_extras(ptile
);
5356 pterrain
= tile_terrain(ptile
);
5358 if (NULL
!= pterrain
) {
5359 if (layer
== LAYER_TERRAIN1
5360 || layer
== LAYER_TERRAIN2
5361 || layer
== LAYER_TERRAIN3
5362 || layer
== LAYER_WATER
5363 || layer
== LAYER_ROADS
) {
5364 build_tile_data(ptile
, pterrain
, tterrain_near
, textras_near
);
5367 log_error("fill_sprite_array() tile (%d,%d) has no terrain!",
5371 BV_CLR_ALL(textras
);
5375 case LAYER_BACKGROUND
:
5376 /* Set up background color. */
5377 if (gui_options
.solid_color_behind_units
) {
5379 owner
= unit_owner(punit
);
5380 } else if (pcity
&& gui_options
.draw_cities
) {
5381 owner
= city_owner(pcity
);
5385 ADD_SPRITE_SIMPLE(t
->sprites
.player
[player_index(owner
)].background
);
5386 } else if (ptile
&& !gui_options
.draw_terrain
) {
5387 ADD_SPRITE_SIMPLE(t
->sprites
.background
.graphic
);
5391 case LAYER_TERRAIN1
:
5392 if (NULL
!= pterrain
&& gui_options
.draw_terrain
&& !solid_bg
) {
5393 sprs
+= fill_terrain_sprite_layer(t
, sprs
, 0, ptile
, pterrain
, tterrain_near
);
5397 case LAYER_TERRAIN2
:
5398 if (NULL
!= pterrain
&& gui_options
.draw_terrain
&& !solid_bg
) {
5399 sprs
+= fill_terrain_sprite_layer(t
, sprs
, 1, ptile
, pterrain
, tterrain_near
);
5403 case LAYER_TERRAIN3
:
5404 if (NULL
!= pterrain
&& gui_options
.draw_terrain
&& !solid_bg
) {
5405 fc_assert(MAX_NUM_LAYERS
== 3);
5406 sprs
+= fill_terrain_sprite_layer(t
, sprs
, 2, ptile
, pterrain
, tterrain_near
);
5411 if (NULL
!= pterrain
) {
5412 if (gui_options
.draw_terrain
&& !solid_bg
5413 && terrain_type_terrain_class(pterrain
) == TC_OCEAN
) {
5414 for (dir
= 0; dir
< t
->num_cardinal_tileset_dirs
; dir
++) {
5415 int didx
= t
->cardinal_tileset_dirs
[dir
];
5417 extra_type_list_iterate(t
->style_lists
[ESTYLE_RIVER
], priver
) {
5418 int idx
= extra_index(priver
);
5420 if (BV_ISSET(textras_near
[didx
], idx
)) {
5421 if (t
->sprites
.extras
[idx
].u
.road
.ru
.rivers
.outlet
[dir
] != NULL
) {
5422 ADD_SPRITE_SIMPLE(t
->sprites
.extras
[idx
].u
.road
.ru
.rivers
.outlet
[dir
]);
5426 } extra_type_list_iterate_end
;
5430 sprs
+= fill_irrigation_sprite_array(t
, sprs
, textras
, textras_near
,
5433 if (gui_options
.draw_terrain
&& !solid_bg
) {
5434 extra_type_list_iterate(t
->style_lists
[ESTYLE_RIVER
], priver
) {
5435 int idx
= extra_index(priver
);
5437 if (BV_ISSET(textras
, idx
)) {
5440 /* Draw rivers on top of irrigation. */
5442 for (i
= 0; i
< t
->num_cardinal_tileset_dirs
; i
++) {
5443 enum direction8 cdir
= t
->cardinal_tileset_dirs
[i
];
5445 if (terrain_type_terrain_class(tterrain_near
[cdir
]) == TC_OCEAN
5446 || BV_ISSET(textras_near
[cdir
], idx
)) {
5451 ADD_SPRITE_SIMPLE(t
->sprites
.extras
[idx
].u
.road
.ru
.rivers
.spec
[tileno
]);
5453 } extra_type_list_iterate_end
;
5459 if (NULL
!= pterrain
) {
5460 extra_type_list_iterate(t
->style_lists
[ESTYLE_ROAD_ALL_SEPARATE
], pextra
) {
5461 if (is_extra_drawing_enabled(pextra
)) {
5462 sprs
+= fill_road_sprite_array(t
, pextra
, sprs
,
5463 textras
, textras_near
,
5464 tterrain_near
, pcity
);
5466 } extra_type_list_iterate_end
;
5467 extra_type_list_iterate(t
->style_lists
[ESTYLE_ROAD_PARITY_COMBINED
], pextra
) {
5468 if (is_extra_drawing_enabled(pextra
)) {
5469 sprs
+= fill_road_sprite_array(t
, pextra
, sprs
,
5470 textras
, textras_near
,
5471 tterrain_near
, pcity
);
5473 } extra_type_list_iterate_end
;
5474 extra_type_list_iterate(t
->style_lists
[ESTYLE_ROAD_ALL_COMBINED
], pextra
) {
5475 if (is_extra_drawing_enabled(pextra
)) {
5476 sprs
+= fill_road_sprite_array(t
, pextra
, sprs
,
5477 textras
, textras_near
,
5478 tterrain_near
, pcity
);
5480 } extra_type_list_iterate_end
;
5484 case LAYER_SPECIAL1
:
5485 if (NULL
!= pterrain
) {
5486 if (gui_options
.draw_specials
) {
5487 if (tile_resource_is_valid(ptile
)) {
5488 ADD_SPRITE_SIMPLE(t
->sprites
.resource
[resource_index(tile_resource(ptile
))]);
5493 extra_type_list_iterate(t
->style_lists
[ESTYLE_3LAYER
], pextra
) {
5494 if (tile_has_extra(ptile
, pextra
)
5495 && is_extra_drawing_enabled(pextra
)
5496 && t
->sprites
.extras
[extra_index(pextra
)].u
.bmf
.background
) {
5497 bool hidden
= FALSE
;
5499 extra_type_list_iterate(pextra
->hiders
, phider
) {
5500 if (BV_ISSET(textras
, extra_index(phider
))) {
5504 } extra_type_list_iterate_end
;
5507 ADD_SPRITE_FULL(t
->sprites
.extras
[extra_index(pextra
)].u
.bmf
.background
);
5510 } extra_type_list_iterate_end
;
5513 extra_type_list_iterate(t
->style_lists
[ESTYLE_SINGLE1
], pextra
) {
5514 if (BV_ISSET(textras
, extra_index(pextra
))
5515 && is_extra_drawing_enabled(pextra
)) {
5516 bool hidden
= FALSE
;
5518 extra_type_list_iterate(pextra
->hiders
, phider
) {
5519 if (BV_ISSET(textras
, extra_index(phider
))) {
5523 } extra_type_list_iterate_end
;
5526 ADD_SPRITE_SIMPLE(t
->sprites
.extras
[extra_index(pextra
)].u
.single
);
5529 } extra_type_list_iterate_end
;
5534 if (t
->type
== TS_ISOMETRIC
) {
5535 sprs
+= fill_grid_sprite_array(t
, sprs
, ptile
, pedge
, pcorner
,
5536 punit
, pcity
, citymode
);
5541 /* City. Some city sprites are drawn later. */
5542 if (pcity
&& gui_options
.draw_cities
) {
5543 if (!gui_options
.draw_full_citybar
&& !gui_options
.solid_color_behind_units
) {
5544 ADD_SPRITE(get_city_flag_sprite(t
, pcity
), TRUE
,
5545 FULL_TILE_X_OFFSET
+ t
->city_flag_offset_x
,
5546 FULL_TILE_Y_OFFSET
+ t
->city_flag_offset_y
);
5548 /* For iso-view the city.wall graphics include the full city, whereas
5549 * for non-iso view they are an overlay on top of the base city
5551 if (t
->type
== TS_OVERHEAD
|| pcity
->client
.walls
<= 0) {
5552 ADD_SPRITE(get_city_sprite(t
->sprites
.city
.tile
, pcity
), TRUE
,
5553 FULL_TILE_X_OFFSET
+ t
->city_offset_x
,
5554 FULL_TILE_Y_OFFSET
+ t
->city_offset_y
);
5556 if (t
->type
== TS_ISOMETRIC
&& pcity
->client
.walls
> 0) {
5557 struct city_sprite
*cspr
= t
->sprites
.city
.wall
[pcity
->client
.walls
- 1];
5558 struct sprite
*spr
= NULL
;
5561 spr
= get_city_sprite(cspr
, pcity
);
5564 cspr
= t
->sprites
.city
.single_wall
;
5566 spr
= get_city_sprite(cspr
, pcity
);
5571 ADD_SPRITE(spr
, TRUE
,
5572 FULL_TILE_X_OFFSET
+ t
->city_offset_x
,
5573 FULL_TILE_Y_OFFSET
+ t
->city_offset_y
);
5576 if (!gui_options
.draw_full_citybar
&& pcity
->client
.occupied
) {
5577 ADD_SPRITE(get_city_sprite(t
->sprites
.city
.occupied
, pcity
), TRUE
,
5578 FULL_TILE_X_OFFSET
+ t
->occupied_offset_x
,
5579 FULL_TILE_Y_OFFSET
+ t
->occupied_offset_y
);
5581 if (t
->type
== TS_OVERHEAD
&& pcity
->client
.walls
> 0) {
5582 struct city_sprite
*cspr
= t
->sprites
.city
.wall
[pcity
->client
.walls
- 1];
5583 struct sprite
*spr
= NULL
;
5586 spr
= get_city_sprite(cspr
, pcity
);
5589 cspr
= t
->sprites
.city
.single_wall
;
5591 spr
= get_city_sprite(cspr
, pcity
);
5596 ADD_SPRITE_FULL(spr
);
5599 if (pcity
->client
.unhappy
) {
5600 ADD_SPRITE_FULL(t
->sprites
.city
.disorder
);
5605 case LAYER_SPECIAL2
:
5606 if (NULL
!= pterrain
) {
5608 extra_type_list_iterate(t
->style_lists
[ESTYLE_3LAYER
], pextra
) {
5609 if (tile_has_extra(ptile
, pextra
)
5610 && is_extra_drawing_enabled(pextra
)
5611 && t
->sprites
.extras
[extra_index(pextra
)].u
.bmf
.middleground
) {
5612 bool hidden
= FALSE
;
5614 extra_type_list_iterate(pextra
->hiders
, phider
) {
5615 if (BV_ISSET(textras
, extra_index(phider
))) {
5619 } extra_type_list_iterate_end
;
5622 ADD_SPRITE_FULL(t
->sprites
.extras
[extra_index(pextra
)].u
.bmf
.middleground
);
5625 } extra_type_list_iterate_end
;
5628 extra_type_list_iterate(t
->style_lists
[ESTYLE_SINGLE2
], pextra
) {
5629 if (BV_ISSET(textras
, extra_index(pextra
))
5630 && is_extra_drawing_enabled(pextra
)) {
5631 bool hidden
= FALSE
;
5633 extra_type_list_iterate(pextra
->hiders
, phider
) {
5634 if (BV_ISSET(textras
, extra_index(phider
))) {
5638 } extra_type_list_iterate_end
;
5641 ADD_SPRITE_SIMPLE(t
->sprites
.extras
[extra_index(pextra
)].u
.single
);
5644 } extra_type_list_iterate_end
;
5649 case LAYER_FOCUS_UNIT
:
5650 if (do_draw_unit
&& XOR(layer
== LAYER_UNIT
, unit_is_in_focus(punit
))) {
5651 bool stacked
= ptile
&& (unit_list_size(ptile
->units
) > 1);
5652 bool backdrop
= !pcity
;
5654 if (ptile
&& unit_is_in_focus(punit
)
5655 && t
->sprites
.unit
.select
[0]) {
5656 /* Special case for drawing the selection rectangle. The blinking
5657 * unit is handled separately, inside get_drawable_unit(). */
5658 ADD_SPRITE_SIMPLE(t
->sprites
.unit
.select
[focus_unit_state
]);
5661 sprs
+= fill_unit_sprite_array(t
, sprs
, punit
, stacked
, backdrop
);
5662 } else if (putype
!= NULL
&& layer
== LAYER_UNIT
) {
5663 /* Only the sprite for the unit type. */
5664 sprs
+= fill_unit_type_sprite_array(t
, sprs
, putype
,
5665 direction8_invalid());
5669 case LAYER_SPECIAL3
:
5670 if (NULL
!= pterrain
) {
5672 bool show_flag
= FALSE
;
5673 struct player
*eowner
= extra_owner(ptile
);
5675 extra_type_list_iterate(t
->style_lists
[ESTYLE_3LAYER
], pextra
) {
5676 if (is_extra_drawing_enabled(pextra
)
5677 && tile_has_extra(ptile
, pextra
)
5678 && t
->sprites
.extras
[extra_index(pextra
)].u
.bmf
.foreground
) {
5679 bool hidden
= FALSE
;
5681 extra_type_list_iterate(pextra
->hiders
, phider
) {
5682 if (BV_ISSET(textras
, extra_index(phider
))) {
5686 } extra_type_list_iterate_end
;
5689 if (t
->sprites
.extras
[extra_index(pextra
)].u
.bmf
.foreground
) {
5690 ADD_SPRITE_FULL(t
->sprites
.extras
[extra_index(pextra
)].u
.bmf
.foreground
);
5694 } extra_type_list_iterate_end
;
5696 /* Show base flag. Not part of previous iteration as
5697 * "extras of ESTYLE_3_LAYER" != "bases" */
5698 if (eowner
!= NULL
) {
5699 extra_type_list_iterate(t
->flagged_bases_list
, pextra
) {
5700 if (tile_has_extra(ptile
, pextra
)) {
5701 bool hidden
= FALSE
;
5703 extra_type_list_iterate(pextra
->hiders
, phider
) {
5704 if (BV_ISSET(textras
, extra_index(phider
))) {
5708 } extra_type_list_iterate_end
;
5714 } extra_type_list_iterate_end
;
5717 ADD_SPRITE(get_nation_flag_sprite(t
, nation_of_player(eowner
)), TRUE
,
5718 FULL_TILE_X_OFFSET
+ t
->city_flag_offset_x
,
5719 FULL_TILE_Y_OFFSET
+ t
->city_flag_offset_y
);
5727 sprs
+= fill_fog_sprite_array(t
, sprs
, ptile
, pedge
, pcorner
);
5731 /* City size. Drawing this under fog makes it hard to read. */
5732 if (pcity
&& gui_options
.draw_cities
&& !gui_options
.draw_full_citybar
) {
5735 ADD_SPRITE(t
->sprites
.city
.size
[city_size_get(pcity
) % 10],
5736 FALSE
, FULL_TILE_X_OFFSET
, FULL_TILE_Y_OFFSET
);
5737 if (10 <= city_size_get(pcity
)) {
5738 ADD_SPRITE(t
->sprites
.city
.size_tens
[(city_size_get(pcity
) / 10)
5739 % 10], FALSE
, FULL_TILE_X_OFFSET
, FULL_TILE_Y_OFFSET
);
5740 if (100 <= city_size_get(pcity
)) {
5741 struct sprite
*sprite
=
5742 t
->sprites
.city
.size_hundreds
[(city_size_get(pcity
) / 100) % 10];
5744 if (NULL
!= sprite
) {
5745 ADD_SPRITE(sprite
, FALSE
,
5746 FULL_TILE_X_OFFSET
, FULL_TILE_Y_OFFSET
);
5750 if (1000 <= city_size_get(pcity
)) {
5757 /* Warn only once by tileset. */
5758 static char last_reported
[256] = "";
5760 if (0 != strcmp(last_reported
, t
->name
)) {
5761 log_normal(_("Tileset \"%s\" doesn't support big cities size, "
5762 "such as %d. Size not displayed as expected."),
5763 t
->name
, city_size_get(pcity
));
5764 sz_strlcpy(last_reported
, t
->name
);
5771 if (t
->type
== TS_OVERHEAD
) {
5772 sprs
+= fill_grid_sprite_array(t
, sprs
, ptile
, pedge
, pcorner
,
5773 punit
, pcity
, citymode
);
5777 case LAYER_OVERLAYS
:
5778 sprs
+= fill_city_overlays_sprite_array(t
, sprs
, ptile
, citymode
);
5779 if (mapdeco_is_crosshair_set(ptile
)) {
5780 ADD_SPRITE_SIMPLE(t
->sprites
.user
.attention
);
5785 case LAYER_TILELABEL
:
5786 /* Nothing. This is just a placeholder. */
5790 if (ptile
&& goto_is_active()) {
5791 sprs
+= fill_goto_sprite_array(t
, sprs
, ptile
, pedge
, pcorner
);
5795 case LAYER_WORKERTASK
:
5796 if (citymode
!= NULL
&& ptile
!= NULL
) {
5797 worker_task_list_iterate(citymode
->task_reqs
, ptask
) {
5798 if (ptask
->ptile
== ptile
) {
5799 switch (ptask
->act
) {
5801 if (ptask
->tgt
== NULL
) {
5802 ADD_SPRITE_SIMPLE(t
->sprites
.unit
.plant
);
5804 ADD_SPRITE_SIMPLE(t
->sprites
.extras
[extra_index(ptask
->tgt
)].activity
);
5807 case ACTIVITY_IRRIGATE
:
5808 if (ptask
->tgt
== NULL
) {
5809 ADD_SPRITE_SIMPLE(t
->sprites
.unit
.irrigate
);
5811 ADD_SPRITE_SIMPLE(t
->sprites
.extras
[extra_index(ptask
->tgt
)].activity
);
5814 case ACTIVITY_GEN_ROAD
:
5815 ADD_SPRITE_SIMPLE(t
->sprites
.extras
[extra_index(ptask
->tgt
)].activity
);
5817 case ACTIVITY_TRANSFORM
:
5818 ADD_SPRITE_SIMPLE(t
->sprites
.unit
.transform
);
5824 } worker_task_list_iterate_end
;
5829 if (ptile
&& editor_is_active()) {
5830 if (editor_tile_is_selected(ptile
)) {
5831 int color
= 2 % tileset_num_city_colors(tileset
);
5832 ADD_SPRITE_SIMPLE(t
->sprites
.city
.unworked_tile_overlay
.p
[color
]);
5835 if (NULL
!= map_startpos_get(ptile
)) {
5836 /* FIXME: Use a more representative sprite. */
5837 ADD_SPRITE_SIMPLE(t
->sprites
.user
.attention
);
5847 return sprs
- save_sprs
;
5850 /**********************************************************************
5851 Set city tiles sprite values; should only happen after
5852 tilespec_load_tiles().
5853 ***********************************************************************/
5854 void tileset_setup_city_tiles(struct tileset
*t
, int style
)
5856 if (style
== game
.control
.styles_count
- 1) {
5859 /* Free old sprites */
5860 free_city_sprite(t
->sprites
.city
.tile
);
5862 for (i
= 0; i
< NUM_WALL_TYPES
; i
++) {
5863 free_city_sprite(t
->sprites
.city
.wall
[i
]);
5864 t
->sprites
.city
.wall
[i
] = NULL
;
5866 free_city_sprite(t
->sprites
.city
.single_wall
);
5867 t
->sprites
.city
.single_wall
= NULL
;
5869 free_city_sprite(t
->sprites
.city
.occupied
);
5871 t
->sprites
.city
.tile
= load_city_sprite(t
, "city");
5873 for (i
= 0; i
< NUM_WALL_TYPES
; i
++) {
5876 fc_snprintf(buffer
, sizeof(buffer
), "bldg_%d", i
);
5877 t
->sprites
.city
.wall
[i
] = load_city_sprite(t
, buffer
);
5879 t
->sprites
.city
.single_wall
= load_city_sprite(t
, "wall");
5881 t
->sprites
.city
.occupied
= load_city_sprite(t
, "occupied");
5883 for (style
= 0; style
< game
.control
.styles_count
; style
++) {
5884 if (t
->sprites
.city
.tile
->styles
[style
].land_num_thresholds
== 0) {
5885 tileset_error(LOG_FATAL
, _("City style \"%s\": no city graphics."),
5886 city_style_rule_name(style
));
5888 if (t
->sprites
.city
.occupied
->styles
[style
].land_num_thresholds
== 0) {
5889 tileset_error(LOG_FATAL
, _("City style \"%s\": no occupied graphics."),
5890 city_style_rule_name(style
));
5896 /****************************************************************************
5897 Return the amount of time between calls to toggle_focus_unit_state.
5898 The main loop needs to call toggle_focus_unit_state about this often
5899 to do the active-unit animation.
5900 ****************************************************************************/
5901 double get_focus_unit_toggle_timeout(const struct tileset
*t
)
5903 if (t
->sprites
.unit
.select
[0]) {
5910 /****************************************************************************
5911 Reset the focus unit state. This should be called when changing
5913 ****************************************************************************/
5914 void reset_focus_unit_state(struct tileset
*t
)
5916 focus_unit_state
= 0;
5919 /****************************************************************************
5920 Setup tileset for showing combat where focus unit participates.
5921 ****************************************************************************/
5922 void focus_unit_in_combat(struct tileset
*t
)
5924 if (!t
->sprites
.unit
.select
[0]) {
5925 reset_focus_unit_state(t
);
5929 /****************************************************************************
5930 Toggle/increment the focus unit state. This should be called once
5931 every get_focus_unit_toggle_timeout() seconds.
5932 ****************************************************************************/
5933 void toggle_focus_unit_state(struct tileset
*t
)
5936 if (t
->sprites
.unit
.select
[0]) {
5937 focus_unit_state
%= NUM_TILES_SELECT
;
5939 focus_unit_state
%= 2;
5943 /**********************************************************************
5944 Find unit that we can display from given tile.
5945 ***********************************************************************/
5946 struct unit
*get_drawable_unit(const struct tileset
*t
,
5948 const struct city
*citymode
)
5950 struct unit
*punit
= find_visible_unit(ptile
);
5952 if (punit
== NULL
) {
5956 if (citymode
&& unit_owner(punit
) == city_owner(citymode
)) {
5960 if (!unit_is_in_focus(punit
)
5961 || t
->sprites
.unit
.select
[0] || focus_unit_state
== 0) {
5968 /****************************************************************************
5969 This patch unloads all sprites from the sprite hash (the hash itself
5971 ****************************************************************************/
5972 static void unload_all_sprites(struct tileset
*t
)
5974 if (t
->sprite_hash
) {
5975 sprite_hash_iterate(t
->sprite_hash
, tag_name
, ss
) {
5976 while (ss
->ref_count
> 0) {
5977 unload_sprite(t
, tag_name
);
5979 } sprite_hash_iterate_end
;
5983 /**********************************************************************
5984 Free all sprites from tileset.
5985 ***********************************************************************/
5986 void tileset_free_tiles(struct tileset
*t
)
5990 log_debug("tileset_free_tiles()");
5992 unload_all_sprites(t
);
5994 free_city_sprite(t
->sprites
.city
.tile
);
5995 t
->sprites
.city
.tile
= NULL
;
5997 for (i
= 0; i
< NUM_WALL_TYPES
; i
++) {
5998 free_city_sprite(t
->sprites
.city
.wall
[i
]);
5999 t
->sprites
.city
.wall
[i
] = NULL
;
6001 free_city_sprite(t
->sprites
.city
.single_wall
);
6002 t
->sprites
.city
.single_wall
= NULL
;
6004 free_city_sprite(t
->sprites
.city
.occupied
);
6005 t
->sprites
.city
.occupied
= NULL
;
6007 if (t
->sprite_hash
) {
6008 sprite_hash_destroy(t
->sprite_hash
);
6009 t
->sprite_hash
= NULL
;
6012 small_sprite_list_iterate(t
->small_sprites
, ss
) {
6013 small_sprite_list_remove(t
->small_sprites
, ss
);
6017 fc_assert(ss
->sprite
== NULL
);
6019 } small_sprite_list_iterate_end
;
6021 specfile_list_iterate(t
->specfiles
, sf
) {
6022 specfile_list_remove(t
->specfiles
, sf
);
6023 free(sf
->file_name
);
6024 if (sf
->big_sprite
) {
6025 free_sprite(sf
->big_sprite
);
6026 sf
->big_sprite
= NULL
;
6029 } specfile_list_iterate_end
;
6031 sprite_vector_iterate(&t
->sprites
.city
.worked_tile_overlay
, psprite
) {
6032 free_sprite(*psprite
);
6033 } sprite_vector_iterate_end
;
6034 sprite_vector_free(&t
->sprites
.city
.worked_tile_overlay
);
6036 sprite_vector_iterate(&t
->sprites
.city
.unworked_tile_overlay
, psprite
) {
6037 free_sprite(*psprite
);
6038 } sprite_vector_iterate_end
;
6039 sprite_vector_free(&t
->sprites
.city
.unworked_tile_overlay
);
6041 if (t
->sprites
.tx
.fullfog
) {
6042 free(t
->sprites
.tx
.fullfog
);
6043 t
->sprites
.tx
.fullfog
= NULL
;
6046 sprite_vector_free(&t
->sprites
.colors
.overlays
);
6047 sprite_vector_free(&t
->sprites
.explode
.unit
);
6048 sprite_vector_free(&t
->sprites
.nation_flag
);
6049 sprite_vector_free(&t
->sprites
.nation_shield
);
6050 sprite_vector_free(&t
->sprites
.citybar
.occupancy
);
6052 tileset_background_free(t
);
6055 /**************************************************************************
6056 Return the sprite for drawing the given spaceship part.
6057 **************************************************************************/
6058 struct sprite
*get_spaceship_sprite(const struct tileset
*t
,
6059 enum spaceship_part part
)
6061 return t
->sprites
.spaceship
[part
];
6064 /**************************************************************************
6065 Return a sprite for the given citizen. The citizen's type is given,
6066 as well as their index (in the range [0..city_size_get(pcity))). The
6067 citizen's city can be used to determine which sprite to use (a NULL
6068 value indicates there is no city; i.e., the sprite is just being
6070 **************************************************************************/
6071 struct sprite
*get_citizen_sprite(const struct tileset
*t
,
6072 enum citizen_category type
,
6074 const struct city
*pcity
)
6076 const struct citizen_graphic
*graphic
;
6077 int gfx_index
= citizen_index
;
6079 if (pcity
!= NULL
) {
6080 gfx_index
+= pcity
->client
.first_citizen_index
;
6083 if (type
< CITIZEN_SPECIALIST
) {
6084 fc_assert(type
>= 0);
6085 graphic
= &t
->sprites
.citizen
[type
];
6087 fc_assert(type
< (CITIZEN_SPECIALIST
+ SP_MAX
));
6088 graphic
= &t
->sprites
.specialist
[type
- CITIZEN_SPECIALIST
];
6091 if (graphic
->count
== 0) {
6095 return graphic
->sprite
[gfx_index
% graphic
->count
];
6098 /**************************************************************************
6099 Return the sprite for the nation.
6100 **************************************************************************/
6101 struct sprite
*get_nation_flag_sprite(const struct tileset
*t
,
6102 const struct nation_type
*pnation
)
6104 return t
->sprites
.nation_flag
.p
[nation_index(pnation
)];
6107 /**************************************************************************
6108 Return the shield sprite for the nation.
6109 **************************************************************************/
6110 struct sprite
*get_nation_shield_sprite(const struct tileset
*t
,
6111 const struct nation_type
*pnation
)
6113 return t
->sprites
.nation_shield
.p
[nation_index(pnation
)];
6116 /**************************************************************************
6117 Return the sprite for the technology/advance.
6118 **************************************************************************/
6119 struct sprite
*get_tech_sprite(const struct tileset
*t
, Tech_type_id tech
)
6121 fc_assert_ret_val(0 <= tech
&& tech
< advance_count(), NULL
);
6122 return t
->sprites
.tech
[tech
];
6125 /**************************************************************************
6126 Return the sprite for the building/improvement.
6127 **************************************************************************/
6128 struct sprite
*get_building_sprite(const struct tileset
*t
,
6129 struct impr_type
*pimprove
)
6131 fc_assert_ret_val(NULL
!= pimprove
, NULL
);
6132 return t
->sprites
.building
[improvement_index(pimprove
)];
6135 /****************************************************************************
6136 Return the sprite for the government.
6137 ****************************************************************************/
6138 struct sprite
*get_government_sprite(const struct tileset
*t
,
6139 const struct government
*gov
)
6141 fc_assert_ret_val(NULL
!= gov
, NULL
);
6142 return t
->sprites
.government
[government_index(gov
)];
6145 /****************************************************************************
6146 Return the sprite for the unit type (the base "unit" sprite).
6147 ****************************************************************************/
6148 struct sprite
*get_unittype_sprite(const struct tileset
*t
,
6149 const struct unit_type
*punittype
,
6150 enum direction8 facing
,
6153 int uidx
= utype_index(punittype
);
6155 fc_assert_ret_val(NULL
!= punittype
, NULL
);
6157 if (!direction8_is_valid(facing
) || !is_valid_dir(facing
)) {
6158 /* Fallback to random orientation sprite.
6159 * The randomness was fixed at tileset load time for stability
6160 * (in tileset_setup_unit_type_from_tag()); here we need to adapt
6161 * that to the map topology (which is now known).
6162 * default_dir_seed was set to give uniform distribution for either
6163 * 6 or 8 valid directions.
6164 * Thus this direction is stable for a given unit type unless the
6165 * map topology changes. */
6166 unsigned int dir_index
;
6168 fc_assert_ret_val(game
.map
.num_valid_dirs
> 0, NULL
);
6170 = t
->sprites
.units
.default_dir_seed
[uidx
] % game
.map
.num_valid_dirs
;
6171 facing
= game
.map
.valid_dirs
[dir_index
];
6172 fc_assert_ret_val(is_valid_dir(facing
), NULL
);
6175 if (t
->sprites
.units
.icon
[uidx
]
6176 && (icon
|| t
->sprites
.units
.facing
[uidx
][facing
] == NULL
)) {
6177 /* Has icon sprite */
6178 return t
->sprites
.units
.icon
[uidx
];
6180 return t
->sprites
.units
.facing
[uidx
][facing
];
6184 /**************************************************************************
6185 Return a "sample" sprite for this city style.
6186 **************************************************************************/
6187 struct sprite
*get_sample_city_sprite(const struct tileset
*t
,
6190 int num_thresholds
=
6191 t
->sprites
.city
.tile
->styles
[style_idx
].land_num_thresholds
;
6193 if (num_thresholds
== 0) {
6196 return (t
->sprites
.city
.tile
->styles
[style_idx
]
6197 .land_thresholds
[num_thresholds
- 1].sprite
);
6201 /**************************************************************************
6202 Return a sprite with an "arrow" theme graphic.
6203 **************************************************************************/
6204 struct sprite
*get_arrow_sprite(const struct tileset
*t
,
6205 enum arrow_type arrow
)
6207 fc_assert_ret_val(arrow
>= 0 && arrow
< ARROW_LAST
, NULL
);
6209 return t
->sprites
.arrow
[arrow
];
6212 /**************************************************************************
6213 Return a tax sprite for the given output type (usually gold/lux/sci).
6214 **************************************************************************/
6215 struct sprite
*get_tax_sprite(const struct tileset
*t
, Output_type_id otype
)
6219 return t
->sprites
.tax_science
;
6221 return t
->sprites
.tax_gold
;
6223 return t
->sprites
.tax_luxury
;
6233 /**************************************************************************
6234 Return event icon sprite
6235 **************************************************************************/
6236 struct sprite
*get_event_sprite(const struct tileset
*t
, enum event_type event
)
6238 return t
->sprites
.events
[event
];
6241 /**************************************************************************
6242 Return a thumbs-up/thumbs-down sprite to show treaty approval or
6244 **************************************************************************/
6245 struct sprite
*get_treaty_thumb_sprite(const struct tileset
*t
, bool on_off
)
6247 return t
->sprites
.treaty_thumb
[on_off
? 1 : 0];
6250 /**************************************************************************
6251 Return a sprite_vector containing the animation sprites for a unit
6253 **************************************************************************/
6254 const struct sprite_vector
*get_unit_explode_animation(const struct
6257 return &t
->sprites
.explode
.unit
;
6260 /****************************************************************************
6261 Return a sprite contining the single nuke graphic.
6263 TODO: This should be an animation like the unit explode animation.
6264 ****************************************************************************/
6265 struct sprite
*get_nuke_explode_sprite(const struct tileset
*t
)
6267 return t
->sprites
.explode
.nuke
;
6270 /**************************************************************************
6271 Return all the sprites used for city bar drawing.
6272 **************************************************************************/
6273 const struct citybar_sprites
*get_citybar_sprites(const struct tileset
*t
)
6275 if (gui_options
.draw_full_citybar
) {
6276 return &t
->sprites
.citybar
;
6282 /**************************************************************************
6283 Return all the sprites used for editor icons, images, etc.
6284 **************************************************************************/
6285 const struct editor_sprites
*get_editor_sprites(const struct tileset
*t
)
6287 return &t
->sprites
.editor
;
6290 /**************************************************************************
6291 Returns a sprite for the given cursor. The "hot" coordinates (the
6292 active coordinates of the mouse relative to the sprite) are placed int
6294 A cursor can consist of several frames to be used for animation.
6295 **************************************************************************/
6296 struct sprite
*get_cursor_sprite(const struct tileset
*t
,
6297 enum cursor_type cursor
,
6298 int *hot_x
, int *hot_y
, int frame
)
6300 *hot_x
= t
->sprites
.cursor
[cursor
].hot_x
;
6301 *hot_y
= t
->sprites
.cursor
[cursor
].hot_y
;
6302 return t
->sprites
.cursor
[cursor
].frame
[frame
];
6305 /****************************************************************************
6306 Return a sprite for the given icon. Icons are used by the operating
6307 system/window manager. Usually freeciv has to tell the OS what icon to
6310 Note that this function will return NULL before the sprites are loaded.
6311 The GUI code must be sure to call tileset_load_tiles before setting the
6313 ****************************************************************************/
6314 struct sprite
*get_icon_sprite(const struct tileset
*t
, enum icon_type icon
)
6316 return t
->sprites
.icon
[icon
];
6319 /****************************************************************************
6320 Returns a sprite with the "user-attention" crosshair graphic.
6322 FIXME: This function shouldn't be needed if the attention graphics are
6323 drawn natively by the tileset code.
6324 ****************************************************************************/
6325 struct sprite
*get_attention_crosshair_sprite(const struct tileset
*t
)
6327 return t
->sprites
.user
.attention
;
6330 /****************************************************************************
6331 Returns a sprite for the given indicator with the given index. The
6332 index should be in [0, NUM_TILES_PROGRESS).
6333 ****************************************************************************/
6334 struct sprite
*get_indicator_sprite(const struct tileset
*t
,
6335 enum indicator_type indicator
,
6338 idx
= CLIP(0, idx
, NUM_TILES_PROGRESS
- 1);
6340 fc_assert_ret_val(indicator
>= 0 && indicator
< INDICATOR_COUNT
, NULL
);
6342 return t
->sprites
.indicator
[indicator
][idx
];
6345 /****************************************************************************
6346 Return a sprite for the unhappiness of the unit - to be shown as an
6347 overlay on the unit in the city support dialog, for instance.
6349 May return NULL if there's no unhappiness.
6350 ****************************************************************************/
6351 struct sprite
*get_unit_unhappy_sprite(const struct tileset
*t
,
6352 const struct unit
*punit
,
6355 const int unhappy
= CLIP(0, happy_cost
, MAX_NUM_UPKEEP_SPRITES
+1);
6358 return t
->sprites
.upkeep
.unhappy
[unhappy
- 1];
6364 /****************************************************************************
6365 Return a sprite for the upkeep of the unit - to be shown as an overlay
6366 on the unit in the city support dialog, for instance.
6368 May return NULL if there's no upkeep of the kind.
6369 ****************************************************************************/
6370 struct sprite
*get_unit_upkeep_sprite(const struct tileset
*t
,
6371 Output_type_id otype
,
6372 const struct unit
*punit
,
6373 const int *upkeep_cost
)
6375 const int upkeep
= CLIP(0, upkeep_cost
[otype
], MAX_NUM_UPKEEP_SPRITES
+ 1);
6378 return t
->sprites
.upkeep
.output
[otype
][upkeep
- 1];
6384 /****************************************************************************
6385 Return a rectangular sprite containing a fog "color". This can be used
6386 for drawing fog onto arbitrary areas (like the overview).
6387 ****************************************************************************/
6388 struct sprite
*get_basic_fog_sprite(const struct tileset
*t
)
6390 return t
->sprites
.tx
.fog
;
6393 /****************************************************************************
6394 Return the tileset's color system.
6395 ****************************************************************************/
6396 struct color_system
*get_color_system(const struct tileset
*t
)
6398 return t
->color_system
;
6401 /****************************************************************************
6402 Loads preferred theme if there's any.
6403 ****************************************************************************/
6404 void tileset_use_preferred_theme(const struct tileset
*t
)
6406 char *default_theme_name
= NULL
;
6407 size_t default_theme_name_sz
= 0;
6410 switch (get_gui_type()) {
6412 default_theme_name
= gui_options
.gui_gtk2_default_theme_name
;
6413 default_theme_name_sz
= sizeof(gui_options
.gui_gtk2_default_theme_name
);
6416 default_theme_name
= gui_options
.gui_gtk3_default_theme_name
;
6417 default_theme_name_sz
= sizeof(gui_options
.gui_gtk3_default_theme_name
);
6420 default_theme_name
= gui_options
.gui_gtk3_22_default_theme_name
;
6421 default_theme_name_sz
= sizeof(gui_options
.gui_gtk3_22_default_theme_name
);
6424 default_theme_name
= gui_options
.gui_sdl_default_theme_name
;
6425 default_theme_name_sz
= sizeof(gui_options
.gui_sdl_default_theme_name
);
6428 default_theme_name
= gui_options
.gui_sdl2_default_theme_name
;
6429 default_theme_name_sz
= sizeof(gui_options
.gui_sdl2_default_theme_name
);
6438 if (NULL
== default_theme_name
|| 0 == default_theme_name_sz
) {
6439 /* Theme is not supported by this client. */
6443 for (i
= 0; i
< t
->num_preferred_themes
; i
++) {
6444 if (strcmp(t
->preferred_themes
[i
], default_theme_name
)) {
6445 if (popup_theme_suggestion_dialog(t
->preferred_themes
[i
])) {
6446 log_debug("trying theme \"%s\".", t
->preferred_themes
[i
]);
6447 if (load_theme(t
->preferred_themes
[i
])) {
6448 (void) fc_strlcpy(default_theme_name
, t
->preferred_themes
[i
],
6449 default_theme_name_sz
);
6455 log_verbose("The tileset doesn't specify preferred themes or none of its "
6456 "preferred themes can be used. Using system default.");
6460 /****************************************************************************
6461 Initialize tileset structure
6462 ****************************************************************************/
6463 void tileset_init(struct tileset
*t
)
6467 /* We currently have no city sprites loaded. */
6468 t
->sprites
.city
.tile
= NULL
;
6470 for (wi
= 0; wi
< NUM_WALL_TYPES
; wi
++) {
6471 t
->sprites
.city
.wall
[wi
] = NULL
;
6473 t
->sprites
.city
.single_wall
= NULL
;
6475 t
->sprites
.city
.occupied
= NULL
;
6477 t
->sprites
.background
.color
= NULL
;
6478 t
->sprites
.background
.graphic
= NULL
;
6480 player_slots_iterate(pslot
) {
6481 int edge
, j
, id
= player_slot_index(pslot
);
6483 for (edge
= 0; edge
< EDGE_COUNT
; edge
++) {
6484 for (j
= 0; j
< 2; j
++) {
6485 t
->sprites
.player
[id
].grid_borders
[edge
][j
] = NULL
;
6489 t
->sprites
.player
[id
].color
= NULL
;
6490 t
->sprites
.player
[id
].background
= NULL
;
6491 } player_slots_iterate_end
;
6493 t
->max_upkeep_height
= 0;
6496 /****************************************************************************
6497 Fill the sprite array with sprites that together make a representative
6498 image of the given terrain type. Suitable for use as an icon and in list
6501 NB: The 'layer' argument is NOT a LAYER_* value, but rather one of 0, 1, 2.
6502 Using other values for 'layer' here will result in undefined behaviour. ;)
6503 ****************************************************************************/
6504 int fill_basic_terrain_layer_sprite_array(struct tileset
*t
,
6505 struct drawn_sprite
*sprs
,
6507 struct terrain
*pterrain
)
6509 struct drawn_sprite
*save_sprs
= sprs
;
6510 struct drawing_data
*draw
= t
->sprites
.drawing
[terrain_index(pterrain
)];
6512 struct terrain
*tterrain_near
[8];
6513 bv_special tspecial_near
[8];
6515 struct tile dummy_tile
; /* :( */
6520 memset(&dummy_tile
, 0, sizeof(struct tile
));
6522 for (i
= 0; i
< 8; i
++) {
6523 tterrain_near
[i
] = pterrain
;
6524 BV_CLR_ALL(tspecial_near
[i
]);
6527 i
= draw
->is_reversed
? draw
->num_layers
- layer
- 1 : layer
;
6528 sprs
+= fill_terrain_sprite_array(t
, sprs
, i
, &dummy_tile
,
6529 pterrain
, tterrain_near
, draw
);
6531 return sprs
- save_sprs
;
6534 /****************************************************************************
6535 Return the sprite for the given resource type.
6536 ****************************************************************************/
6537 struct sprite
*get_resource_sprite(const struct tileset
*t
,
6538 const struct resource
*presource
)
6540 if (presource
== NULL
) {
6544 return t
->sprites
.resource
[resource_index(presource
)];
6547 /****************************************************************************
6548 Return a representative sprite for the given extra type.
6549 ****************************************************************************/
6550 int fill_basic_extra_sprite_array(const struct tileset
*t
,
6551 struct drawn_sprite
*sprs
,
6552 const struct extra_type
*pextra
)
6554 int idx
= extra_index(pextra
);
6555 struct drawn_sprite
*saved_sprs
= sprs
;
6557 switch (t
->sprites
.extras
[idx
].extrastyle
) {
6558 case ESTYLE_SINGLE1
:
6559 case ESTYLE_SINGLE2
:
6560 ADD_SPRITE_SIMPLE(t
->sprites
.extras
[idx
].u
.single
);
6562 case ESTYLE_CARDINALS
:
6563 ADD_SPRITE_SIMPLE(t
->sprites
.extras
[idx
].u
.cardinals
[0]);
6565 case ESTYLE_ROAD_ALL_SEPARATE
:
6566 case ESTYLE_ROAD_PARITY_COMBINED
:
6567 case ESTYLE_ROAD_ALL_COMBINED
:
6569 return fill_basic_road_sprite_array(t
, sprs
, pextra
);
6571 return fill_basic_base_sprite_array(t
, sprs
, pextra
);
6573 fc_assert(t
->sprites
.extras
[idx
].extrastyle
!= ESTYLE_COUNT
);
6577 return sprs
- saved_sprs
;
6580 /****************************************************************************
6581 Fills the sprite array with sprites that together make a representative
6582 image of the given road type. The image is suitable for use as an icon
6583 for the road type, for example.
6584 ****************************************************************************/
6585 int fill_basic_road_sprite_array(const struct tileset
*t
,
6586 struct drawn_sprite
*sprs
,
6587 const struct extra_type
*pextra
)
6589 struct drawn_sprite
*saved_sprs
= sprs
;
6592 enum extrastyle_id extrastyle
;
6594 if (!t
|| !sprs
|| !pextra
) {
6598 idx
= extra_index(pextra
);
6600 if (!(0 <= idx
&& idx
< game
.control
.num_extra_types
)) {
6604 extrastyle
= t
->sprites
.extras
[idx
].extrastyle
;
6606 if (extrastyle
== ESTYLE_RIVER
) {
6607 ADD_SPRITE_SIMPLE(t
->sprites
.extras
[idx
].u
.road
.ru
.rivers
.spec
[0]);
6609 for (i
= 0; i
< t
->num_valid_tileset_dirs
; i
++) {
6610 if (!t
->valid_tileset_dirs
[i
]) {
6613 if (extrastyle
== ESTYLE_ROAD_ALL_SEPARATE
) {
6614 ADD_SPRITE_SIMPLE(t
->sprites
.extras
[idx
].u
.road
.ru
.dir
[i
]);
6615 } else if (extrastyle
== ESTYLE_ROAD_PARITY_COMBINED
) {
6617 ADD_SPRITE_SIMPLE(t
->sprites
.extras
[idx
].u
.road
.ru
.combo
.even
[1 << (i
/ 2)]);
6619 } else if (extrastyle
== ESTYLE_ROAD_ALL_COMBINED
) {
6620 ADD_SPRITE_SIMPLE(t
->sprites
.extras
[idx
].u
.road
.ru
.total
[1 << i
]);
6625 return sprs
- saved_sprs
;
6628 /****************************************************************************
6629 Fills the sprite array with sprites that together make a representative
6630 image of the given base type. The image is suitable for use as an icon
6631 for the base type, for example.
6632 ****************************************************************************/
6633 int fill_basic_base_sprite_array(const struct tileset
*t
,
6634 struct drawn_sprite
*sprs
,
6635 const struct extra_type
*pextra
)
6637 struct drawn_sprite
*saved_sprs
= sprs
;
6640 if (!t
|| !sprs
|| !pextra
) {
6644 idx
= extra_index(pextra
);
6646 if (!(0 <= idx
&& idx
< game
.control
.num_extra_types
)) {
6650 #define ADD_SPRITE_IF_NOT_NULL(x) do {\
6652 ADD_SPRITE_FULL(x);\
6656 /* Corresponds to LAYER_SPECIAL{1,2,3} order. */
6657 ADD_SPRITE_IF_NOT_NULL(t
->sprites
.extras
[idx
].u
.bmf
.background
);
6658 ADD_SPRITE_IF_NOT_NULL(t
->sprites
.extras
[idx
].u
.bmf
.middleground
);
6659 ADD_SPRITE_IF_NOT_NULL(t
->sprites
.extras
[idx
].u
.bmf
.foreground
);
6661 #undef ADD_SPRITE_IF_NOT_NULL
6663 return sprs
- saved_sprs
;
6666 /****************************************************************************
6667 Setup tiles for one player using the player color.
6668 ****************************************************************************/
6669 void tileset_player_init(struct tileset
*t
, struct player
*pplayer
)
6672 struct sprite
*color
;
6674 fc_assert_ret(pplayer
!= NULL
);
6676 plrid
= player_index(pplayer
);
6677 fc_assert_ret(plrid
>= 0);
6678 fc_assert_ret(plrid
< ARRAY_SIZE(t
->sprites
.player
));
6680 /* Free all data before recreating it. */
6681 tileset_player_free(t
, plrid
);
6683 if (player_has_color(t
, pplayer
)) {
6684 t
->sprites
.player
[plrid
].color
= color
6685 = create_plr_sprite(get_player_color(t
, pplayer
));
6687 /* XXX: if player hasn't been assigned a color, perhaps there's no
6688 * point proceeding with an arbitrary color; this should only happen
6689 * in pregame. Probably blank sprites would be better. */
6691 fc_assert_ret(t
->sprites
.background
.color
!= NULL
);
6693 color
= t
->sprites
.background
.color
;
6696 t
->sprites
.player
[plrid
].background
6697 = crop_sprite(color
, 0, 0,
6698 t
->normal_tile_width
, t
->normal_tile_height
,
6699 t
->sprites
.mask
.tile
, 0, 0, t
->scale
, FALSE
);
6701 for (i
= 0; i
< EDGE_COUNT
; i
++) {
6702 for (j
= 0; j
< 2; j
++) {
6705 if (color
&& t
->sprites
.grid
.borders
[i
][j
]) {
6706 s
= crop_sprite(color
, 0, 0,
6707 t
->normal_tile_width
, t
->normal_tile_height
,
6708 t
->sprites
.grid
.borders
[i
][j
], 0, 0, 1.0f
, FALSE
);
6710 s
= t
->sprites
.grid
.borders
[i
][j
];
6712 t
->sprites
.player
[plrid
].grid_borders
[i
][j
] = s
;
6717 /****************************************************************************
6718 Free tiles for one player using the player color.
6719 ****************************************************************************/
6720 static void tileset_player_free(struct tileset
*t
, int plrid
)
6724 fc_assert_ret(plrid
>= 0);
6725 fc_assert_ret(plrid
< ARRAY_SIZE(t
->sprites
.player
));
6727 if (t
->sprites
.player
[plrid
].color
) {
6728 free_sprite(t
->sprites
.player
[plrid
].color
);
6729 t
->sprites
.player
[plrid
].color
= NULL
;
6731 if (t
->sprites
.player
[plrid
].background
) {
6732 free_sprite(t
->sprites
.player
[plrid
].background
);
6733 t
->sprites
.player
[plrid
].background
= NULL
;
6736 for (i
= 0; i
< EDGE_COUNT
; i
++) {
6737 for (j
= 0; j
< 2; j
++) {
6738 if (t
->sprites
.player
[plrid
].grid_borders
[i
][j
]) {
6739 free_sprite(t
->sprites
.player
[plrid
].grid_borders
[i
][j
]);
6740 t
->sprites
.player
[plrid
].grid_borders
[i
][j
] = NULL
;
6746 /****************************************************************************
6747 Setup tiles for the background.
6748 ****************************************************************************/
6749 void tileset_background_init(struct tileset
*t
)
6751 /* Free all data before recreating it. */
6752 tileset_background_free(t
);
6754 /* generate background color */
6755 t
->sprites
.background
.color
6756 = create_plr_sprite(ensure_color(game
.plr_bg_color
));
6758 /* Chop up and build the background graphics. */
6759 t
->sprites
.background
.graphic
6760 = crop_sprite(t
->sprites
.background
.color
, 0, 0,
6761 t
->normal_tile_width
, t
->normal_tile_height
,
6762 t
->sprites
.mask
.tile
, 0, 0, t
->scale
, FALSE
);
6765 /****************************************************************************
6766 Free tiles for the background.
6767 ****************************************************************************/
6768 void tileset_background_free(struct tileset
*t
)
6770 if (t
->sprites
.background
.color
) {
6771 free_sprite(t
->sprites
.background
.color
);
6772 t
->sprites
.background
.color
= NULL
;
6775 if (t
->sprites
.background
.graphic
) {
6776 free_sprite(t
->sprites
.background
.graphic
);
6777 t
->sprites
.background
.graphic
= NULL
;
6781 /****************************************************************************
6782 Reset tileset data specific to ruleset.
6783 ****************************************************************************/
6784 void tileset_ruleset_reset(struct tileset
*t
)
6788 for (i
= 0; i
< ESTYLE_COUNT
; i
++) {
6789 if (t
->style_lists
[i
] != NULL
) {
6790 extra_type_list_destroy(t
->style_lists
[i
]);
6791 t
->style_lists
[i
] = extra_type_list_new();
6795 if (t
->flagged_bases_list
!= NULL
) {
6796 extra_type_list_destroy(t
->flagged_bases_list
);
6797 t
->flagged_bases_list
= extra_type_list_new();
6801 /****************************************************************************
6802 Is tileset in sane state?
6803 ****************************************************************************/
6804 bool tileset_is_fully_loaded(void)
6806 return !tileset_update
;
6809 /****************************************************************************
6811 ****************************************************************************/
6812 const char *tileset_name_get(struct tileset
*t
)
6814 return t
->given_name
;
6817 /****************************************************************************
6818 Return tileset version
6819 ****************************************************************************/
6820 const char *tileset_version(struct tileset
*t
)
6825 /****************************************************************************
6826 Return tileset description summary
6827 ****************************************************************************/
6828 const char *tileset_summary(struct tileset
*t
)
6833 /****************************************************************************
6834 Return tileset description body
6835 ****************************************************************************/
6836 const char *tileset_description(struct tileset
*t
)
6838 return t
->description
;
6841 /****************************************************************************
6842 Return tileset topology index
6843 ****************************************************************************/
6844 int tileset_topo_index(struct tileset
*t
)
6846 return t
->ts_topo_idx
;