Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
1 | pmbaty | 1 | /* |
2 | SDLPoP, a port/conversion of the DOS game Prince of Persia. |
||
3 | Copyright (C) 2013-2018 Dávid Nagy |
||
4 | |||
5 | This program is free software: you can redistribute it and/or modify |
||
6 | it under the terms of the GNU General Public License as published by |
||
7 | the Free Software Foundation, either version 3 of the License, or |
||
8 | (at your option) any later version. |
||
9 | |||
10 | This program is distributed in the hope that it will be useful, |
||
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||
13 | GNU General Public License for more details. |
||
14 | |||
15 | You should have received a copy of the GNU General Public License |
||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. |
||
17 | |||
18 | The authors of this program may be contacted at http://forum.princed.org |
||
19 | */ |
||
20 | |||
21 | #include "common.h" |
||
22 | |||
23 | #ifdef USE_SCREENSHOT |
||
24 | |||
25 | // TODO: Use incrementing numbers and a separate folder, like DOSBox? Or allow custom filenames. |
||
26 | const char screenshot_filename[] = "screenshot.png"; |
||
27 | |||
28 | #define EVENT_OFFSET 0 // Add this number to displayed event numbers. Use 1 for Apoplexy compatibility. |
||
29 | |||
30 | #define NUMBER_OF_ROOMS 24 |
||
31 | |||
32 | // Save a screenshot. |
||
33 | void save_screenshot() { |
||
34 | IMG_SavePNG(onscreen_surface_, screenshot_filename); |
||
35 | printf("Saved screenshot to \"%s\".\n", screenshot_filename); |
||
36 | } |
||
37 | |||
38 | // Switch to the given room and draw it. |
||
39 | void switch_to_room(int room) { |
||
40 | drawn_room = room; |
||
41 | load_room_links(); |
||
42 | |||
43 | if (tbl_level_type[current_level]) { |
||
44 | gen_palace_wall_colors(); |
||
45 | } |
||
46 | |||
47 | // for guards |
||
48 | Guard.direction = dir_56_none; |
||
49 | guardhp_curr = 0; // otherwise guard HPs stay on screen |
||
50 | draw_guard_hp(0, 10); // otherwise guard HPs still stay on screen if some guards have extra HP |
||
51 | enter_guard(); // otherwise the guard won't show up |
||
52 | check_shadow(); // otherwise the shadow won't appear on level 6 |
||
53 | |||
54 | // for potion bubbles |
||
55 | for (int tilepos=0;tilepos<30;tilepos++) { |
||
56 | int tile_type = curr_room_tiles[tilepos] & 0x1F; |
||
57 | if (tile_type == tiles_10_potion) { |
||
58 | int modifier = curr_room_modif[tilepos]; |
||
59 | if ((modifier & 7) == 0) curr_room_modif[tilepos]++; |
||
60 | } |
||
61 | } |
||
62 | |||
63 | redraw_screen(1); |
||
64 | } |
||
65 | |||
66 | bool event_used[256] = {false}; |
||
67 | bool has_trigger_potion = false; |
||
68 | |||
69 | // delta vectors for room links |
||
70 | const int dx[4] = {-1, +1, 0, 0}; |
||
71 | const int dy[4] = { 0, 0, -1, +1}; |
||
72 | |||
73 | int xpos[NUMBER_OF_ROOMS+1] = {0}; |
||
74 | int ypos[NUMBER_OF_ROOMS+1] = {0}; |
||
75 | |||
76 | // Show annotations for non-visible things, like: room bounds, room numbers, door events, loose floors, potion types, special events, ... |
||
77 | // (this will make the function even more like a cheat) |
||
78 | // TODO: guard HPs, skill? fake tiles? |
||
79 | void draw_extras() { |
||
80 | // ambiguous tiles |
||
81 | // The editor branch has something similar... |
||
82 | for (int tilepos=0;tilepos<30;tilepos++) { |
||
83 | int tile_type = curr_room_tiles[tilepos] & 0x1F; |
||
84 | int modifier = curr_room_modif[tilepos]; |
||
85 | int row = tilepos/10; |
||
86 | int col = tilepos%10; |
||
87 | int y = row * 63 + 3; |
||
88 | int x = col * 32; |
||
89 | |||
90 | // special floors |
||
91 | rect_type floor_rect = {y+60-3, x, y+63-3, x+32}; |
||
92 | |||
93 | // loose floors |
||
94 | if (tile_type == tiles_11_loose) { |
||
95 | int color = color_15_brightwhite; |
||
96 | if (curr_room_tiles[tilepos] & 0x20) color = color_13_brightmagenta; // stable loose floor |
||
97 | show_text_with_color(&floor_rect, 0, -1, "~~~~", color); |
||
98 | } |
||
99 | |||
100 | // buttons |
||
101 | if (tile_type == tiles_15_opener) { |
||
102 | show_text_with_color(&floor_rect, 0, -1, "^^^^", color_10_brightgreen); |
||
103 | } |
||
104 | if (tile_type == tiles_6_closer) { |
||
105 | //show_text_with_color(&floor_rect, 0, -1, "XXXX", color_12_brightred); |
||
106 | floor_rect.top -= 2; |
||
107 | show_text_with_color(&floor_rect, 0, -1, "xxxx", color_12_brightred); // Only the top half is visible, looks like an inverted "^" or a tiny "v". |
||
108 | } |
||
109 | |||
110 | bool is_trob_here = false; |
||
111 | for (int index = 0; index < trobs_count; ++index) { |
||
112 | trob = trobs[index]; |
||
113 | if (trob.room == drawn_room && trob.tilepos == tilepos) { |
||
114 | is_trob_here = true; |
||
115 | break; |
||
116 | } |
||
117 | } |
||
118 | |||
119 | if (!is_trob_here) { // It's not stuck if it's currently animated. |
||
120 | // harmless spikes |
||
121 | if (tile_type == tiles_2_spike) { |
||
122 | if (modifier >= 5) { // harmless |
||
123 | rect_type spike_rect = {y+50, x, y+60, x+32}; |
||
124 | show_text_with_color(&spike_rect, 0, -1, "safe", color_10_brightgreen); |
||
125 | } |
||
126 | } |
||
127 | |||
128 | // stuck chompers |
||
129 | if (tile_type == tiles_18_chomper) { |
||
130 | int frame = (modifier & 0x7F); |
||
131 | if (frame != 0) { |
||
132 | rect_type chomper_rect = {y, x-10, y+60, x+32+10}; |
||
133 | int color = color_10_brightgreen; |
||
134 | if (frame == 2) color = color_12_brightred; |
||
135 | show_text_with_color(&chomper_rect, 0, 0, "stuck", color); |
||
136 | } |
||
137 | } |
||
138 | } |
||
139 | |||
140 | // potion types |
||
141 | if (tile_type == tiles_10_potion) { |
||
142 | struct pot_type { |
||
143 | int color; |
||
144 | const char* text; |
||
145 | } pot_types[7] = { |
||
146 | {color_7_lightgray, "x"}, // empty |
||
147 | {color_12_brightred, "+1"}, // heal |
||
148 | {color_12_brightred, "+++"}, // life |
||
149 | {color_10_brightgreen, "slow\nfall"}, // slow fall |
||
150 | {color_10_brightgreen, "flip"}, // upside down |
||
151 | {color_9_brightblue, "-1"}, // hurt |
||
152 | {color_9_brightblue, "trig"}, // open |
||
153 | }; |
||
154 | int potion_type = modifier >> 3; |
||
155 | int color; |
||
156 | const char* text; |
||
157 | char temp_text[4]; |
||
158 | if (potion_type >= 0 && potion_type < 7) { |
||
159 | color = pot_types[potion_type].color; |
||
160 | text = pot_types[potion_type].text; |
||
161 | } else { |
||
162 | color = color_15_brightwhite; |
||
163 | snprintf(temp_text, sizeof(temp_text), "%d", potion_type); |
||
164 | text = temp_text; |
||
165 | } |
||
166 | rect_type pot_rect = {y+40, x, y+60, x+32}; |
||
167 | show_text_with_color(&pot_rect, 0, -1, text, color); |
||
168 | } |
||
169 | |||
170 | // triggered door events |
||
171 | if (tile_type == tiles_6_closer || tile_type == tiles_15_opener |
||
172 | // These tiles are triggered even if they are not buttons! |
||
173 | /* |
||
174 | || (current_level == 1 && drawn_room == 5 && tilepos == 2) // triggered at start |
||
175 | || (current_level == 13 && drawn_room == 24 && tilepos == 0) // triggered when player enters any room from the right after Jaffar died |
||
176 | */ |
||
177 | || (has_trigger_potion && drawn_room == 8 && tilepos == 0) // triggered when player drinks an open potion |
||
178 | ) { |
||
179 | int first_event = modifier; |
||
180 | int last_event = modifier; |
||
181 | while (last_event<256 && get_doorlink_next(last_event)) last_event++; |
||
182 | /* |
||
183 | char events[10]; |
||
184 | if (modifier==last_event) { |
||
185 | snprintf(events, sizeof(events), "%d", first_event+EVENT_OFFSET); |
||
186 | } else { // from-to |
||
187 | snprintf(events, sizeof(events), "%d:%d", first_event+EVENT_OFFSET, last_event+EVENT_OFFSET); |
||
188 | } |
||
189 | */ |
||
190 | char events[256*4] = ""; // More than enough space to list all the numbers from 0 to 255. |
||
191 | int events_pos = 0; |
||
192 | for (int event=first_event; event<=last_event && events_pos<sizeof(events); event++) { |
||
193 | int len = snprintf(events+events_pos, sizeof(events)-events_pos, "%d ", event+EVENT_OFFSET); |
||
194 | if (len < 0) break; // snprintf might return -1 if the buffer is too small. |
||
195 | events_pos += len; |
||
196 | } |
||
197 | --events_pos; |
||
198 | if (events_pos>0 && events_pos<sizeof(events)) events[events_pos]='\0'; // trim trailing space |
||
199 | rect_type buttonmod_rect = {y/*+50-3*/, x, y+60-3, x+32}; |
||
200 | show_text_with_color(&buttonmod_rect, 0, 1, events, color_14_brightyellow); |
||
201 | } |
||
202 | |||
203 | // TODO: Add an option to merge events pointing to the same tile? |
||
204 | |||
205 | // door events that point here |
||
206 | char events[256*4] = ""; |
||
207 | int events_pos = 0; |
||
208 | for (int event=0; event<256 && events_pos<sizeof(events); event++) { |
||
209 | if (event_used[event] && get_doorlink_room(event) == drawn_room && get_doorlink_tile(event) == tilepos) { |
||
210 | int len = snprintf(events+events_pos, sizeof(events)-events_pos, "%d ", event+EVENT_OFFSET); |
||
211 | if (len < 0) break; |
||
212 | events_pos += len; |
||
213 | } |
||
214 | } |
||
215 | --events_pos; |
||
216 | if (events_pos>0 && events_pos<sizeof(events)) events[events_pos]='\0'; // trim trailing space |
||
217 | if (*events) { |
||
218 | //printf("room %d, tile %d, events: %s\n", drawn_room, tilepos, events); // debug |
||
219 | rect_type events_rect = {y,x,y+63-3,x+32-7}; |
||
220 | show_text_with_color(&events_rect, 0, 1, events, color_14_brightyellow); |
||
221 | } |
||
222 | |||
223 | // special events |
||
224 | char* special_event = NULL; |
||
225 | if (current_level == 0 && drawn_room == 24) { |
||
226 | special_event = "exit"; // exit by entering this room |
||
227 | } |
||
228 | // not marked: level 1 falling entry |
||
229 | if (current_level == 1 && drawn_room == 5 && tilepos == 2) { |
||
230 | special_event = "start\ntrig"; // triggered at start |
||
231 | } |
||
232 | if (current_level == 3 && drawn_room == 7 && col == 0) { |
||
233 | special_event = "<-\nchk point"; // checkpoint activation |
||
234 | } |
||
235 | if (current_level == 3 && drawn_room == 7 && tilepos == 4) { |
||
236 | special_event = "removed"; // loose floor is removed |
||
237 | } |
||
238 | if (current_level == 3 && drawn_room == 2 && tile_type == tiles_4_gate) { |
||
239 | special_event = "loud"; // closing can be heard everywhere |
||
240 | } |
||
241 | if (current_level == 3 && drawn_room == 2 && tilepos == 6) { |
||
242 | special_event = "check point"; // restart at checkpoint |
||
243 | // TODO: Show this room even if it is unreachable from the start via room links? |
||
244 | } |
||
245 | if (current_level == 3 && drawn_room == 1 && tilepos == 15 && tile_type == tiles_21_skeleton) { |
||
246 | special_event = "skel wake"; // skeleton wakes |
||
247 | } |
||
248 | if (current_level == 3 && drawn_room == 3 && tilepos == 14) { |
||
249 | special_event = "skel cont"; // skeleton continue |
||
250 | } |
||
251 | if (current_level == 4 && drawn_room == 4 && tilepos == 4) { |
||
252 | special_event = "mirror"; // mirror appears |
||
253 | } |
||
254 | // not marked: level 4 mirror clip |
||
255 | // not marked: level 5 shadow, required opening gate |
||
256 | if (current_level == 5 && drawn_room == 24 && tilepos == 3 && tile_type == tiles_10_potion) { |
||
257 | special_event = "stolen"; // stolen potion |
||
258 | } |
||
259 | // not marked: level 6 shadow (it's already visible) |
||
260 | if (current_level == 6 && drawn_room == 1 && row == 2) { |
||
261 | special_event = "exit\ndown"; // exit by falling |
||
262 | } |
||
263 | // not marked: level 7 falling entry |
||
264 | if (current_level == 8 && drawn_room == 16 && tilepos == 9) { |
||
265 | special_event = "mouse"; // mouse comes |
||
266 | } |
||
267 | if (current_level == 12 && drawn_room == 15 && tilepos == 1 && tile_type == tiles_22_sword) { |
||
268 | special_event = "disapp"; // sword disappears |
||
269 | } |
||
270 | if (current_level == 12 && drawn_room == 18 && col == 9) { |
||
271 | special_event = "disapp\n->"; // sword disappears |
||
272 | } |
||
273 | // not marked: level 12 shadow |
||
274 | if (current_level == 12 && row == 0 && (drawn_room == 2 || (drawn_room == 13 && col >= 6))) { |
||
275 | special_event = "floor"; // floors appear |
||
276 | } |
||
277 | if (current_level == 12 && drawn_room == 23) { |
||
278 | special_event = "exit"; // exit by entering this room |
||
279 | } |
||
280 | if (current_level == 13 && (drawn_room == level.roomlinks[23-1].up || drawn_room == level.roomlinks[16-1].up) && (tilepos >= 22 && tilepos <= 27)) { |
||
281 | special_event = "fall"; // falling loose floors |
||
282 | } |
||
283 | if (current_level == 13 && drawn_room == 3 && col == 9) { |
||
284 | special_event = "meet\n->"; // meet Jaffar |
||
285 | } |
||
286 | // not marked: flash |
||
287 | if (current_level == 13 && drawn_room == 24 && tilepos == 0) { |
||
288 | special_event = "Jffr\ntrig"; // triggered when player enters any room from the right after Jaffar died |
||
289 | } |
||
290 | if (current_level == 14 && drawn_room == 5) { |
||
291 | special_event = "end"; // end of game |
||
292 | } |
||
293 | if (has_trigger_potion && drawn_room == 8 && tilepos == 0) { |
||
294 | special_event = "blue\ntrig"; // triggered when player drinks an open potion |
||
295 | } |
||
296 | if (special_event) { |
||
297 | rect_type event_rect = {y,x-10,y+63,x+32+10}; |
||
298 | show_text_with_color(&event_rect, 0, 0, special_event, color_14_brightyellow); |
||
299 | } |
||
300 | |||
301 | // Attempt to show broken room links: |
||
302 | byte* roomlinks = (byte*)(&level.roomlinks[drawn_room-1]); |
||
303 | for (int direction = 0; direction < 4; direction++) { |
||
304 | int other_room = roomlinks[direction]; |
||
305 | if (other_room >= 1 && other_room <= NUMBER_OF_ROOMS) { |
||
306 | int other_x = xpos[drawn_room] + dx[direction]; |
||
307 | int other_y = ypos[drawn_room] + dy[direction]; |
||
308 | // If the linked room was placed elsewhere: Write the number of the linked room to the corresponding edge of the room. |
||
309 | if (xpos[other_room] != other_x || ypos[other_room] != other_y) { |
||
310 | int center_x = 160+dx[direction]*150; |
||
311 | int center_y = 96+dy[direction]*85; |
||
312 | rect_type text_rect = {center_y-6, center_x-10, center_y+6, center_x+10}; |
||
313 | char room_num[4]; |
||
314 | snprintf(room_num, sizeof(room_num), "%d", other_room); |
||
315 | method_5_rect(&text_rect, 0, color_4_red); |
||
316 | show_text_with_color(&text_rect, 0, 0, room_num, color_15_brightwhite); |
||
317 | } |
||
318 | } |
||
319 | } |
||
320 | |||
321 | // start pos |
||
322 | if (level.start_room == drawn_room && level.start_pos == tilepos) { |
||
323 | byte start_dir = level.start_dir; |
||
324 | if (current_level == 1 || current_level == 13) start_dir ^= 0xFF; // falling/running entry |
||
325 | char* start_text = (start_dir == dir_0_right) ? "start\n->" : "start\n<-"; |
||
326 | rect_type start_rect = {y,x-10,y+63,x+32+10}; |
||
327 | show_text_with_color(&start_rect, 0, 0, start_text, color_14_brightyellow); |
||
328 | } |
||
329 | |||
330 | } |
||
331 | |||
332 | // room number |
||
333 | char room_num[4]; |
||
334 | snprintf(room_num, sizeof(room_num), "%d", drawn_room); |
||
335 | rect_type text_rect = {10, 10, 21, 30}; |
||
336 | method_5_rect(&text_rect, 0, color_8_darkgray); |
||
337 | show_text_with_color(&text_rect, 0, 0, room_num, color_15_brightwhite); |
||
338 | |||
339 | // grid lines |
||
340 | rect_type vline = {0,0,192,1}; |
||
341 | method_5_rect(&vline, 0, color_12_brightred); |
||
342 | rect_type hline = {3,0,4,320}; |
||
343 | method_5_rect(&hline, 0, color_12_brightred); |
||
344 | } |
||
345 | |||
346 | // Save a "screenshot" of the whole level. |
||
347 | void save_level_screenshot(bool want_extras) { |
||
348 | // TODO: Disable in the intro or if a cutscene is active? |
||
349 | |||
350 | // Restrict this to cheat mode. After all, it's like using H/J/U/N or opening the level in an editor. |
||
351 | if (!cheats_enabled) return; |
||
352 | |||
353 | upside_down = 0; |
||
354 | |||
355 | //printf("random_seed = 0x%08X\n", random_seed); |
||
356 | |||
357 | // First, figure out where to put each room. |
||
358 | // We don't stop on broken room links, because the resulting map might still be usable. |
||
359 | |||
360 | bool processed[NUMBER_OF_ROOMS+1] = {false}; |
||
361 | for (int room=1;room<=NUMBER_OF_ROOMS;room++) { |
||
362 | xpos[drawn_room] = -999; |
||
363 | ypos[drawn_room] = -999; |
||
364 | } |
||
365 | xpos[drawn_room] = 0; |
||
366 | ypos[drawn_room] = 0; |
||
367 | int queue[NUMBER_OF_ROOMS] = {drawn_room}; // We start mapping from the current room. |
||
368 | int queue_start = 0; |
||
369 | int queue_end = 1; |
||
370 | |||
371 | while (queue_start < queue_end) { |
||
372 | int room = queue[queue_start++]; |
||
373 | byte* roomlinks = (byte*)(&level.roomlinks[room-1]); |
||
374 | for (int direction = 0; direction < 4; direction++) { |
||
375 | int other_room = roomlinks[direction]; |
||
376 | if (other_room >= 1 && other_room <= NUMBER_OF_ROOMS && !processed[other_room]) { |
||
377 | int other_x = xpos[room] + dx[direction]; |
||
378 | int other_y = ypos[room] + dy[direction]; |
||
379 | xpos[other_room] = other_x; |
||
380 | ypos[other_room] = other_y; |
||
381 | processed[other_room] = true; |
||
382 | queue[queue_end++] = other_room; |
||
383 | } |
||
384 | } |
||
385 | } |
||
386 | |||
387 | int min_x=0, max_x=0, min_y=0, max_y=0; |
||
388 | for (int room=1;room<=NUMBER_OF_ROOMS;room++) { |
||
389 | if (xpos[room] < min_x) min_x = xpos[room]; |
||
390 | if (xpos[room] > max_x) max_x = xpos[room]; |
||
391 | if (ypos[room] < min_y) min_y = ypos[room]; |
||
392 | if (ypos[room] > max_y) max_y = ypos[room]; |
||
393 | } |
||
394 | |||
395 | int map_width = max_x-min_x+1; |
||
396 | int map_height = max_y-min_y+1; |
||
397 | |||
398 | #define MAX_MAP_SIZE NUMBER_OF_ROOMS |
||
399 | int map[MAX_MAP_SIZE][MAX_MAP_SIZE] = {{0}}; |
||
400 | for (int room=1;room<=NUMBER_OF_ROOMS;room++) { |
||
401 | if (processed[room]) { |
||
402 | int y = ypos[room] - min_y; |
||
403 | int x = xpos[room] - min_x; |
||
404 | if (x>=0 && y>=0 && x<MAX_MAP_SIZE && y<MAX_MAP_SIZE) { |
||
405 | if (map[y][x]) { |
||
406 | printf("Warning: room %d was mapped to the same place as room %d!\n", room, map[y][x]); |
||
407 | // Force broken link display for room links pointing into this room: |
||
408 | // TODO: Try to find some other place for this room? |
||
409 | xpos[room] = -999; |
||
410 | ypos[room] = -999; |
||
411 | } else { |
||
412 | map[y][x] = room; |
||
413 | } |
||
414 | } |
||
415 | } |
||
416 | } |
||
417 | |||
418 | // Debug printout of arrangement. |
||
419 | /* |
||
420 | printf("LEVEL %d\n", current_level); |
||
421 | for (int y=0;y<map_height;y++) { |
||
422 | for (int x=0;x<map_width;x++) { |
||
423 | int room = map[y][x]; |
||
424 | if (room) { |
||
425 | printf(" %2d", room); |
||
426 | } else { |
||
427 | printf(" "); |
||
428 | } |
||
429 | } |
||
430 | printf("\n"); |
||
431 | } |
||
432 | printf("\n"); |
||
433 | */ |
||
434 | |||
435 | // Now we have the arrangement, let's make the picture! |
||
436 | |||
437 | int image_width = map_width*320; |
||
438 | int image_height = map_height*189+3+8; |
||
439 | |||
440 | SDL_Surface* map_surface = SDL_CreateRGBSurface(0, image_width, image_height, 32, 0xFF, 0xFF<<8, 0xFF<<16, 0xFF<<24); |
||
441 | if (map_surface == NULL) { |
||
442 | sdlperror("SDL_CreateRGBSurface (map_surface)"); |
||
443 | //exit(1); |
||
444 | return; |
||
445 | } |
||
446 | |||
447 | // TODO: Background color for places where there is no room? |
||
448 | |||
449 | // TODO: Add an option for displaying all unreachable rooms? |
||
450 | |||
451 | has_trigger_potion = false; |
||
452 | |||
453 | // Is there a trigger potion on the level? |
||
454 | for (int room=1;room<=NUMBER_OF_ROOMS;room++) { |
||
455 | if (processed[room]) { |
||
456 | get_room_address(room); |
||
457 | for (int tilepos=0;tilepos<30;tilepos++) { |
||
458 | int tile_type = curr_room_tiles[tilepos] & 0x1F; |
||
459 | if (tile_type == tiles_10_potion && curr_room_modif[tilepos] >> 3 == 6) { |
||
460 | has_trigger_potion = true; |
||
461 | } |
||
462 | } |
||
463 | } |
||
464 | } |
||
465 | |||
466 | memset(event_used, 0, sizeof(event_used)); |
||
467 | |||
468 | // Find out which door events are used: |
||
469 | for (int room=1;room<=NUMBER_OF_ROOMS;room++) { |
||
470 | if (processed[room]) { |
||
471 | get_room_address(room); |
||
472 | for (int tilepos=0;tilepos<30;tilepos++) { |
||
473 | int tile_type = curr_room_tiles[tilepos] & 0x1F; |
||
474 | if (tile_type == tiles_6_closer || tile_type == tiles_15_opener |
||
475 | // These tiles are triggered even if they are not buttons! |
||
476 | // TODO: Force displaying of special trigger rooms even if they are unreachable via room links? |
||
477 | /* |
||
478 | || (current_level == 1 && room == 5 && tilepos == 2) // triggered at start |
||
479 | || (current_level == 13 && room == 24 && tilepos == 0) // triggered when player enters any room from the right after Jaffar died |
||
480 | */ |
||
481 | || (has_trigger_potion && room == 8 && tilepos == 0) // triggered when player drinks an open potion |
||
482 | ) { |
||
483 | int modifier = curr_room_modif[tilepos]; |
||
484 | for (int index = modifier; index < 256; index++) { |
||
485 | event_used[index] = true; |
||
486 | if (!get_doorlink_next(index)) break; |
||
487 | } |
||
488 | } |
||
489 | } |
||
490 | } |
||
491 | } |
||
492 | |||
493 | // debug |
||
494 | /* |
||
495 | printf("Used events:"); |
||
496 | for (int event=0;event<256;event++) { |
||
497 | if (event_used[event]) { |
||
498 | printf(" %d", event+EVENT_OFFSET); |
||
499 | } |
||
500 | } |
||
501 | printf("\n"); |
||
502 | */ |
||
503 | /* |
||
504 | for (int event=0;event<256;event++) { |
||
505 | if (event_used[event]) { |
||
506 | printf("event %d: room %d tile %d %s\n", |
||
507 | event+EVENT_OFFSET, get_doorlink_room(event), get_doorlink_tile(event), |
||
508 | get_doorlink_next(event) ? "+next" : ""); |
||
509 | } |
||
510 | } |
||
511 | */ |
||
512 | |||
513 | screen_updates_suspended = true; |
||
514 | int old_room = drawn_room; |
||
515 | for (int y=0;y<map_height;y++) { |
||
516 | for (int x=0;x<map_width;x++) { |
||
517 | int room = map[y][x]; |
||
518 | if (room) { |
||
519 | SDL_Rect dest_rect; |
||
520 | dest_rect.x = x*320; |
||
521 | dest_rect.y = y*189; |
||
522 | switch_to_room(room); |
||
523 | |||
524 | if (want_extras) draw_extras(); |
||
525 | |||
526 | // TODO: Hide the status bar, or maybe show some custom text on it? |
||
527 | |||
528 | SDL_BlitSurface(onscreen_surface_, NULL, map_surface, &dest_rect); |
||
529 | } |
||
530 | } |
||
531 | } |
||
532 | switch_to_room(old_room); |
||
533 | screen_updates_suspended = false; |
||
534 | |||
535 | IMG_SavePNG(map_surface, screenshot_filename); |
||
536 | printf("Saved level screenshot to \"%s\".\n", screenshot_filename); |
||
537 | |||
538 | SDL_FreeSurface(map_surface); |
||
539 | |||
540 | //printf("random_seed = 0x%08X\n", random_seed); |
||
541 | } |
||
542 | |||
543 | bool want_auto = false; |
||
544 | bool want_auto_whole_level = false; |
||
545 | bool want_auto_extras = false; |
||
546 | |||
547 | void init_screenshot() { |
||
548 | // Command-line options to automatically save a screenshot at startup. |
||
549 | const char* screenshot_param = check_param("--screenshot"); |
||
550 | if (screenshot_param != NULL) { |
||
551 | // We require megahit+levelnumber. |
||
552 | if (start_level < 0) { |
||
553 | printf("You must supply a level number if you want to make an automatic screenshot!\n"); |
||
554 | exit(1); |
||
555 | } else { |
||
556 | want_auto = true; |
||
557 | want_auto_whole_level = (check_param("--screenshot-level") != NULL); |
||
558 | want_auto_extras = (check_param("--screenshot-level-extras") != NULL); |
||
559 | } |
||
560 | } |
||
561 | } |
||
562 | |||
563 | // TODO: Don't open a window if the user wants an auto screenshot. |
||
564 | |||
565 | // To skip cutscenes, etc. |
||
566 | bool want_auto_screenshot() { |
||
567 | return want_auto; |
||
568 | } |
||
569 | |||
570 | // Called when the level is drawn for the first time. |
||
571 | void auto_screenshot() { |
||
572 | if (!want_auto) return; |
||
573 | |||
574 | if (want_auto_whole_level) { |
||
575 | save_level_screenshot(want_auto_extras); |
||
576 | } else { |
||
577 | save_screenshot(); |
||
578 | } |
||
579 | |||
580 | quit(1); |
||
581 | } |
||
582 | |||
583 | #endif |
||
584 |