File: | src/blocks.c |
Location: | line 206, column 19 |
Description: | Access to field 'w' results in a dereference of a null pointer (loaded from variable 'original_img') |
1 | /* | |||
2 | * | |||
3 | * Copyright (c) 2004-2010 Arthur Huillet | |||
4 | * Copyright (c) 1994, 2002, 2003 Johannes Prix | |||
5 | * Copyright (c) 1994, 2002 Reinhard Prix | |||
6 | * | |||
7 | * | |||
8 | * This file is part of Freedroid | |||
9 | * | |||
10 | * Freedroid is free software; you can redistribute it and/or modify | |||
11 | * it under the terms of the GNU General Public License as published by | |||
12 | * the Free Software Foundation; either version 2 of the License, or | |||
13 | * (at your option) any later version. | |||
14 | * | |||
15 | * Freedroid is distributed in the hope that it will be useful, | |||
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
18 | * GNU General Public License for more details. | |||
19 | * | |||
20 | * You should have received a copy of the GNU General Public License | |||
21 | * along with Freedroid; see the file COPYING. If not, write to the | |||
22 | * Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, | |||
23 | * MA 02111-1307 USA | |||
24 | * | |||
25 | */ | |||
26 | ||||
27 | #define _blocks_c | |||
28 | ||||
29 | #include "system.h" | |||
30 | ||||
31 | #include "defs.h" | |||
32 | #include "struct.h" | |||
33 | #include "global.h" | |||
34 | #include "proto.h" | |||
35 | ||||
36 | #include "lvledit/lvledit_display.h" | |||
37 | ||||
38 | static int current_enemy_nr; | |||
39 | ||||
40 | static int __enemy_animation(const char *filename, int *rotation, int *phase, int *first_image, int **last_image) | |||
41 | { | |||
42 | int i; | |||
43 | int rotation_index = 0; | |||
44 | int phase_index = 0; | |||
45 | int first_animation_image = 0; | |||
46 | int* last_animation_image = NULL((void*)0); | |||
47 | ||||
48 | struct { | |||
49 | const char *format_string; | |||
50 | int first_image; | |||
51 | int *last_image; | |||
52 | } animations[] = { | |||
53 | { "enemy_rot_%02d_walk-%02d.png", first_walk_animation_image[current_enemy_nr], &last_walk_animation_image[current_enemy_nr] }, | |||
54 | { "enemy_rot_%02d_attack-%02d.png", first_attack_animation_image[current_enemy_nr], &last_attack_animation_image[current_enemy_nr] }, | |||
55 | { "enemy_rot_%02d_gethit-%02d.png", first_gethit_animation_image[current_enemy_nr], &last_gethit_animation_image[current_enemy_nr] }, | |||
56 | { "enemy_rot_%02d_death-%02d.png", first_death_animation_image[current_enemy_nr], &last_death_animation_image[current_enemy_nr] }, | |||
57 | { "enemy_rot_%02d_stand-%02d.png", first_stand_animation_image[current_enemy_nr], &last_stand_animation_image[current_enemy_nr] } | |||
58 | }; | |||
59 | ||||
60 | for (i = 0; i < sizeof(animations) / sizeof(animations[0]); i++) { | |||
61 | if (sscanf(filename, animations[i].format_string, &rotation_index, &phase_index) == 2) { | |||
62 | first_animation_image = animations[i].first_image; | |||
63 | last_animation_image = animations[i].last_image; | |||
64 | break; | |||
65 | } | |||
66 | } | |||
67 | ||||
68 | if (i == sizeof(animations) / sizeof(animations[0])) { | |||
69 | error_message(__FUNCTION__, "Unexpected image filename '%s' for enemy '%s'.", PLEASE_INFORM, | |||
70 | filename, PrefixToFilename[current_enemy_nr]); | |||
71 | return -1; | |||
72 | } | |||
73 | ||||
74 | if (rotation) | |||
75 | *rotation = rotation_index; | |||
76 | if (phase) | |||
77 | *phase = phase_index; | |||
78 | if (first_image) | |||
79 | *first_image = first_animation_image; | |||
80 | if (last_image) | |||
81 | *last_image = last_animation_image; | |||
82 | ||||
83 | return 0; | |||
84 | } | |||
85 | ||||
86 | static struct image *get_storage_for_enemy_image(const char *filename) | |||
87 | { | |||
88 | int rotation_index; | |||
89 | int phase_index; | |||
90 | int first_animation_image; | |||
91 | ||||
92 | if (__enemy_animation(filename, &rotation_index, &phase_index, &first_animation_image, NULL((void*)0))) | |||
93 | return NULL((void*)0); | |||
94 | ||||
95 | return &enemy_images[current_enemy_nr][rotation_index][first_animation_image + phase_index - 1]; | |||
96 | } | |||
97 | ||||
98 | static struct image *compute_number_of_phases_for_enemy(const char *filename) | |||
99 | { | |||
100 | int phase_index; | |||
101 | int *last_animation_image; | |||
102 | ||||
103 | if (!__enemy_animation(filename, NULL((void*)0), &phase_index, NULL((void*)0), &last_animation_image)) { | |||
104 | if (*last_animation_image < phase_index + 1) | |||
105 | *last_animation_image = phase_index + 1; | |||
106 | } | |||
107 | ||||
108 | return NULL((void*)0); | |||
109 | } | |||
110 | ||||
111 | /** | |||
112 | * Enemy animation images are stored in texture atlases. This functions loads all | |||
113 | * the images for the given enemy model. | |||
114 | * It's typically called once whenever the enemy type is first encountered | |||
115 | * in one run of the engine. | |||
116 | */ | |||
117 | static void load_enemy_graphics(int enemy_model_nr) | |||
118 | { | |||
119 | char atlas_filename[4096]; | |||
120 | char atlas_directory[4096]; | |||
121 | ||||
122 | sprintf(atlas_filename, "droids/%s/atlas.txt", PrefixToFilename[enemy_model_nr]); | |||
123 | sprintf(atlas_directory, "droids/%s/", PrefixToFilename[enemy_model_nr]); | |||
124 | ||||
125 | // The information about cycle length needs to be entered into the | |||
126 | // corresponding arrays (usually initialized in blocks.c, for those | |||
127 | // series, that don't have an image archive yet...) | |||
128 | // | |||
129 | last_walk_animation_image[enemy_model_nr] = 0; | |||
130 | last_attack_animation_image[enemy_model_nr] = 0; | |||
131 | last_gethit_animation_image[enemy_model_nr] = 0; | |||
132 | last_death_animation_image[enemy_model_nr] = 0; | |||
133 | last_stand_animation_image[enemy_model_nr] = 0; | |||
134 | ||||
135 | current_enemy_nr = enemy_model_nr; | |||
136 | if (load_texture_atlas(atlas_filename, atlas_directory, compute_number_of_phases_for_enemy)) { | |||
137 | error_message(__FUNCTION__, "Unable to access the texture atlas for enemy '%s' at '%s'.", | |||
138 | PLEASE_INFORM | IS_FATAL, PrefixToFilename[enemy_model_nr], atlas_filename); | |||
139 | } | |||
140 | ||||
141 | first_walk_animation_image[enemy_model_nr] = 1; | |||
142 | first_attack_animation_image[enemy_model_nr] = last_walk_animation_image[enemy_model_nr] + 1; | |||
143 | last_attack_animation_image[enemy_model_nr] += last_walk_animation_image[enemy_model_nr]; | |||
144 | first_gethit_animation_image[enemy_model_nr] = last_attack_animation_image[enemy_model_nr] + 1; | |||
145 | last_gethit_animation_image[enemy_model_nr] += last_attack_animation_image[enemy_model_nr]; | |||
146 | first_death_animation_image[enemy_model_nr] = last_gethit_animation_image[enemy_model_nr] + 1; | |||
147 | last_death_animation_image[enemy_model_nr] += last_gethit_animation_image[enemy_model_nr]; | |||
148 | first_stand_animation_image[enemy_model_nr] = last_death_animation_image[enemy_model_nr] + 1; | |||
149 | last_stand_animation_image[enemy_model_nr] += last_death_animation_image[enemy_model_nr]; | |||
150 | ||||
151 | // Now some error checking against more phases in this enemy animation than | |||
152 | // currently allowed from the array size... | |||
153 | // | |||
154 | if (last_stand_animation_image[enemy_model_nr] >= MAX_ENEMY_MOVEMENT_PHASES999) { | |||
155 | error_message(__FUNCTION__, | |||
156 | "The number of images found in the image collection for enemy model %d is bigger than currently allowed (found %d images, max. %d).", | |||
157 | PLEASE_INFORM | IS_FATAL, enemy_model_nr, last_stand_animation_image[enemy_model_nr], MAX_ENEMY_MOVEMENT_PHASES999); | |||
158 | } | |||
159 | ||||
160 | if (load_texture_atlas(atlas_filename, atlas_directory, get_storage_for_enemy_image)) { | |||
161 | error_message(__FUNCTION__, "Unable to load texture atlas for enemy '%s' at %s.", | |||
162 | PLEASE_INFORM | IS_FATAL, PrefixToFilename[enemy_model_nr], atlas_filename); | |||
163 | } | |||
164 | } | |||
165 | ||||
166 | ||||
167 | /** | |||
168 | * This function loads the Blast image and decodes it into the multiple | |||
169 | * small Blast surfaces. | |||
170 | */ | |||
171 | void Load_Blast_Surfaces(void) | |||
172 | { | |||
173 | int i, j; | |||
174 | char fpath[2048]; | |||
175 | ||||
176 | for (i = 0; i < sizeof(Blastmap) / sizeof(Blastmap[0]); i++) { | |||
177 | for (j = 0; j < Blastmap[i].phases; j++) { | |||
178 | sprintf(fpath, "blasts/%s_%04d.png", Blastmap[i].name, j + 1); | |||
179 | load_image(&Blastmap[i].images[j], fpath, TRUE(1)); | |||
180 | } | |||
181 | } | |||
182 | } | |||
183 | ||||
184 | static void load_item_graphics(int item_type) | |||
185 | { | |||
186 | SDL_Surface *original_img; | |||
187 | SDL_Surface *tmp_surf2 = NULL((void*)0); | |||
188 | char fpath[PATH_MAX4096]; | |||
189 | char our_filename[PATH_MAX4096]; | |||
190 | itemspec *spec = &ItemMap[item_type]; | |||
191 | ||||
192 | sprintf(our_filename, "items/%s", spec->item_inv_file_name); | |||
193 | ||||
194 | // Load the inventory image | |||
195 | find_file(our_filename, GRAPHICS_DIR, fpath, PLEASE_INFORM | IS_FATAL); | |||
196 | ||||
197 | original_img = IMG_Load(fpath); | |||
| ||||
198 | if (original_img == NULL((void*)0)) { | |||
199 | error_message(__FUNCTION__, "Inventory image for item type %d, at path %s was not found", | |||
200 | PLEASE_INFORM | IS_FATAL, item_type, fpath); | |||
201 | } | |||
202 | ||||
203 | int target_x = spec->inv_size.x * 32; | |||
204 | int target_y = spec->inv_size.y * 32; | |||
205 | float factor_x, factor_y; | |||
206 | if ((target_x != original_img->w) || (target_y != original_img->h)) { | |||
| ||||
207 | factor_x = (float)target_x / (float)original_img->w; | |||
208 | factor_y = (float)target_y / (float)original_img->h; | |||
209 | tmp_surf2 = zoomSurface(original_img, factor_x, factor_y, FALSE(0)); | |||
210 | spec->inventory_image.surface = SDL_DisplayFormatAlpha(tmp_surf2); | |||
211 | SDL_FreeSurface(tmp_surf2); | |||
212 | } else | |||
213 | spec->inventory_image.surface = SDL_DisplayFormatAlpha(original_img); | |||
214 | ||||
215 | if (use_open_gl) { | |||
216 | make_texture_out_of_surface(&spec->inventory_image); | |||
217 | } else { | |||
218 | spec->inventory_image.w = spec->inventory_image.surface->w; | |||
219 | spec->inventory_image.h = spec->inventory_image.surface->h; | |||
220 | } | |||
221 | ||||
222 | // For the shop, we need versions of each image, where the image is scaled so | |||
223 | // that it takes up a whole 64x64 shop display square. So we prepare scaled | |||
224 | // versions here and now... | |||
225 | ||||
226 | // Scale shop image | |||
227 | if (original_img->w >= original_img->h) { | |||
228 | target_x = 64; | |||
229 | target_y = original_img->h * 64.0 / (float)original_img->w; //keep the scaling ratio ! | |||
230 | } | |||
231 | ||||
232 | if (original_img->h > original_img->w) { | |||
233 | target_y = 64; | |||
234 | target_x = original_img->w * 64.0 / (float)original_img->h; | |||
235 | } | |||
236 | ||||
237 | factor_x = ((float)GameConfig.screen_width / 640.0) * ((float)target_x / (float)original_img->w); | |||
238 | factor_y = ((float)GameConfig.screen_height / 480.0) * ((float)target_y / (float)original_img->h); | |||
239 | tmp_surf2 = zoomSurface(original_img, factor_x, factor_y, FALSE(0)); | |||
240 | spec->shop_image.surface = SDL_DisplayFormatAlpha(tmp_surf2); | |||
241 | SDL_FreeSurface(original_img); | |||
242 | SDL_FreeSurface(tmp_surf2); | |||
243 | ||||
244 | if (use_open_gl) { | |||
245 | make_texture_out_of_surface(&spec->shop_image); | |||
246 | } else { | |||
247 | spec->shop_image.w = spec->shop_image.surface->w; | |||
248 | spec->shop_image.h = spec->shop_image.surface->h; | |||
249 | } | |||
250 | ||||
251 | // Load ingame image | |||
252 | if (strcmp(spec->item_rotation_series_prefix, "NONE_AVAILABLE_YET")__extension__ ({ size_t __s1_len, __s2_len; (__builtin_constant_p (spec->item_rotation_series_prefix) && __builtin_constant_p ("NONE_AVAILABLE_YET") && (__s1_len = strlen (spec-> item_rotation_series_prefix), __s2_len = strlen ("NONE_AVAILABLE_YET" ), (!((size_t)(const void *)((spec->item_rotation_series_prefix ) + 1) - (size_t)(const void *)(spec->item_rotation_series_prefix ) == 1) || __s1_len >= 4) && (!((size_t)(const void *)(("NONE_AVAILABLE_YET") + 1) - (size_t)(const void *)("NONE_AVAILABLE_YET" ) == 1) || __s2_len >= 4)) ? __builtin_strcmp (spec->item_rotation_series_prefix , "NONE_AVAILABLE_YET") : (__builtin_constant_p (spec->item_rotation_series_prefix ) && ((size_t)(const void *)((spec->item_rotation_series_prefix ) + 1) - (size_t)(const void *)(spec->item_rotation_series_prefix ) == 1) && (__s1_len = strlen (spec->item_rotation_series_prefix ), __s1_len < 4) ? (__builtin_constant_p ("NONE_AVAILABLE_YET" ) && ((size_t)(const void *)(("NONE_AVAILABLE_YET") + 1) - (size_t)(const void *)("NONE_AVAILABLE_YET") == 1) ? __builtin_strcmp (spec->item_rotation_series_prefix, "NONE_AVAILABLE_YET") : (__extension__ ({ const unsigned char *__s2 = (const unsigned char *) (const char *) ("NONE_AVAILABLE_YET"); int __result = (((const unsigned char *) (const char *) (spec->item_rotation_series_prefix ))[0] - __s2[0]); if (__s1_len > 0 && __result == 0 ) { __result = (((const unsigned char *) (const char *) (spec ->item_rotation_series_prefix))[1] - __s2[1]); if (__s1_len > 1 && __result == 0) { __result = (((const unsigned char *) (const char *) (spec->item_rotation_series_prefix ))[2] - __s2[2]); if (__s1_len > 2 && __result == 0 ) __result = (((const unsigned char *) (const char *) (spec-> item_rotation_series_prefix))[3] - __s2[3]); } } __result; }) )) : (__builtin_constant_p ("NONE_AVAILABLE_YET") && ( (size_t)(const void *)(("NONE_AVAILABLE_YET") + 1) - (size_t) (const void *)("NONE_AVAILABLE_YET") == 1) && (__s2_len = strlen ("NONE_AVAILABLE_YET"), __s2_len < 4) ? (__builtin_constant_p (spec->item_rotation_series_prefix) && ((size_t)( const void *)((spec->item_rotation_series_prefix) + 1) - ( size_t)(const void *)(spec->item_rotation_series_prefix) == 1) ? __builtin_strcmp (spec->item_rotation_series_prefix, "NONE_AVAILABLE_YET") : (- (__extension__ ({ const unsigned char *__s2 = (const unsigned char *) (const char *) (spec->item_rotation_series_prefix ); int __result = (((const unsigned char *) (const char *) ("NONE_AVAILABLE_YET" ))[0] - __s2[0]); if (__s2_len > 0 && __result == 0 ) { __result = (((const unsigned char *) (const char *) ("NONE_AVAILABLE_YET" ))[1] - __s2[1]); if (__s2_len > 1 && __result == 0 ) { __result = (((const unsigned char *) (const char *) ("NONE_AVAILABLE_YET" ))[2] - __s2[2]); if (__s2_len > 2 && __result == 0 ) __result = (((const unsigned char *) (const char *) ("NONE_AVAILABLE_YET" ))[3] - __s2[3]); } } __result; })))) : __builtin_strcmp (spec ->item_rotation_series_prefix, "NONE_AVAILABLE_YET")))); } )) { | |||
253 | sprintf(our_filename, "items/%s/ingame.png", spec->item_rotation_series_prefix); | |||
254 | load_image(&spec->ingame_image, our_filename, TRUE(1)); | |||
255 | } else { | |||
256 | memcpy(&spec->ingame_image, &spec->inventory_image, sizeof(struct image)); | |||
257 | } | |||
258 | } | |||
259 | ||||
260 | static void load_if_needed(int type) | |||
261 | { | |||
262 | itemspec *spec = &ItemMap[type]; | |||
263 | ||||
264 | if (!image_loaded(&spec->inventory_image)) { | |||
265 | load_item_graphics(type); | |||
266 | } | |||
267 | } | |||
268 | ||||
269 | struct image *get_item_inventory_image(int type) | |||
270 | { | |||
271 | load_if_needed(type); | |||
272 | return &ItemMap[type].inventory_image; | |||
273 | } | |||
274 | ||||
275 | struct image *get_item_shop_image(int type) | |||
276 | { | |||
277 | load_if_needed(type); | |||
278 | return &ItemMap[type].shop_image; | |||
279 | } | |||
280 | ||||
281 | struct image *get_item_ingame_image(int type) | |||
282 | { | |||
283 | load_if_needed(type); | |||
284 | return &ItemMap[type].ingame_image; | |||
285 | } | |||
286 | ||||
287 | void load_all_items(void) | |||
288 | { | |||
289 | int i; | |||
290 | ||||
291 | for (i = 0; i < Number_Of_Item_Types; i++) { | |||
292 | load_item_graphics(i); | |||
293 | } | |||
294 | } | |||
295 | ||||
296 | /** | |||
297 | * Free all images associated with items. | |||
298 | */ | |||
299 | void free_item_graphics(void) | |||
300 | { | |||
301 | int i; | |||
302 | struct image empty_image = EMPTY_IMAGE{ .surface = ((void*)0) , .offset_x = 0 , .offset_y = 0 , .texture_has_been_created = 0 , .cached_transformation = { ((void*)0), 0.0, 0.0, { 0.0 , 0.0, 0.0, 0.0}, 0 } }; | |||
303 | ||||
304 | for (i = 0; i < Number_Of_Item_Types; i++) { | |||
305 | if (image_loaded(&ItemMap[i].inventory_image)) { | |||
306 | delete_image(&ItemMap[i].inventory_image); | |||
307 | ||||
308 | // If the ingame image is not available for an item, then it is just a copy | |||
309 | // of the inventory image. In this case, the ingame image should not be | |||
310 | // deleted. The resources associated with this image will be freed when | |||
311 | // the inventory image is deleted. | |||
312 | if (strcmp(ItemMap[i].item_rotation_series_prefix, "NONE_AVAILABLE_YET")__extension__ ({ size_t __s1_len, __s2_len; (__builtin_constant_p (ItemMap[i].item_rotation_series_prefix) && __builtin_constant_p ("NONE_AVAILABLE_YET") && (__s1_len = strlen (ItemMap [i].item_rotation_series_prefix), __s2_len = strlen ("NONE_AVAILABLE_YET" ), (!((size_t)(const void *)((ItemMap[i].item_rotation_series_prefix ) + 1) - (size_t)(const void *)(ItemMap[i].item_rotation_series_prefix ) == 1) || __s1_len >= 4) && (!((size_t)(const void *)(("NONE_AVAILABLE_YET") + 1) - (size_t)(const void *)("NONE_AVAILABLE_YET" ) == 1) || __s2_len >= 4)) ? __builtin_strcmp (ItemMap[i]. item_rotation_series_prefix, "NONE_AVAILABLE_YET") : (__builtin_constant_p (ItemMap[i].item_rotation_series_prefix) && ((size_t )(const void *)((ItemMap[i].item_rotation_series_prefix) + 1) - (size_t)(const void *)(ItemMap[i].item_rotation_series_prefix ) == 1) && (__s1_len = strlen (ItemMap[i].item_rotation_series_prefix ), __s1_len < 4) ? (__builtin_constant_p ("NONE_AVAILABLE_YET" ) && ((size_t)(const void *)(("NONE_AVAILABLE_YET") + 1) - (size_t)(const void *)("NONE_AVAILABLE_YET") == 1) ? __builtin_strcmp (ItemMap[i].item_rotation_series_prefix, "NONE_AVAILABLE_YET" ) : (__extension__ ({ const unsigned char *__s2 = (const unsigned char *) (const char *) ("NONE_AVAILABLE_YET"); int __result = (((const unsigned char *) (const char *) (ItemMap[i].item_rotation_series_prefix ))[0] - __s2[0]); if (__s1_len > 0 && __result == 0 ) { __result = (((const unsigned char *) (const char *) (ItemMap [i].item_rotation_series_prefix))[1] - __s2[1]); if (__s1_len > 1 && __result == 0) { __result = (((const unsigned char *) (const char *) (ItemMap[i].item_rotation_series_prefix ))[2] - __s2[2]); if (__s1_len > 2 && __result == 0 ) __result = (((const unsigned char *) (const char *) (ItemMap [i].item_rotation_series_prefix))[3] - __s2[3]); } } __result ; }))) : (__builtin_constant_p ("NONE_AVAILABLE_YET") && ((size_t)(const void *)(("NONE_AVAILABLE_YET") + 1) - (size_t )(const void *)("NONE_AVAILABLE_YET") == 1) && (__s2_len = strlen ("NONE_AVAILABLE_YET"), __s2_len < 4) ? (__builtin_constant_p (ItemMap[i].item_rotation_series_prefix) && ((size_t )(const void *)((ItemMap[i].item_rotation_series_prefix) + 1) - (size_t)(const void *)(ItemMap[i].item_rotation_series_prefix ) == 1) ? __builtin_strcmp (ItemMap[i].item_rotation_series_prefix , "NONE_AVAILABLE_YET") : (- (__extension__ ({ const unsigned char *__s2 = (const unsigned char *) (const char *) (ItemMap [i].item_rotation_series_prefix); int __result = (((const unsigned char *) (const char *) ("NONE_AVAILABLE_YET"))[0] - __s2[0]) ; if (__s2_len > 0 && __result == 0) { __result = ( ((const unsigned char *) (const char *) ("NONE_AVAILABLE_YET" ))[1] - __s2[1]); if (__s2_len > 1 && __result == 0 ) { __result = (((const unsigned char *) (const char *) ("NONE_AVAILABLE_YET" ))[2] - __s2[2]); if (__s2_len > 2 && __result == 0 ) __result = (((const unsigned char *) (const char *) ("NONE_AVAILABLE_YET" ))[3] - __s2[3]); } } __result; })))) : __builtin_strcmp (ItemMap [i].item_rotation_series_prefix, "NONE_AVAILABLE_YET")))); })) | |||
313 | delete_image(&ItemMap[i].ingame_image); | |||
314 | else | |||
315 | memcpy(&ItemMap[i].ingame_image, &empty_image, sizeof(struct image)); | |||
316 | ||||
317 | delete_image(&ItemMap[i].shop_image); | |||
318 | } | |||
319 | } | |||
320 | } | |||
321 | ||||
322 | /** | |||
323 | * This function loads the items image and decodes it into the multiple | |||
324 | * small item surfaces. | |||
325 | */ | |||
326 | void Load_Mouse_Move_Cursor_Surfaces(void) | |||
327 | { | |||
328 | int j; | |||
329 | char our_filename[2000] = ""; | |||
330 | ||||
331 | for (j = 0; j < NUMBER_OF_MOUSE_CURSOR_PICTURES2; j++) { | |||
332 | sprintf(our_filename, "cursors/mouse_move_cursor_%d.png", j); | |||
333 | load_image(&MouseCursorImageList[j], our_filename, FALSE(0)); | |||
334 | } | |||
335 | ||||
336 | }; // void Load_Mouse_Move_Cursor_Surfaces( void ) | |||
337 | ||||
338 | /** | |||
339 | * This function loads all the bullet images into memory. | |||
340 | * | |||
341 | */ | |||
342 | void iso_load_bullet_surfaces(void) | |||
343 | { | |||
344 | int i, j, k; | |||
345 | char constructed_filename[5000]; | |||
346 | ||||
347 | for (i = 0; i < bullet_specs.size; i++) { | |||
348 | struct bulletspec *bullet_spec = dynarray_member(&bullet_specs, i, sizeof(struct bulletspec)); | |||
349 | ||||
350 | if (strlen(bullet_spec->name) && strstr(bullet_spec->name, "NO BULLET IMAGE")) | |||
351 | continue; | |||
352 | ||||
353 | for (j = 0; j < bullet_spec->phases; j++) { | |||
354 | for (k = 0; k < BULLET_DIRECTIONS16; k++) { | |||
355 | sprintf(constructed_filename, "bullets/iso_bullet_%s_%02d_%04d.png", bullet_spec->name, k, j + 1); | |||
356 | ||||
357 | load_image(&bullet_spec->image[k][j], constructed_filename, TRUE(1)); | |||
358 | } | |||
359 | } | |||
360 | } | |||
361 | ||||
362 | }; // void iso_load_bullet_surfaces ( void ) | |||
363 | ||||
364 | /** | |||
365 | * | |||
366 | * | |||
367 | */ | |||
368 | void get_offset_for_iso_image_from_file_and_path(char *fpath, struct image * our_iso_image) | |||
369 | { | |||
370 | char offset_file_name[10000]; | |||
371 | FILE *OffsetFile; | |||
372 | char *offset_data; | |||
373 | // Now we try to load the associated offset file, that we'll be needing | |||
374 | // in order to properly fine-position the image later when blitting is to | |||
375 | // a map location. | |||
376 | // | |||
377 | strcpy(offset_file_name, fpath); | |||
378 | offset_file_name[strlen(offset_file_name) - 4] = 0; | |||
379 | strcat(offset_file_name, ".offset"); | |||
380 | ||||
381 | // Let's see if we can find an offset file... | |||
382 | // | |||
383 | if ((OffsetFile = fopen(offset_file_name, "rb")) == NULL((void*)0)) { | |||
384 | error_message(__FUNCTION__, "\ | |||
385 | FreedroidRPG was unable to open offset file %s for an isometric image.\n\ | |||
386 | Since the offset could not be obtained from the offset file, 0 will be used instead.\n\ | |||
387 | This can lead to minor positioning perturbations\n\ | |||
388 | in graphics displayed, but FreedroidRPG will continue to work.", NO_REPORT, offset_file_name); | |||
389 | our_iso_image->offset_x = 0; | |||
390 | our_iso_image->offset_y = 0; | |||
391 | return; | |||
392 | } else { | |||
393 | fclose(OffsetFile); | |||
394 | } | |||
395 | ||||
396 | // So at this point we can be certain, that the offset file is there. | |||
397 | // That means, that we can now use the (otherwise terminating) read-and-malloc-... | |||
398 | // functions. | |||
399 | // | |||
400 | offset_data = ReadAndMallocAndTerminateFile(offset_file_name, END_OF_OFFSET_FILE_STRING"** End of iso_image offset file **"); | |||
401 | ||||
402 | ReadValueFromString(offset_data, OFFSET_FILE_OFFSETX_STRING"OffsetX=", "%hd", &(our_iso_image->offset_x), offset_data + strlen(offset_data)); | |||
403 | ||||
404 | ReadValueFromString(offset_data, OFFSET_FILE_OFFSETY_STRING"OffsetY=", "%hd", &(our_iso_image->offset_y), offset_data + strlen(offset_data)); | |||
405 | free(offset_data); | |||
406 | ||||
407 | }; // void get_offset_for_iso_image_from_file_and_path ( fpath , our_iso_image ) | |||
408 | ||||
409 | static int EnemyFullyPrepared[ENEMY_ROTATION_MODELS_AVAILABLE43]; | |||
410 | ||||
411 | /** | |||
412 | * | |||
413 | * | |||
414 | */ | |||
415 | void LoadAndPrepareEnemyRotationModelNr(int ModelNr) | |||
416 | { | |||
417 | // Now a sanity check against using rotation types, that don't exist | |||
418 | // in FreedroidRPG at all! | |||
419 | // | |||
420 | if ((ModelNr < 0) || (ModelNr >= ENEMY_ROTATION_MODELS_AVAILABLE43)) { | |||
421 | error_message(__FUNCTION__, "\ | |||
422 | FreedroidRPG received a rotation model number that does not exist: %d", PLEASE_INFORM | IS_FATAL, ModelNr); | |||
423 | } | |||
424 | // Now we can check if the given rotation model type was perhaps already | |||
425 | // allocated and loaded and fully prepared. Then of course we need not | |||
426 | // do anything here... Otherwise we can have trust and mark it as loaded | |||
427 | // already... | |||
428 | // | |||
429 | if (EnemyFullyPrepared[ModelNr]) | |||
430 | return; | |||
431 | EnemyFullyPrepared[ModelNr] = TRUE(1); | |||
432 | Activate_Conservative_Frame_Computation(); | |||
433 | ||||
434 | load_enemy_graphics(ModelNr); | |||
435 | } | |||
436 | ||||
437 | void free_enemy_graphics(void) | |||
438 | { | |||
439 | int i; | |||
440 | int rotation_index, phase_index; | |||
441 | ||||
442 | for (i = 0; i < ENEMY_ROTATION_MODELS_AVAILABLE43; i++) { | |||
443 | if (!EnemyFullyPrepared[i]) | |||
444 | continue; | |||
445 | ||||
446 | for (rotation_index = 0; rotation_index < ROTATION_ANGLES_PER_ROTATION_MODEL8; rotation_index++) { | |||
447 | for (phase_index = 0; phase_index < MAX_ENEMY_MOVEMENT_PHASES999; phase_index++) | |||
448 | delete_image(&enemy_images[i][rotation_index][phase_index]); | |||
449 | } | |||
450 | EnemyFullyPrepared[i] = FALSE(0); | |||
451 | } | |||
452 | } | |||
453 | ||||
454 | /** | |||
455 | * Read the Enemy Surfaces details from the data stream. | |||
456 | */ | |||
457 | void get_enemy_surfaces_data(char *DataPointer) | |||
458 | { | |||
459 | char *SurfacePointer; | |||
460 | char *EndOfSurfaceData; | |||
461 | int SurfaceIndex = 0; | |||
462 | ||||
463 | #define ENEMY_SURFACES_SECTION_BEGIN_STRING"*** Start of Enemy Surfaces Section: ***" "*** Start of Enemy Surfaces Section: ***" | |||
464 | #define ENEMY_SURFACES_SECTION_END_STRING"*** End of Enemy Surfaces Section: ***" "*** End of Enemy Surfaces Section: ***" | |||
465 | #define NEW_SURFACE_BEGIN_STRING"** Start of new surface specification subsection **" "** Start of new surface specification subsection **" | |||
466 | ||||
467 | #define SURFACES_FILE_NAME_BEGIN_STRING"PrefixToFilename=\"" "PrefixToFilename=\"" | |||
468 | #define SURFACES_WALK_ANI_SPEED_BEGIN_STRING"droid_walk_animation_speed_factor=" "droid_walk_animation_speed_factor=" | |||
469 | #define SURFACES_ATTACK_ANI_SPEED_BEGIN_STRING"droid_attack_animation_speed_factor=" "droid_attack_animation_speed_factor=" | |||
470 | #define SURFACES_GETHIT_ANI_SPEED_BEGIN_STRING"droid_gethit_animation_speed_factor=" "droid_gethit_animation_speed_factor=" | |||
471 | #define SURFACES_DEATH_ANI_SPEED_BEGIN_STRING"droid_death_animation_speed_factor=" "droid_death_animation_speed_factor=" | |||
472 | #define SURFACES_STAND_ANI_SPEED_BEGIN_STRING"droid_stand_animation_speed_factor=" "droid_stand_animation_speed_factor=" | |||
473 | ||||
474 | ||||
475 | EndOfSurfaceData = LocateStringInData(DataPointer, ENEMY_SURFACES_SECTION_END_STRING"*** End of Enemy Surfaces Section: ***"); | |||
476 | ||||
477 | DebugPrintf(1, "\n\nStarting to read surfaces data...\n\n"); | |||
478 | ||||
479 | SurfacePointer = DataPointer; | |||
480 | ||||
481 | while ((SurfacePointer = strstr(SurfacePointer, NEW_SURFACE_BEGIN_STRING"** Start of new surface specification subsection **")) != NULL((void*)0)) { | |||
482 | if (SurfaceIndex >= ENEMY_ROTATION_MODELS_AVAILABLE43) { | |||
483 | error_message(__FUNCTION__, "enemy_surfaces.dat specifies more surfaces than ENEMY_ROTATION_MODELS_AVAILABLE (%d) allows.", PLEASE_INFORM | IS_FATAL, ENEMY_ROTATION_MODELS_AVAILABLE43); | |||
484 | } | |||
485 | ||||
486 | DebugPrintf(1, "\n\nFound another surface specification entry! Lets add that to the others!"); | |||
487 | SurfacePointer++; | |||
488 | ||||
489 | PrefixToFilename[SurfaceIndex] = ReadAndMallocStringFromData(SurfacePointer, SURFACES_FILE_NAME_BEGIN_STRING"PrefixToFilename=\"", "\""); | |||
490 | ||||
491 | ReadValueFromStringWithDefault(SurfacePointer, SURFACES_WALK_ANI_SPEED_BEGIN_STRING"droid_walk_animation_speed_factor=", | |||
492 | "%d", "0", &(droid_walk_animation_speed_factor[SurfaceIndex]), EndOfSurfaceData); | |||
493 | ReadValueFromStringWithDefault(SurfacePointer, SURFACES_ATTACK_ANI_SPEED_BEGIN_STRING"droid_attack_animation_speed_factor=", | |||
494 | "%d", "0", &(droid_attack_animation_speed_factor[SurfaceIndex]), EndOfSurfaceData); | |||
495 | ReadValueFromStringWithDefault(SurfacePointer, SURFACES_GETHIT_ANI_SPEED_BEGIN_STRING"droid_gethit_animation_speed_factor=", | |||
496 | "%d", "0", &(droid_gethit_animation_speed_factor[SurfaceIndex]), EndOfSurfaceData); | |||
497 | ReadValueFromStringWithDefault(SurfacePointer, SURFACES_DEATH_ANI_SPEED_BEGIN_STRING"droid_death_animation_speed_factor=", | |||
498 | "%d", "0", &(droid_death_animation_speed_factor[SurfaceIndex]), EndOfSurfaceData); | |||
499 | ReadValueFromStringWithDefault(SurfacePointer, SURFACES_STAND_ANI_SPEED_BEGIN_STRING"droid_stand_animation_speed_factor=", | |||
500 | "%d", "0", &(droid_stand_animation_speed_factor[SurfaceIndex]), EndOfSurfaceData); | |||
501 | ||||
502 | SurfaceIndex++; | |||
503 | } | |||
504 | ||||
505 | DebugPrintf(1, "\nEnd of get_enemy_surfaces_data ( char* DataPointer ) reached."); | |||
506 | } | |||
507 | ||||
508 | /** | |||
509 | * This function creates all the surfaces, that are necessary to blit the | |||
510 | * 'head' and 'shoes' of an enemy. The numbers are not dealt with here. | |||
511 | */ | |||
512 | void Load_Enemy_Surfaces(void) | |||
513 | { | |||
514 | int i; | |||
515 | ||||
516 | for (i = 0; i < ENEMY_ROTATION_MODELS_AVAILABLE43; i++) { | |||
517 | struct image empty = EMPTY_IMAGE{ .surface = ((void*)0) , .offset_x = 0 , .offset_y = 0 , .texture_has_been_created = 0 , .cached_transformation = { ((void*)0), 0.0, 0.0, { 0.0 , 0.0, 0.0, 0.0}, 0 } }; | |||
518 | chat_portrait_of_droid[i] = empty; | |||
519 | } | |||
520 | ||||
521 | // When using the new tux image collection files, the animation cycle | |||
522 | // lengths for droids will be taken from the image collection file itself. | |||
523 | // That is good, because it's so dynamic. However, it also means, that | |||
524 | // the real animation phase lengths and that will in general not be known | |||
525 | // until the graphics for that bot has been loaded. But on the other hand | |||
526 | // it might happen that some phase computation is done before the first | |||
527 | // blit already. In that case, uninitialized data structs might cause | |||
528 | // severe harm. Therefore we initialize some sane default values, that should | |||
529 | // protect against certain cases of wrong phase counts. | |||
530 | // | |||
531 | for (i = 0; i < ENEMY_ROTATION_MODELS_AVAILABLE43; i++) { | |||
532 | first_walk_animation_image[i] = 1; | |||
533 | last_walk_animation_image[i] = 1; | |||
534 | first_attack_animation_image[i] = 1; | |||
535 | last_attack_animation_image[i] = 1; | |||
536 | first_gethit_animation_image[i] = 1; | |||
537 | last_gethit_animation_image[i] = 1; | |||
538 | first_death_animation_image[i] = 1; | |||
539 | last_death_animation_image[i] = 1; | |||
540 | first_stand_animation_image[i] = 1; | |||
541 | last_stand_animation_image[i] = 1; | |||
542 | } | |||
543 | ||||
544 | ||||
545 | char fpath[PATH_MAX4096]; | |||
546 | char *Data; | |||
547 | ||||
548 | find_file("enemy_surfaces.dat", MAP_DIR, fpath, PLEASE_INFORM | IS_FATAL); | |||
549 | Data = ReadAndMallocAndTerminateFile(fpath, "*** End of this Freedroid data File ***"); | |||
550 | get_enemy_surfaces_data(Data); | |||
551 | free(Data); | |||
552 | } | |||
553 | ||||
554 | static void load_droid_portrait(int type) | |||
555 | { | |||
556 | char fpath[1024]; | |||
557 | ||||
558 | strcpy(fpath, "droids/"); | |||
559 | strcat(fpath, PrefixToFilename[Droidmap[type].individual_shape_nr]); | |||
560 | strcat(fpath, "/portrait.png"); | |||
561 | ||||
562 | load_image(&chat_portrait_of_droid[type], fpath, FALSE(0)); | |||
563 | } | |||
564 | ||||
565 | struct image *get_droid_portrait_image(int type) | |||
566 | { | |||
567 | if (type >= ENEMY_ROTATION_MODELS_AVAILABLE43) { | |||
568 | error_message(__FUNCTION__, "Tried to load a portrait image of a bot those type is #%d, but the maximum configured value is %d." | |||
569 | "ENEMY_ROTATION_MODELS_AVAILABLE should be raised.", | |||
570 | PLEASE_INFORM | IS_FATAL, | |||
571 | type, ENEMY_ROTATION_MODELS_AVAILABLE43 - 1); | |||
572 | return NULL((void*)0); | |||
573 | } | |||
574 | ||||
575 | if (!image_loaded(&chat_portrait_of_droid[type])) { | |||
576 | load_droid_portrait(type); | |||
577 | } | |||
578 | ||||
579 | return &chat_portrait_of_droid[type]; | |||
580 | } | |||
581 | ||||
582 | /** | |||
583 | * Return a pointer towards the struct image | |||
584 | * associated to the given obstacle type. | |||
585 | */ | |||
586 | struct image *get_obstacle_image(int type, int frame_index) | |||
587 | { | |||
588 | struct obstacle_graphics *obs_graphics = &((struct obstacle_graphics *)obstacle_images.arr)[type]; | |||
589 | return &obs_graphics->images[frame_index % obs_graphics->count]; | |||
590 | } | |||
591 | ||||
592 | /** | |||
593 | * Return a pointer towards the shadow image | |||
594 | * associated to the given obstacle type. | |||
595 | */ | |||
596 | struct image *get_obstacle_shadow_image(int type, int frame_index) | |||
597 | { | |||
598 | struct obstacle_graphics *obs_graphics= &((struct obstacle_graphics *)obstacle_images.arr)[type]; | |||
599 | return &obs_graphics->shadows[frame_index % obs_graphics->count]; | |||
600 | } | |||
601 | ||||
602 | /** | |||
603 | * Return a pointer towards the map label image. | |||
604 | */ | |||
605 | struct image *get_map_label_image() | |||
606 | { | |||
607 | static struct image img = EMPTY_IMAGE{ .surface = ((void*)0) , .offset_x = 0 , .offset_y = 0 , .texture_has_been_created = 0 , .cached_transformation = { ((void*)0), 0.0, 0.0, { 0.0 , 0.0, 0.0, 0.0}, 0 } }; | |||
608 | ||||
609 | if (!image_loaded(&img)) | |||
610 | load_image(&img, "level_editor_map_label_indicator.png", TRUE(1)); | |||
611 | ||||
612 | return &img; | |||
613 | } | |||
614 | ||||
615 | /** | |||
616 | * Free all images associated with obstacles. | |||
617 | */ | |||
618 | void free_obstacle_graphics(void) | |||
619 | { | |||
620 | int i, j; | |||
621 | for (i = 0; i < obstacle_map.size; i++) { | |||
622 | struct obstacle_graphics *graphics = &((struct obstacle_graphics *)obstacle_images.arr)[i]; | |||
623 | for (j = 0; j < graphics->count; j++) { | |||
624 | delete_image(&graphics->images[j]); | |||
625 | delete_image(&graphics->shadows[j]); | |||
626 | } | |||
627 | } | |||
628 | } | |||
629 | ||||
630 | /** | |||
631 | * Check if all images for obstacles were loaded correctly. Issue warnings for | |||
632 | * missing images. | |||
633 | */ | |||
634 | static void validate_obstacle_graphics(void) | |||
635 | { | |||
636 | int i, j; | |||
637 | for (i = 0; i < obstacle_map.size; i++) { | |||
638 | struct obstacle_graphics *graphics = &((struct obstacle_graphics *)obstacle_images.arr)[i]; | |||
639 | for (j = 0; j < graphics->count; j++) { | |||
640 | const char *filename = ((char **)get_obstacle_spec(i)->filenames.arr)[j]; | |||
641 | if (!image_loaded(&graphics->images[j])) { | |||
642 | if (strcmp(filename, "DUMMY OBSTACLE")__extension__ ({ size_t __s1_len, __s2_len; (__builtin_constant_p (filename) && __builtin_constant_p ("DUMMY OBSTACLE" ) && (__s1_len = strlen (filename), __s2_len = strlen ("DUMMY OBSTACLE"), (!((size_t)(const void *)((filename) + 1 ) - (size_t)(const void *)(filename) == 1) || __s1_len >= 4 ) && (!((size_t)(const void *)(("DUMMY OBSTACLE") + 1 ) - (size_t)(const void *)("DUMMY OBSTACLE") == 1) || __s2_len >= 4)) ? __builtin_strcmp (filename, "DUMMY OBSTACLE") : ( __builtin_constant_p (filename) && ((size_t)(const void *)((filename) + 1) - (size_t)(const void *)(filename) == 1) && (__s1_len = strlen (filename), __s1_len < 4) ? (__builtin_constant_p ("DUMMY OBSTACLE") && ((size_t)(const void *)(("DUMMY OBSTACLE" ) + 1) - (size_t)(const void *)("DUMMY OBSTACLE") == 1) ? __builtin_strcmp (filename, "DUMMY OBSTACLE") : (__extension__ ({ const unsigned char *__s2 = (const unsigned char *) (const char *) ("DUMMY OBSTACLE" ); int __result = (((const unsigned char *) (const char *) (filename ))[0] - __s2[0]); if (__s1_len > 0 && __result == 0 ) { __result = (((const unsigned char *) (const char *) (filename ))[1] - __s2[1]); if (__s1_len > 1 && __result == 0 ) { __result = (((const unsigned char *) (const char *) (filename ))[2] - __s2[2]); if (__s1_len > 2 && __result == 0 ) __result = (((const unsigned char *) (const char *) (filename ))[3] - __s2[3]); } } __result; }))) : (__builtin_constant_p ( "DUMMY OBSTACLE") && ((size_t)(const void *)(("DUMMY OBSTACLE" ) + 1) - (size_t)(const void *)("DUMMY OBSTACLE") == 1) && (__s2_len = strlen ("DUMMY OBSTACLE"), __s2_len < 4) ? (__builtin_constant_p (filename) && ((size_t)(const void *)((filename) + 1 ) - (size_t)(const void *)(filename) == 1) ? __builtin_strcmp (filename, "DUMMY OBSTACLE") : (- (__extension__ ({ const unsigned char *__s2 = (const unsigned char *) (const char *) (filename ); int __result = (((const unsigned char *) (const char *) ("DUMMY OBSTACLE" ))[0] - __s2[0]); if (__s2_len > 0 && __result == 0 ) { __result = (((const unsigned char *) (const char *) ("DUMMY OBSTACLE" ))[1] - __s2[1]); if (__s2_len > 1 && __result == 0 ) { __result = (((const unsigned char *) (const char *) ("DUMMY OBSTACLE" ))[2] - __s2[2]); if (__s2_len > 2 && __result == 0 ) __result = (((const unsigned char *) (const char *) ("DUMMY OBSTACLE" ))[3] - __s2[3]); } } __result; })))) : __builtin_strcmp (filename , "DUMMY OBSTACLE")))); })) { | |||
643 | error_message(__FUNCTION__, "Could not load the image '%s' for obstacle %d.", | |||
644 | PLEASE_INFORM, filename, i); | |||
645 | } | |||
646 | } | |||
647 | } | |||
648 | } | |||
649 | } | |||
650 | ||||
651 | static struct image *get_storage_for_obstacle_image(const char *filename) | |||
652 | { | |||
653 | int i, j; | |||
654 | ||||
655 | for (i = 0; i < obstacle_map.size; i++) { | |||
656 | obstacle_spec *spec = get_obstacle_spec(i); | |||
657 | struct obstacle_graphics *graphics = &((struct obstacle_graphics *)obstacle_images.arr)[i]; | |||
658 | for (j = 0; j < spec->filenames.size; j++) { | |||
659 | const char *fname = ((char **)spec->filenames.arr)[j]; | |||
660 | if (!strcmp(fname, filename)__extension__ ({ size_t __s1_len, __s2_len; (__builtin_constant_p (fname) && __builtin_constant_p (filename) && (__s1_len = strlen (fname), __s2_len = strlen (filename), (! ((size_t)(const void *)((fname) + 1) - (size_t)(const void *) (fname) == 1) || __s1_len >= 4) && (!((size_t)(const void *)((filename) + 1) - (size_t)(const void *)(filename) == 1) || __s2_len >= 4)) ? __builtin_strcmp (fname, filename ) : (__builtin_constant_p (fname) && ((size_t)(const void *)((fname) + 1) - (size_t)(const void *)(fname) == 1) && (__s1_len = strlen (fname), __s1_len < 4) ? (__builtin_constant_p (filename) && ((size_t)(const void *)((filename) + 1 ) - (size_t)(const void *)(filename) == 1) ? __builtin_strcmp (fname, filename) : (__extension__ ({ const unsigned char *__s2 = (const unsigned char *) (const char *) (filename); int __result = (((const unsigned char *) (const char *) (fname))[0] - __s2 [0]); if (__s1_len > 0 && __result == 0) { __result = (((const unsigned char *) (const char *) (fname))[1] - __s2 [1]); if (__s1_len > 1 && __result == 0) { __result = (((const unsigned char *) (const char *) (fname))[2] - __s2 [2]); if (__s1_len > 2 && __result == 0) __result = (((const unsigned char *) (const char *) (fname))[3] - __s2[ 3]); } } __result; }))) : (__builtin_constant_p (filename) && ((size_t)(const void *)((filename) + 1) - (size_t)(const void *)(filename) == 1) && (__s2_len = strlen (filename), __s2_len < 4) ? (__builtin_constant_p (fname) && ( (size_t)(const void *)((fname) + 1) - (size_t)(const void *)( fname) == 1) ? __builtin_strcmp (fname, filename) : (- (__extension__ ({ const unsigned char *__s2 = (const unsigned char *) (const char *) (fname); int __result = (((const unsigned char *) (const char *) (filename))[0] - __s2[0]); if (__s2_len > 0 && __result == 0) { __result = (((const unsigned char *) (const char *) (filename))[1] - __s2[1]); if (__s2_len > 1 && __result == 0) { __result = (((const unsigned char *) (const char *) (filename))[2] - __s2[2]); if (__s2_len > 2 && __result == 0) __result = (((const unsigned char *) (const char *) (filename))[3] - __s2[3]); } } __result; })))) : __builtin_strcmp (fname, filename)))); })) | |||
661 | return &graphics->images[j]; | |||
662 | } | |||
663 | } | |||
664 | ||||
665 | error_message(__FUNCTION__, "Obstacles texture atlas specifies element %s which is not expected.", | |||
666 | PLEASE_INFORM, filename); | |||
667 | return NULL((void*)0); | |||
668 | } | |||
669 | ||||
670 | static struct image *get_storage_for_obstacle_shadow_image(const char *filename) | |||
671 | { | |||
672 | int i, j; | |||
673 | const char *obstacle_filename = filename + strlen("shadow_"); | |||
674 | ||||
675 | for (i = 0; i < obstacle_map.size; i++) { | |||
676 | obstacle_spec *spec = get_obstacle_spec(i); | |||
677 | struct obstacle_graphics *graphics = &((struct obstacle_graphics *)obstacle_images.arr)[i]; | |||
678 | for (j = 0; j < spec->filenames.size; j++) { | |||
679 | const char *fname = ((char **)spec->filenames.arr)[j]; | |||
680 | if (!strcmp(fname, obstacle_filename)__extension__ ({ size_t __s1_len, __s2_len; (__builtin_constant_p (fname) && __builtin_constant_p (obstacle_filename) && (__s1_len = strlen (fname), __s2_len = strlen (obstacle_filename ), (!((size_t)(const void *)((fname) + 1) - (size_t)(const void *)(fname) == 1) || __s1_len >= 4) && (!((size_t)( const void *)((obstacle_filename) + 1) - (size_t)(const void * )(obstacle_filename) == 1) || __s2_len >= 4)) ? __builtin_strcmp (fname, obstacle_filename) : (__builtin_constant_p (fname) && ((size_t)(const void *)((fname) + 1) - (size_t)(const void * )(fname) == 1) && (__s1_len = strlen (fname), __s1_len < 4) ? (__builtin_constant_p (obstacle_filename) && ((size_t)(const void *)((obstacle_filename) + 1) - (size_t)( const void *)(obstacle_filename) == 1) ? __builtin_strcmp (fname , obstacle_filename) : (__extension__ ({ const unsigned char * __s2 = (const unsigned char *) (const char *) (obstacle_filename ); int __result = (((const unsigned char *) (const char *) (fname ))[0] - __s2[0]); if (__s1_len > 0 && __result == 0 ) { __result = (((const unsigned char *) (const char *) (fname ))[1] - __s2[1]); if (__s1_len > 1 && __result == 0 ) { __result = (((const unsigned char *) (const char *) (fname ))[2] - __s2[2]); if (__s1_len > 2 && __result == 0 ) __result = (((const unsigned char *) (const char *) (fname) )[3] - __s2[3]); } } __result; }))) : (__builtin_constant_p ( obstacle_filename) && ((size_t)(const void *)((obstacle_filename ) + 1) - (size_t)(const void *)(obstacle_filename) == 1) && (__s2_len = strlen (obstacle_filename), __s2_len < 4) ? ( __builtin_constant_p (fname) && ((size_t)(const void * )((fname) + 1) - (size_t)(const void *)(fname) == 1) ? __builtin_strcmp (fname, obstacle_filename) : (- (__extension__ ({ const unsigned char *__s2 = (const unsigned char *) (const char *) (fname); int __result = (((const unsigned char *) (const char *) (obstacle_filename ))[0] - __s2[0]); if (__s2_len > 0 && __result == 0 ) { __result = (((const unsigned char *) (const char *) (obstacle_filename ))[1] - __s2[1]); if (__s2_len > 1 && __result == 0 ) { __result = (((const unsigned char *) (const char *) (obstacle_filename ))[2] - __s2[2]); if (__s2_len > 2 && __result == 0 ) __result = (((const unsigned char *) (const char *) (obstacle_filename ))[3] - __s2[3]); } } __result; })))) : __builtin_strcmp (fname , obstacle_filename)))); })) | |||
681 | return &graphics->shadows[j]; | |||
682 | } | |||
683 | } | |||
684 | ||||
685 | error_message(__FUNCTION__, "Obstacle shadows texture atlas specifies element %s which is not expected.", | |||
686 | PLEASE_INFORM, filename); | |||
687 | return NULL((void*)0); | |||
688 | } | |||
689 | ||||
690 | void load_all_obstacles(int with_startup_bar) | |||
691 | { | |||
692 | int i, j; | |||
693 | struct image empty_image = EMPTY_IMAGE{ .surface = ((void*)0) , .offset_x = 0 , .offset_y = 0 , .texture_has_been_created = 0 , .cached_transformation = { ((void*)0), 0.0, 0.0, { 0.0 , 0.0, 0.0, 0.0}, 0 } }; | |||
694 | ||||
695 | if (load_texture_atlas("obstacles/atlas.txt", "obstacles/", get_storage_for_obstacle_image)) { | |||
696 | error_message(__FUNCTION__, "Unable to load texture atlas for obstacles at obstacles/atlas.txt.", PLEASE_INFORM | IS_FATAL); | |||
697 | } | |||
698 | ||||
699 | if (with_startup_bar) | |||
700 | next_startup_percentage(62); | |||
701 | ||||
702 | // Clear obstacle shadow images | |||
703 | // It's required because only subset of obstacles has got shadow | |||
704 | for (i = 0; i < obstacle_map.size; i++) { | |||
705 | obstacle_spec *spec = get_obstacle_spec(i); | |||
706 | struct obstacle_graphics *graphics = &((struct obstacle_graphics *)obstacle_images.arr)[i]; | |||
707 | for (j = 0; j < spec->filenames.size; j++) | |||
708 | memcpy(&graphics->shadows[j], &empty_image, sizeof(empty_image)); | |||
709 | } | |||
710 | ||||
711 | if (load_texture_atlas("obstacles/shadow_atlas.txt", "obstacles/", get_storage_for_obstacle_shadow_image)) | |||
712 | error_message(__FUNCTION__, "Unable to load texture atlas for obstacle shadows at obstacle/shadow_atlas.txt.", PLEASE_INFORM | IS_FATAL); | |||
713 | ||||
714 | if (with_startup_bar) | |||
715 | next_startup_percentage(8); | |||
716 | ||||
717 | validate_obstacle_graphics(); | |||
718 | } | |||
719 | ||||
720 | static struct image *get_storage_for_floor_tile(const char *filename) | |||
721 | { | |||
722 | int i, j; | |||
723 | ||||
724 | for (i = 0; i < underlay_floor_tiles.size; i++) { | |||
725 | struct floor_tile_spec *floor_tile = dynarray_member(&underlay_floor_tiles, i, sizeof(struct floor_tile_spec)); | |||
726 | for (j = 0; j < floor_tile->frames; j++) { | |||
727 | if (!strcmp(((char **)floor_tile->filenames.arr)[j], filename)__extension__ ({ size_t __s1_len, __s2_len; (__builtin_constant_p (((char **)floor_tile->filenames.arr)[j]) && __builtin_constant_p (filename) && (__s1_len = strlen (((char **)floor_tile ->filenames.arr)[j]), __s2_len = strlen (filename), (!((size_t )(const void *)((((char **)floor_tile->filenames.arr)[j]) + 1) - (size_t)(const void *)(((char **)floor_tile->filenames .arr)[j]) == 1) || __s1_len >= 4) && (!((size_t)(const void *)((filename) + 1) - (size_t)(const void *)(filename) == 1) || __s2_len >= 4)) ? __builtin_strcmp (((char **)floor_tile ->filenames.arr)[j], filename) : (__builtin_constant_p ((( char **)floor_tile->filenames.arr)[j]) && ((size_t )(const void *)((((char **)floor_tile->filenames.arr)[j]) + 1) - (size_t)(const void *)(((char **)floor_tile->filenames .arr)[j]) == 1) && (__s1_len = strlen (((char **)floor_tile ->filenames.arr)[j]), __s1_len < 4) ? (__builtin_constant_p (filename) && ((size_t)(const void *)((filename) + 1 ) - (size_t)(const void *)(filename) == 1) ? __builtin_strcmp (((char **)floor_tile->filenames.arr)[j], filename) : (__extension__ ({ const unsigned char *__s2 = (const unsigned char *) (const char *) (filename); int __result = (((const unsigned char *) (const char *) (((char **)floor_tile->filenames.arr)[j])) [0] - __s2[0]); if (__s1_len > 0 && __result == 0) { __result = (((const unsigned char *) (const char *) (((char **)floor_tile->filenames.arr)[j]))[1] - __s2[1]); if (__s1_len > 1 && __result == 0) { __result = (((const unsigned char *) (const char *) (((char **)floor_tile->filenames.arr )[j]))[2] - __s2[2]); if (__s1_len > 2 && __result == 0) __result = (((const unsigned char *) (const char *) (( (char **)floor_tile->filenames.arr)[j]))[3] - __s2[3]); } } __result; }))) : (__builtin_constant_p (filename) && ((size_t)(const void *)((filename) + 1) - (size_t)(const void *)(filename) == 1) && (__s2_len = strlen (filename), __s2_len < 4) ? (__builtin_constant_p (((char **)floor_tile ->filenames.arr)[j]) && ((size_t)(const void *)((( (char **)floor_tile->filenames.arr)[j]) + 1) - (size_t)(const void *)(((char **)floor_tile->filenames.arr)[j]) == 1) ? __builtin_strcmp (((char **)floor_tile->filenames.arr)[j], filename) : (- ( __extension__ ({ const unsigned char *__s2 = (const unsigned char *) (const char *) (((char **)floor_tile->filenames.arr)[j ]); int __result = (((const unsigned char *) (const char *) ( filename))[0] - __s2[0]); if (__s2_len > 0 && __result == 0) { __result = (((const unsigned char *) (const char *) ( filename))[1] - __s2[1]); if (__s2_len > 1 && __result == 0) { __result = (((const unsigned char *) (const char *) ( filename))[2] - __s2[2]); if (__s2_len > 2 && __result == 0) __result = (((const unsigned char *) (const char *) (filename ))[3] - __s2[3]); } } __result; })))) : __builtin_strcmp (((char **)floor_tile->filenames.arr)[j], filename)))); })) | |||
728 | return &floor_tile->images[j]; | |||
729 | } | |||
730 | } | |||
731 | ||||
732 | for (i = 0; i < overlay_floor_tiles.size; i++) { | |||
733 | struct floor_tile_spec *floor_tile = dynarray_member(&overlay_floor_tiles, i, sizeof(struct floor_tile_spec)); | |||
734 | for (j = 0; j < floor_tile->frames; j++) { | |||
735 | if (!strcmp(((char **)floor_tile->filenames.arr)[j], filename)__extension__ ({ size_t __s1_len, __s2_len; (__builtin_constant_p (((char **)floor_tile->filenames.arr)[j]) && __builtin_constant_p (filename) && (__s1_len = strlen (((char **)floor_tile ->filenames.arr)[j]), __s2_len = strlen (filename), (!((size_t )(const void *)((((char **)floor_tile->filenames.arr)[j]) + 1) - (size_t)(const void *)(((char **)floor_tile->filenames .arr)[j]) == 1) || __s1_len >= 4) && (!((size_t)(const void *)((filename) + 1) - (size_t)(const void *)(filename) == 1) || __s2_len >= 4)) ? __builtin_strcmp (((char **)floor_tile ->filenames.arr)[j], filename) : (__builtin_constant_p ((( char **)floor_tile->filenames.arr)[j]) && ((size_t )(const void *)((((char **)floor_tile->filenames.arr)[j]) + 1) - (size_t)(const void *)(((char **)floor_tile->filenames .arr)[j]) == 1) && (__s1_len = strlen (((char **)floor_tile ->filenames.arr)[j]), __s1_len < 4) ? (__builtin_constant_p (filename) && ((size_t)(const void *)((filename) + 1 ) - (size_t)(const void *)(filename) == 1) ? __builtin_strcmp (((char **)floor_tile->filenames.arr)[j], filename) : (__extension__ ({ const unsigned char *__s2 = (const unsigned char *) (const char *) (filename); int __result = (((const unsigned char *) (const char *) (((char **)floor_tile->filenames.arr)[j])) [0] - __s2[0]); if (__s1_len > 0 && __result == 0) { __result = (((const unsigned char *) (const char *) (((char **)floor_tile->filenames.arr)[j]))[1] - __s2[1]); if (__s1_len > 1 && __result == 0) { __result = (((const unsigned char *) (const char *) (((char **)floor_tile->filenames.arr )[j]))[2] - __s2[2]); if (__s1_len > 2 && __result == 0) __result = (((const unsigned char *) (const char *) (( (char **)floor_tile->filenames.arr)[j]))[3] - __s2[3]); } } __result; }))) : (__builtin_constant_p (filename) && ((size_t)(const void *)((filename) + 1) - (size_t)(const void *)(filename) == 1) && (__s2_len = strlen (filename), __s2_len < 4) ? (__builtin_constant_p (((char **)floor_tile ->filenames.arr)[j]) && ((size_t)(const void *)((( (char **)floor_tile->filenames.arr)[j]) + 1) - (size_t)(const void *)(((char **)floor_tile->filenames.arr)[j]) == 1) ? __builtin_strcmp (((char **)floor_tile->filenames.arr)[j], filename) : (- ( __extension__ ({ const unsigned char *__s2 = (const unsigned char *) (const char *) (((char **)floor_tile->filenames.arr)[j ]); int __result = (((const unsigned char *) (const char *) ( filename))[0] - __s2[0]); if (__s2_len > 0 && __result == 0) { __result = (((const unsigned char *) (const char *) ( filename))[1] - __s2[1]); if (__s2_len > 1 && __result == 0) { __result = (((const unsigned char *) (const char *) ( filename))[2] - __s2[2]); if (__s2_len > 2 && __result == 0) __result = (((const unsigned char *) (const char *) (filename ))[3] - __s2[3]); } } __result; })))) : __builtin_strcmp (((char **)floor_tile->filenames.arr)[j], filename)))); })) | |||
736 | return &floor_tile->images[j]; | |||
737 | } | |||
738 | } | |||
739 | ||||
740 | error_message(__FUNCTION__, "Floor tiles texture atlas specifies element %s which is not expected.", | |||
741 | PLEASE_INFORM, filename); | |||
742 | return NULL((void*)0); | |||
743 | } | |||
744 | ||||
745 | /** | |||
746 | * This function loads isometric floor tiles, and in OpenGL mode, generates | |||
747 | * a texture atlas. | |||
748 | * | |||
749 | */ | |||
750 | void load_floor_tiles(void) | |||
751 | { | |||
752 | // Try to load the atlas | |||
753 | if (load_texture_atlas("floor_tiles/atlas.txt", "floor_tiles/", get_storage_for_floor_tile)) { | |||
754 | error_message(__FUNCTION__, "Unable to load floor tiles atlas at floor_tiles/atlas.txt.", PLEASE_INFORM | IS_FATAL); | |||
755 | } | |||
756 | } | |||
757 | ||||
758 | void free_floor_tiles(void) | |||
759 | { | |||
760 | int i, j; | |||
761 | ||||
762 | for (i = 0; i < underlay_floor_tiles.size; i++) { | |||
763 | struct floor_tile_spec *floor_tile = dynarray_member(&underlay_floor_tiles, i, sizeof(struct floor_tile_spec)); | |||
764 | for (j = 0; j < floor_tile->frames; j++) { | |||
765 | delete_image(&floor_tile->images[j]); | |||
766 | } | |||
767 | } | |||
768 | ||||
769 | for (i = 0; i < overlay_floor_tiles.size; i++) { | |||
770 | struct floor_tile_spec *floor_tile = dynarray_member(&overlay_floor_tiles, i, sizeof(struct floor_tile_spec)); | |||
771 | for (j = 0; j < floor_tile->frames; j++) { | |||
772 | delete_image(&floor_tile->images[j]); | |||
773 | } | |||
774 | } | |||
775 | } | |||
776 | ||||
777 | static int current_tux_motion_class; | |||
778 | static int current_tux_part_group; | |||
779 | ||||
780 | static struct image *get_storage_for_tux_image(const char *filename) | |||
781 | { | |||
782 | int rotation; | |||
783 | int phase; | |||
784 | ||||
785 | if (sscanf(filename, "tux_rot_%02d_phase_%02d.png", &rotation, &phase) != 2) { | |||
786 | error_message(__FUNCTION__, "Invalid filename '%s' in tux texture atlas.", | |||
787 | PLEASE_INFORM, filename); | |||
788 | return NULL((void*)0); | |||
789 | } | |||
790 | ||||
791 | if (rotation >= MAX_TUX_DIRECTIONS16) { | |||
792 | error_message(__FUNCTION__, "Invalid rotation index %d in tux texture atlas.\n" | |||
793 | "Maximum allowed value for the rotation index is %d.", PLEASE_INFORM, | |||
794 | rotation, MAX_TUX_DIRECTIONS16 - 1); | |||
795 | return NULL((void*)0); | |||
796 | } | |||
797 | ||||
798 | if (phase >= TUX_TOTAL_PHASES35) { | |||
799 | error_message(__FUNCTION__, "Invalid phase index %d in tux texture atlas.\n" | |||
800 | "Maximum allowed value for the phase index is %d.", PLEASE_INFORM, | |||
801 | phase, TUX_TOTAL_PHASES35 - 1); | |||
802 | return NULL((void*)0); | |||
803 | } | |||
804 | ||||
805 | return &tux_images[current_tux_motion_class].part_images[current_tux_part_group][phase][rotation]; | |||
806 | } | |||
807 | ||||
808 | /** | |||
809 | * Load the tux image part group for the given motion class. | |||
810 | */ | |||
811 | void load_tux_graphics(int motion_class, int tux_part_group, const char *part_string) | |||
812 | { | |||
813 | char atlas_filename[4096]; | |||
814 | char atlas_directory[4096]; | |||
815 | static char *part_group_strings[ALL_PART_GROUPS] = { | |||
816 | "head/", | |||
817 | "shield/", | |||
818 | "torso/", | |||
819 | "feet/", | |||
820 | "weapon/", | |||
821 | "weaponarm/" | |||
822 | }; | |||
823 | ||||
824 | sprintf(atlas_directory, "tux_motion_parts/%s/%s%s/", | |||
825 | get_motion_class_name_by_id(motion_class), part_group_strings[tux_part_group], part_string); | |||
826 | sprintf(atlas_filename, "%s/atlas.txt", atlas_directory); | |||
827 | ||||
828 | current_tux_motion_class = motion_class; | |||
829 | current_tux_part_group = tux_part_group; | |||
830 | if (load_texture_atlas(atlas_filename, atlas_directory, get_storage_for_tux_image)) { | |||
831 | error_message(__FUNCTION__, "Unable to load tux texture atlas at %s.", | |||
832 | PLEASE_INFORM | IS_FATAL, atlas_filename); | |||
833 | } | |||
834 | } | |||
835 | ||||
836 | /** | |||
837 | * Force tux graphics to reload. | |||
838 | */ | |||
839 | void reload_tux_graphics(void) | |||
840 | { | |||
841 | int i, j; | |||
842 | ||||
843 | // Clear tux part strings. It will force tux graphics to reload. | |||
844 | for (i = 0; i < tux_rendering.motion_class_names.size; i++) { | |||
845 | struct tux_motion_class_images *motion_class = &tux_images[i]; | |||
846 | for (j = 0; j < ALL_PART_GROUPS; j++) | |||
847 | motion_class->part_names[j][0] = '\0'; | |||
848 | } | |||
849 | } | |||
850 | ||||
851 | #undef _blocks_c |