1 /***********************************************************
2 * Rocks'n'Diamonds -- McDuffin Strikes Back! *
3 *----------------------------------------------------------*
4 * (c) 1995-2006 Artsoft Entertainment *
6 * Detmolder Strasse 189 *
9 * e-mail: info@artsoft.org *
10 *----------------------------------------------------------*
12 ***********************************************************/
16 #include "libgame/libgame.h"
28 /* select level set with EMC X11 graphics before activating EM GFX debugging */
29 #define DEBUG_EM_GFX 0
31 /* tool button identifiers */
32 #define TOOL_CTRL_ID_YES 0
33 #define TOOL_CTRL_ID_NO 1
34 #define TOOL_CTRL_ID_CONFIRM 2
35 #define TOOL_CTRL_ID_PLAYER_1 3
36 #define TOOL_CTRL_ID_PLAYER_2 4
37 #define TOOL_CTRL_ID_PLAYER_3 5
38 #define TOOL_CTRL_ID_PLAYER_4 6
40 #define NUM_TOOL_BUTTONS 7
42 /* constants for number of doors and door parts */
44 #define NUM_PANELS NUM_DOORS
45 // #define NUM_PANELS 0
46 #define MAX_PARTS_PER_DOOR 8
47 #define MAX_DOOR_PARTS (NUM_DOORS * MAX_PARTS_PER_DOOR + NUM_PANELS)
48 #define DOOR_PART_IS_PANEL(i) ((i) >= NUM_DOORS * MAX_PARTS_PER_DOOR)
51 struct DoorPartOrderInfo
57 static struct DoorPartOrderInfo door_part_order[MAX_DOOR_PARTS];
59 struct DoorPartControlInfo
63 struct DoorPartPosInfo *pos;
66 static struct DoorPartControlInfo door_part_controls[] =
70 IMG_DOOR_1_GFX_PART_1,
75 IMG_DOOR_1_GFX_PART_2,
80 IMG_DOOR_1_GFX_PART_3,
85 IMG_DOOR_1_GFX_PART_4,
90 IMG_DOOR_1_GFX_PART_5,
95 IMG_DOOR_1_GFX_PART_6,
100 IMG_DOOR_1_GFX_PART_7,
105 IMG_DOOR_1_GFX_PART_8,
111 IMG_DOOR_2_GFX_PART_1,
116 IMG_DOOR_2_GFX_PART_2,
121 IMG_DOOR_2_GFX_PART_3,
126 IMG_DOOR_2_GFX_PART_4,
131 IMG_DOOR_2_GFX_PART_5,
136 IMG_DOOR_2_GFX_PART_6,
141 IMG_DOOR_2_GFX_PART_7,
146 IMG_DOOR_2_GFX_PART_8,
152 IMG_BACKGROUND_PANEL,
169 /* forward declaration for internal use */
170 static void UnmapToolButtons();
171 static void HandleToolButtons(struct GadgetInfo *);
172 static int el_act_dir2crm(int, int, int);
173 static int el_act2crm(int, int);
175 static struct GadgetInfo *tool_gadget[NUM_TOOL_BUTTONS];
176 static int request_gadget_id = -1;
178 static char *print_if_not_empty(int element)
180 static char *s = NULL;
181 char *token_name = element_info[element].token_name;
186 s = checked_malloc(strlen(token_name) + 10 + 1);
188 if (element != EL_EMPTY)
189 sprintf(s, "%d\t['%s']", element, token_name);
191 sprintf(s, "%d", element);
196 void DumpTile(int x, int y)
201 if (level.game_engine_type == GAME_ENGINE_TYPE_EM)
207 printf_line("-", 79);
208 printf("Field Info: SCREEN(%d, %d), LEVEL(%d, %d)\n", sx, sy, x, y);
209 printf_line("-", 79);
211 if (!IN_LEV_FIELD(x, y))
213 printf("(not in level field)\n");
219 printf(" Feld: %d\t['%s']\n", Feld[x][y],
220 element_info[Feld[x][y]].token_name);
221 printf(" Back: %s\n", print_if_not_empty(Back[x][y]));
222 printf(" Store: %s\n", print_if_not_empty(Store[x][y]));
223 printf(" Store2: %s\n", print_if_not_empty(Store2[x][y]));
224 printf(" StorePlayer: %s\n", print_if_not_empty(StorePlayer[x][y]));
225 printf(" MovPos: %d\n", MovPos[x][y]);
226 printf(" MovDir: %d\n", MovDir[x][y]);
227 printf(" MovDelay: %d\n", MovDelay[x][y]);
228 printf(" ChangeDelay: %d\n", ChangeDelay[x][y]);
229 printf(" CustomValue: %d\n", CustomValue[x][y]);
230 printf(" GfxElement: %d\n", GfxElement[x][y]);
231 printf(" GfxAction: %d\n", GfxAction[x][y]);
232 printf(" GfxFrame: %d\n", GfxFrame[x][y]);
236 void SetDrawtoField(int mode)
238 if (mode == DRAW_BUFFERED && setup.soft_scrolling)
246 BX2 = SCR_FIELDX + 1;
247 BY2 = SCR_FIELDY + 1;
266 BX2 = SCR_FIELDX + 1;
267 BY2 = SCR_FIELDY + 1;
282 drawto_field = fieldbuffer;
284 else /* DRAW_BACKBUFFER */
290 BX2 = SCR_FIELDX - 1;
291 BY2 = SCR_FIELDY - 1;
295 drawto_field = backbuffer;
299 void RedrawPlayfield(boolean force_redraw, int x, int y, int width, int height)
301 if (game_status == GAME_MODE_PLAYING &&
302 level.game_engine_type == GAME_ENGINE_TYPE_EM)
304 /* currently there is no partial redraw -- always redraw whole playfield */
305 RedrawPlayfield_EM(TRUE);
307 /* blit playfield from scroll buffer to normal back buffer for fading in */
308 BlitScreenToBitmap_EM(backbuffer);
310 else if (game_status == GAME_MODE_PLAYING &&
311 level.game_engine_type == GAME_ENGINE_TYPE_SP)
313 /* currently there is no partial redraw -- always redraw whole playfield */
314 RedrawPlayfield_SP(TRUE);
316 /* blit playfield from scroll buffer to normal back buffer for fading in */
317 BlitScreenToBitmap_SP(backbuffer);
319 else if (game_status == GAME_MODE_PLAYING &&
320 !game.envelope_active)
326 width = gfx.sxsize + 2 * TILEX;
327 height = gfx.sysize + 2 * TILEY;
333 int x1 = (x - SX) / TILEX, y1 = (y - SY) / TILEY;
334 int x2 = (x - SX + width) / TILEX, y2 = (y - SY + height) / TILEY;
336 for (xx = BX1; xx <= BX2; xx++)
337 for (yy = BY1; yy <= BY2; yy++)
338 if (xx >= x1 && xx <= x2 && yy >= y1 && yy <= y2)
339 DrawScreenField(xx, yy);
343 if (setup.soft_scrolling)
345 int fx = FX, fy = FY;
347 fx += (ScreenMovDir & (MV_LEFT|MV_RIGHT) ? ScreenGfxPos : 0);
348 fy += (ScreenMovDir & (MV_UP|MV_DOWN) ? ScreenGfxPos : 0);
350 BlitBitmap(fieldbuffer, backbuffer, fx,fy, SXSIZE,SYSIZE, SX,SY);
362 BlitBitmap(drawto, window, x, y, width, height, x, y);
365 void DrawMaskedBorder_Rect(int x, int y, int width, int height)
367 Bitmap *bitmap = graphic_info[IMG_GLOBAL_BORDER].bitmap;
369 SetClipOrigin(bitmap, bitmap->stored_clip_gc, 0, 0);
370 BlitBitmapMasked(bitmap, backbuffer, x, y, width, height, x, y);
373 void DrawMaskedBorder_FIELD()
375 if (global.border_status >= GAME_MODE_TITLE &&
376 global.border_status <= GAME_MODE_PLAYING &&
377 border.draw_masked[global.border_status])
378 DrawMaskedBorder_Rect(REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE);
381 void DrawMaskedBorder_DOOR_1()
383 if (border.draw_masked[GFX_SPECIAL_ARG_DOOR] &&
384 (global.border_status != GAME_MODE_EDITOR ||
385 border.draw_masked[GFX_SPECIAL_ARG_EDITOR]))
386 DrawMaskedBorder_Rect(DX, DY, DXSIZE, DYSIZE);
389 void DrawMaskedBorder_DOOR_2()
391 if (border.draw_masked[GFX_SPECIAL_ARG_DOOR] &&
392 global.border_status != GAME_MODE_EDITOR)
393 DrawMaskedBorder_Rect(VX, VY, VXSIZE, VYSIZE);
396 void DrawMaskedBorder_DOOR_3()
398 /* currently not available */
401 void DrawMaskedBorder_ALL()
403 DrawMaskedBorder_FIELD();
404 DrawMaskedBorder_DOOR_1();
405 DrawMaskedBorder_DOOR_2();
406 DrawMaskedBorder_DOOR_3();
409 void DrawMaskedBorder(int redraw_mask)
411 /* never draw masked screen borders on borderless screens */
412 if (effectiveGameStatus() == GAME_MODE_LOADING ||
413 effectiveGameStatus() == GAME_MODE_TITLE)
416 /* never draw masked screen borders when displaying request outside door */
417 if (effectiveGameStatus() == GAME_MODE_PSEUDO_DOOR &&
418 global.use_envelope_request)
421 if (redraw_mask & REDRAW_ALL)
422 DrawMaskedBorder_ALL();
425 if (redraw_mask & REDRAW_FIELD)
426 DrawMaskedBorder_FIELD();
427 if (redraw_mask & REDRAW_DOOR_1)
428 DrawMaskedBorder_DOOR_1();
429 if (redraw_mask & REDRAW_DOOR_2)
430 DrawMaskedBorder_DOOR_2();
431 if (redraw_mask & REDRAW_DOOR_3)
432 DrawMaskedBorder_DOOR_3();
436 void BlitScreenToBitmap(Bitmap *target_bitmap)
438 DrawBuffer *buffer = (drawto_field == window ? backbuffer : drawto_field);
439 int fx = FX, fy = FY;
442 int dx = (ScreenMovDir & (MV_LEFT | MV_RIGHT) ? ScreenGfxPos : 0);
443 int dy = (ScreenMovDir & (MV_UP | MV_DOWN) ? ScreenGfxPos : 0);
444 int dx_var = dx * TILESIZE_VAR / TILESIZE;
445 int dy_var = dy * TILESIZE_VAR / TILESIZE;
448 // fx += dx * TILESIZE_VAR / TILESIZE;
449 // fy += dy * TILESIZE_VAR / TILESIZE;
451 fx += (ScreenMovDir & (MV_LEFT | MV_RIGHT) ? ScreenGfxPos : 0);
452 fy += (ScreenMovDir & (MV_UP | MV_DOWN) ? ScreenGfxPos : 0);
455 ffx = (scroll_x - SBX_Left) * TILEX_VAR + dx_var;
456 ffy = (scroll_y - SBY_Upper) * TILEY_VAR + dy_var;
458 if (EVEN(SCR_FIELDX))
460 if (ffx < SBX_Right * TILEX_VAR + TILEX_VAR / 2 + TILEX_VAR)
461 fx += dx_var - MIN(ffx, TILEX_VAR / 2) + TILEX_VAR;
463 fx += (dx_var > 0 ? TILEX_VAR : 0);
470 if (EVEN(SCR_FIELDY))
472 if (ffy < SBY_Lower * TILEY_VAR + TILEY_VAR / 2 + TILEY_VAR)
473 fy += dy_var - MIN(ffy, TILEY_VAR / 2) + TILEY_VAR;
475 fy += (dy_var > 0 ? TILEY_VAR : 0);
483 printf("::: (%d, %d) [(%d / %d, %d / %d)] => %d, %d\n",
486 SBY_Upper, SBY_Lower,
490 if (border.draw_masked[GAME_MODE_PLAYING])
492 if (buffer != backbuffer)
494 /* copy playfield buffer to backbuffer to add masked border */
495 BlitBitmap(buffer, backbuffer, fx, fy, SXSIZE, SYSIZE, SX, SY);
496 DrawMaskedBorder(REDRAW_FIELD);
499 BlitBitmap(backbuffer, target_bitmap,
500 REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE,
505 BlitBitmap(buffer, target_bitmap, fx, fy, SXSIZE, SYSIZE, SX, SY);
512 DrawBuffer *buffer = (drawto_field == window ? backbuffer : drawto_field);
515 printf("::: TILES TO REFRESH: %d\n", redraw_tiles);
516 for (x = 0; x < SCR_FIELDX; x++)
517 for (y = 0 ; y < SCR_FIELDY; y++)
518 if (redraw[redraw_x1 + x][redraw_y1 + y])
519 printf("::: - %d, %d [%s]\n",
520 LEVELX(x), LEVELY(y),
521 EL_NAME(Feld[LEVELX(x)][LEVELY(y)]));
524 if (redraw_mask & REDRAW_TILES && redraw_tiles > REDRAWTILES_THRESHOLD)
525 redraw_mask |= REDRAW_FIELD;
528 // never redraw single tiles, always redraw the whole field
529 // (redrawing single tiles up to a certain threshold was faster on old,
530 // now legacy graphics, but slows things down on modern graphics now)
531 // UPDATE: this is now globally defined by value of REDRAWTILES_THRESHOLD
532 if (redraw_mask & REDRAW_TILES)
533 redraw_mask |= REDRAW_FIELD;
537 /* !!! TEST ONLY !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */
538 /* (force full redraw) */
539 if (game_status == GAME_MODE_PLAYING)
540 redraw_mask |= REDRAW_FIELD;
543 if (redraw_mask & REDRAW_FIELD)
544 redraw_mask &= ~REDRAW_TILES;
546 if (redraw_mask == REDRAW_NONE)
551 if (redraw_mask & REDRAW_ALL)
552 printf("[REDRAW_ALL]");
553 if (redraw_mask & REDRAW_FIELD)
554 printf("[REDRAW_FIELD]");
555 if (redraw_mask & REDRAW_TILES)
556 printf("[REDRAW_TILES]");
557 if (redraw_mask & REDRAW_DOOR_1)
558 printf("[REDRAW_DOOR_1]");
559 if (redraw_mask & REDRAW_DOOR_2)
560 printf("[REDRAW_DOOR_2]");
561 if (redraw_mask & REDRAW_FROM_BACKBUFFER)
562 printf("[REDRAW_FROM_BACKBUFFER]");
563 printf(" [%d]\n", FrameCounter);
566 if (redraw_mask & REDRAW_TILES &&
567 game_status == GAME_MODE_PLAYING &&
568 border.draw_masked[GAME_MODE_PLAYING])
569 redraw_mask |= REDRAW_FIELD;
571 if (global.fps_slowdown && game_status == GAME_MODE_PLAYING)
573 static boolean last_frame_skipped = FALSE;
574 boolean skip_even_when_not_scrolling = TRUE;
575 boolean just_scrolling = (ScreenMovDir != 0);
576 boolean verbose = FALSE;
578 if (global.fps_slowdown_factor > 1 &&
579 (FrameCounter % global.fps_slowdown_factor) &&
580 (just_scrolling || skip_even_when_not_scrolling))
582 redraw_mask &= ~REDRAW_MAIN;
584 last_frame_skipped = TRUE;
587 printf("FRAME SKIPPED\n");
591 if (last_frame_skipped)
592 redraw_mask |= REDRAW_FIELD;
594 last_frame_skipped = FALSE;
597 printf("frame not skipped\n");
601 /* synchronize X11 graphics at this point; if we would synchronize the
602 display immediately after the buffer switching (after the XFlush),
603 this could mean that we have to wait for the graphics to complete,
604 although we could go on doing calculations for the next frame */
608 /* never draw masked border to backbuffer when using playfield buffer */
609 if (game_status != GAME_MODE_PLAYING ||
610 redraw_mask & REDRAW_FROM_BACKBUFFER ||
611 buffer == backbuffer)
612 DrawMaskedBorder(redraw_mask);
614 DrawMaskedBorder(redraw_mask & REDRAW_DOORS);
616 if (redraw_mask & REDRAW_ALL)
618 BlitBitmap(backbuffer, window, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
620 redraw_mask = REDRAW_NONE;
623 if (redraw_mask & REDRAW_FIELD)
626 printf("::: REDRAW_FIELD\n");
629 if (game_status != GAME_MODE_PLAYING ||
630 redraw_mask & REDRAW_FROM_BACKBUFFER)
632 BlitBitmap(backbuffer, window,
633 REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE, REAL_SX, REAL_SY);
638 BlitScreenToBitmap(window);
640 int fx = FX, fy = FY;
643 int dx = (ScreenMovDir & (MV_LEFT | MV_RIGHT) ? ScreenGfxPos : 0);
644 int dy = (ScreenMovDir & (MV_UP | MV_DOWN) ? ScreenGfxPos : 0);
645 int dx_var = dx * TILESIZE_VAR / TILESIZE;
646 int dy_var = dy * TILESIZE_VAR / TILESIZE;
649 // fx += dx * TILESIZE_VAR / TILESIZE;
650 // fy += dy * TILESIZE_VAR / TILESIZE;
652 fx += (ScreenMovDir & (MV_LEFT | MV_RIGHT) ? ScreenGfxPos : 0);
653 fy += (ScreenMovDir & (MV_UP | MV_DOWN) ? ScreenGfxPos : 0);
656 /* !!! THIS WORKS !!! */
658 printf("::: %d, %d\n", scroll_x, scroll_y);
660 ffx = (scroll_x - SBX_Left) * TILEX_VAR + dx_var;
661 ffy = (scroll_y - SBY_Upper) * TILEY_VAR + dy_var;
663 if (EVEN(SCR_FIELDX))
665 if (ffx < SBX_Right * TILEX_VAR + TILEX_VAR / 2 + TILEX_VAR)
666 fx += dx_var - MIN(ffx, TILEX_VAR / 2) + TILEX_VAR;
668 fx += (dx > 0 ? TILEX_VAR : 0);
675 if (EVEN(SCR_FIELDY))
677 if (ffy < SBY_Lower * TILEY_VAR + TILEY_VAR / 2 + TILEY_VAR)
678 fy += dy_var - MIN(ffy, TILEY_VAR / 2) + TILEY_VAR;
680 fy += (dy > 0 ? TILEY_VAR : 0);
687 if (border.draw_masked[GAME_MODE_PLAYING])
689 if (buffer != backbuffer)
691 /* copy playfield buffer to backbuffer to add masked border */
692 BlitBitmap(buffer, backbuffer, fx, fy, SXSIZE, SYSIZE, SX, SY);
693 DrawMaskedBorder(REDRAW_FIELD);
696 BlitBitmap(backbuffer, window,
697 REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE,
702 BlitBitmap(buffer, window, fx, fy, SXSIZE, SYSIZE, SX, SY);
708 printf("redrawing all (ScreenGfxPos == %d) because %s\n",
710 (setup.soft_scrolling ?
711 "setup.soft_scrolling" :
712 ABS(ScreenGfxPos) + ScrollStepSize == TILEX ?
713 "ABS(ScreenGfxPos) + ScrollStepSize == TILEX" :
714 ABS(ScreenGfxPos) == ScrollStepSize ?
715 "ABS(ScreenGfxPos) == ScrollStepSize" :
716 "redraw_tiles > REDRAWTILES_THRESHOLD"));
721 redraw_mask &= ~REDRAW_MAIN;
724 if (redraw_mask & REDRAW_DOORS)
726 if (redraw_mask & REDRAW_DOOR_1)
727 BlitBitmap(backbuffer, window, DX, DY, DXSIZE, DYSIZE, DX, DY);
729 if (redraw_mask & REDRAW_DOOR_2)
730 BlitBitmap(backbuffer, window, VX, VY, VXSIZE, VYSIZE, VX, VY);
732 if (redraw_mask & REDRAW_DOOR_3)
733 BlitBitmap(backbuffer, window, EX, EY, EXSIZE, EYSIZE, EX, EY);
735 redraw_mask &= ~REDRAW_DOORS;
738 if (redraw_mask & REDRAW_MICROLEVEL)
740 BlitBitmap(backbuffer, window, SX, SY + 10 * TILEY, SXSIZE, 7 * TILEY,
741 SX, SY + 10 * TILEY);
743 redraw_mask &= ~REDRAW_MICROLEVEL;
746 if (redraw_mask & REDRAW_TILES)
749 printf("::: REDRAW_TILES\n");
755 InitGfxClipRegion(TRUE, SX, SY, SXSIZE, SYSIZE);
758 int sx = SX; // - (EVEN(SCR_FIELDX) ? TILEX_VAR / 2 : 0);
759 int sy = SY; // + (EVEN(SCR_FIELDY) ? TILEY_VAR / 2 : 0);
762 int dx_var = dx * TILESIZE_VAR / TILESIZE;
763 int dy_var = dy * TILESIZE_VAR / TILESIZE;
765 int fx = FX, fy = FY;
767 int scr_fieldx = SCR_FIELDX + (EVEN(SCR_FIELDX) ? 2 : 0);
768 int scr_fieldy = SCR_FIELDY + (EVEN(SCR_FIELDY) ? 2 : 0);
770 ffx = (scroll_x - SBX_Left) * TILEX_VAR + dx_var;
771 ffy = (scroll_y - SBY_Upper) * TILEY_VAR + dy_var;
773 if (EVEN(SCR_FIELDX))
775 if (ffx < SBX_Right * TILEX_VAR + TILEX_VAR / 2 + TILEX_VAR)
777 fx += dx_var - MIN(ffx, TILEX_VAR / 2) + TILEX_VAR;
786 fx += (dx_var > 0 ? TILEX_VAR : 0);
790 if (EVEN(SCR_FIELDY))
792 if (ffy < SBY_Lower * TILEY_VAR + TILEY_VAR / 2 + TILEY_VAR)
794 fy += dy_var - MIN(ffy, TILEY_VAR / 2) + TILEY_VAR;
803 fy += (dy_var > 0 ? TILEY_VAR : 0);
808 printf("::: %d, %d, %d, %d\n", sx, sy, SCR_FIELDX, SCR_FIELDY);
811 for (x = 0; x < scr_fieldx; x++)
812 for (y = 0 ; y < scr_fieldy; y++)
813 if (redraw[redraw_x1 + x][redraw_y1 + y])
814 BlitBitmap(buffer, window,
815 FX + x * TILEX_VAR, FY + y * TILEY_VAR,
816 TILEX_VAR, TILEY_VAR,
817 sx + x * TILEX_VAR, sy + y * TILEY_VAR);
820 InitGfxClipRegion(FALSE, -1, -1, -1, -1);
822 for (x = 0; x < SCR_FIELDX; x++)
823 for (y = 0 ; y < SCR_FIELDY; y++)
824 if (redraw[redraw_x1 + x][redraw_y1 + y])
825 BlitBitmap(buffer, window,
826 FX + x * TILEX_VAR, FY + y * TILEY_VAR,
827 TILEX_VAR, TILEY_VAR,
828 SX + x * TILEX_VAR, SY + y * TILEY_VAR);
832 for (x = 0; x < SCR_FIELDX; x++)
833 for (y = 0 ; y < SCR_FIELDY; y++)
834 if (redraw[redraw_x1 + x][redraw_y1 + y])
835 BlitBitmap(buffer, window,
836 FX + x * TILEX, FY + y * TILEY, TILEX, TILEY,
837 SX + x * TILEX, SY + y * TILEY);
841 if (redraw_mask & REDRAW_FPS) /* display frames per second */
846 sprintf(info1, " (only every %d. frame)", global.fps_slowdown_factor);
847 if (!global.fps_slowdown)
850 sprintf(text, "%04.1f fps%s", global.frames_per_second, info1);
852 DrawTextExt(window, SX + SXSIZE + SX, 0, text, FONT_TEXT_2, BLIT_OPAQUE);
854 DrawTextExt(window, SX, SY, text, FONT_TEXT_2, BLIT_OPAQUE);
860 for (x = 0; x < MAX_BUF_XSIZE; x++)
861 for (y = 0; y < MAX_BUF_YSIZE; y++)
864 redraw_mask = REDRAW_NONE;
867 static void FadeCrossSaveBackbuffer()
869 BlitBitmap(backbuffer, bitmap_db_cross, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
872 static void FadeExt(int fade_mask, int fade_mode, int fade_type)
874 static int fade_type_skip = FADE_TYPE_NONE;
875 void (*draw_border_function)(void) = NULL;
876 Bitmap *bitmap = (fade_mode & FADE_TYPE_TRANSFORM ? bitmap_db_cross : NULL);
877 int x, y, width, height;
878 int fade_delay, post_delay;
880 if (fade_type == FADE_TYPE_FADE_OUT)
882 if (fade_type_skip != FADE_TYPE_NONE)
885 printf("::: skipping %d ... [%d] (X)\n", fade_mode, fade_type_skip);
888 /* skip all fade operations until specified fade operation */
889 if (fade_type & fade_type_skip)
890 fade_type_skip = FADE_TYPE_NONE;
895 if (fading.fade_mode & FADE_TYPE_TRANSFORM)
897 FadeCrossSaveBackbuffer();
903 redraw_mask |= fade_mask;
905 if (fade_type == FADE_TYPE_SKIP)
908 printf("::: will skip %d ... [%d]\n", fade_mode, fade_type_skip);
911 fade_type_skip = fade_mode;
917 printf("::: !!! FADING %d ... [%d] [%d]\n", fade_mode, fade_type,
922 fade_delay = fading.fade_delay;
923 post_delay = (fade_mode == FADE_MODE_FADE_OUT ? fading.post_delay : 0);
926 if (fade_type_skip != FADE_TYPE_NONE)
929 printf("::: skipping %d ... [%d]\n", fade_mode, fade_type_skip);
932 /* skip all fade operations until specified fade operation */
933 if (fade_type & fade_type_skip)
934 fade_type_skip = FADE_TYPE_NONE;
944 if (global.autoplay_leveldir)
946 // fading.fade_mode = FADE_MODE_NONE;
953 if (fading.fade_mode == FADE_MODE_NONE)
961 /* !!! what about fade_mask == REDRAW_FIELD | REDRAW_ALL ??? !!! */
964 printf("::: NOW FADING %d ... [%d]\n", fade_mode, fade_type);
968 if (fade_mask == REDRAW_NONE)
969 fade_mask = REDRAW_FIELD;
972 // if (fade_mask & REDRAW_FIELD)
973 if (fade_mask == REDRAW_FIELD)
978 height = FULL_SYSIZE;
981 fade_delay = fading.fade_delay;
982 post_delay = (fade_mode == FADE_MODE_FADE_OUT ? fading.post_delay : 0);
985 if (border.draw_masked_when_fading)
986 draw_border_function = DrawMaskedBorder_FIELD; /* update when fading */
988 DrawMaskedBorder_FIELD(); /* draw once */
990 else /* REDRAW_ALL */
998 fade_delay = fading.fade_delay;
999 post_delay = (fade_mode == FADE_MODE_FADE_OUT ? fading.post_delay : 0);
1004 if (!setup.fade_screens ||
1006 fading.fade_mode == FADE_MODE_NONE)
1008 if (!setup.fade_screens || fade_delay == 0)
1011 if (fade_mode == FADE_MODE_FADE_OUT)
1015 if (fade_mode == FADE_MODE_FADE_OUT &&
1016 fading.fade_mode != FADE_MODE_NONE)
1017 ClearRectangle(backbuffer, x, y, width, height);
1021 BlitBitmap(backbuffer, window, x, y, width, height, x, y);
1022 redraw_mask = REDRAW_NONE;
1030 FadeRectangle(bitmap, x, y, width, height, fade_mode, fade_delay, post_delay,
1031 draw_border_function);
1033 redraw_mask &= ~fade_mask;
1036 void FadeIn(int fade_mask)
1038 if (fading.fade_mode & FADE_TYPE_TRANSFORM)
1039 FadeExt(fade_mask, fading.fade_mode, FADE_TYPE_FADE_IN);
1041 FadeExt(fade_mask, FADE_MODE_FADE_IN, FADE_TYPE_FADE_IN);
1044 void FadeOut(int fade_mask)
1046 if (fading.fade_mode & FADE_TYPE_TRANSFORM)
1047 FadeExt(fade_mask, fading.fade_mode, FADE_TYPE_FADE_OUT);
1049 FadeExt(fade_mask, FADE_MODE_FADE_OUT, FADE_TYPE_FADE_OUT);
1051 global.border_status = game_status;
1054 static void FadeSetLeaveNext(struct TitleFadingInfo fading_leave, boolean set)
1056 static struct TitleFadingInfo fading_leave_stored;
1059 fading_leave_stored = fading_leave;
1061 fading = fading_leave_stored;
1064 void FadeSetEnterMenu()
1066 fading = menu.enter_menu;
1069 printf("::: storing enter_menu\n");
1072 FadeSetLeaveNext(fading, TRUE); /* (keep same fade mode) */
1075 void FadeSetLeaveMenu()
1077 fading = menu.leave_menu;
1080 printf("::: storing leave_menu\n");
1083 FadeSetLeaveNext(fading, TRUE); /* (keep same fade mode) */
1086 void FadeSetEnterScreen()
1088 fading = menu.enter_screen[game_status];
1091 printf("::: storing leave_screen[%d]\n", game_status);
1094 FadeSetLeaveNext(menu.leave_screen[game_status], TRUE); /* store */
1097 void FadeSetNextScreen()
1099 fading = menu.next_screen;
1102 printf("::: storing next_screen\n");
1105 // (do not overwrite fade mode set by FadeSetEnterScreen)
1106 // FadeSetLeaveNext(fading, TRUE); /* (keep same fade mode) */
1109 void FadeSetLeaveScreen()
1112 printf("::: recalling last stored value\n");
1115 FadeSetLeaveNext(menu.leave_screen[game_status], FALSE); /* recall */
1118 void FadeSetFromType(int type)
1120 if (type & TYPE_ENTER_SCREEN)
1121 FadeSetEnterScreen();
1122 else if (type & TYPE_ENTER)
1124 else if (type & TYPE_LEAVE)
1128 void FadeSetDisabled()
1130 static struct TitleFadingInfo fading_none = { FADE_MODE_NONE, -1, -1, -1 };
1132 fading = fading_none;
1135 void FadeSkipNextFadeIn()
1137 FadeExt(0, FADE_MODE_SKIP_FADE_IN, FADE_TYPE_SKIP);
1140 void FadeSkipNextFadeOut()
1142 FadeExt(0, FADE_MODE_SKIP_FADE_OUT, FADE_TYPE_SKIP);
1145 void SetWindowBackgroundImageIfDefined(int graphic)
1147 if (graphic_info[graphic].bitmap)
1148 SetWindowBackgroundBitmap(graphic_info[graphic].bitmap);
1151 void SetMainBackgroundImageIfDefined(int graphic)
1153 if (graphic_info[graphic].bitmap)
1154 SetMainBackgroundBitmap(graphic_info[graphic].bitmap);
1157 void SetDoorBackgroundImageIfDefined(int graphic)
1159 if (graphic_info[graphic].bitmap)
1160 SetDoorBackgroundBitmap(graphic_info[graphic].bitmap);
1163 void SetWindowBackgroundImage(int graphic)
1165 SetWindowBackgroundBitmap(graphic == IMG_UNDEFINED ? NULL :
1166 graphic_info[graphic].bitmap ?
1167 graphic_info[graphic].bitmap :
1168 graphic_info[IMG_BACKGROUND].bitmap);
1171 void SetMainBackgroundImage(int graphic)
1173 SetMainBackgroundBitmap(graphic == IMG_UNDEFINED ? NULL :
1174 graphic_info[graphic].bitmap ?
1175 graphic_info[graphic].bitmap :
1176 graphic_info[IMG_BACKGROUND].bitmap);
1179 void SetDoorBackgroundImage(int graphic)
1181 SetDoorBackgroundBitmap(graphic == IMG_UNDEFINED ? NULL :
1182 graphic_info[graphic].bitmap ?
1183 graphic_info[graphic].bitmap :
1184 graphic_info[IMG_BACKGROUND].bitmap);
1187 void SetPanelBackground()
1190 struct GraphicInfo *gfx = &graphic_info[IMG_BACKGROUND_PANEL];
1193 BlitBitmapTiled(gfx->bitmap, bitmap_db_panel, gfx->src_x, gfx->src_y,
1194 gfx->width, gfx->height, 0, 0, DXSIZE, DYSIZE);
1196 /* (ClearRectangle() only needed if panel bitmap is smaller than panel) */
1197 ClearRectangle(bitmap_db_panel, DX, DY, DXSIZE, DYSIZE);
1198 BlitBitmap(gfx->bitmap, bitmap_db_panel, gfx->src_x, gfx->src_y,
1199 MIN(gfx->width, DXSIZE), MIN(gfx->height, DYSIZE), 0, 0);
1202 BlitBitmap(graphic_info[IMG_GLOBAL_DOOR].bitmap, bitmap_db_panel,
1203 DOOR_GFX_PAGEX5, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE, 0, 0);
1206 SetDoorBackgroundBitmap(bitmap_db_panel);
1209 void DrawBackground(int x, int y, int width, int height)
1211 /* !!! "drawto" might still point to playfield buffer here (see below) !!! */
1212 /* (when entering hall of fame after playing) */
1214 ClearRectangleOnBackground(drawto, x, y, width, height);
1216 ClearRectangleOnBackground(backbuffer, x, y, width, height);
1222 if (IN_GFX_FIELD_FULL(x, y))
1223 redraw_mask |= REDRAW_FIELD;
1224 else if (IN_GFX_DOOR_1(x, y))
1225 redraw_mask |= REDRAW_DOOR_1;
1226 else if (IN_GFX_DOOR_2(x, y))
1227 redraw_mask |= REDRAW_DOOR_2;
1228 else if (IN_GFX_DOOR_3(x, y))
1229 redraw_mask |= REDRAW_DOOR_3;
1231 /* (this only works for the current arrangement of playfield and panels) */
1233 redraw_mask |= REDRAW_FIELD;
1234 else if (y < gfx.vy)
1235 redraw_mask |= REDRAW_DOOR_1;
1237 redraw_mask |= REDRAW_DOOR_2;
1241 /* (this is just wrong (when drawing to one of the two door panel areas)) */
1242 redraw_mask |= REDRAW_FIELD;
1246 void DrawBackgroundForFont(int x, int y, int width, int height, int font_nr)
1248 struct FontBitmapInfo *font = getFontBitmapInfo(font_nr);
1250 if (font->bitmap == NULL)
1253 DrawBackground(x, y, width, height);
1256 void DrawBackgroundForGraphic(int x, int y, int width, int height, int graphic)
1258 struct GraphicInfo *g = &graphic_info[graphic];
1260 if (g->bitmap == NULL)
1263 DrawBackground(x, y, width, height);
1268 /* !!! "drawto" might still point to playfield buffer here (see above) !!! */
1269 /* (when entering hall of fame after playing) */
1270 DrawBackground(REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE);
1272 /* !!! maybe this should be done before clearing the background !!! */
1273 if (setup.soft_scrolling && game_status == GAME_MODE_PLAYING)
1275 ClearRectangle(fieldbuffer, 0, 0, FXSIZE, FYSIZE);
1276 SetDrawtoField(DRAW_BUFFERED);
1279 SetDrawtoField(DRAW_BACKBUFFER);
1282 void MarkTileDirty(int x, int y)
1284 int xx = redraw_x1 + x;
1285 int yy = redraw_y1 + y;
1287 if (!redraw[xx][yy])
1290 redraw[xx][yy] = TRUE;
1291 redraw_mask |= REDRAW_TILES;
1294 void SetBorderElement()
1298 BorderElement = EL_EMPTY;
1300 for (y = 0; y < lev_fieldy && BorderElement == EL_EMPTY; y++)
1302 for (x = 0; x < lev_fieldx; x++)
1304 if (!IS_INDESTRUCTIBLE(Feld[x][y]))
1305 BorderElement = EL_STEELWALL;
1307 if (y != 0 && y != lev_fieldy - 1 && x != lev_fieldx - 1)
1313 void FloodFillLevel(int from_x, int from_y, int fill_element,
1314 short field[MAX_LEV_FIELDX][MAX_LEV_FIELDY],
1315 int max_fieldx, int max_fieldy)
1319 static int check[4][2] = { { -1, 0 }, { 0, -1 }, { 1, 0 }, { 0, 1 } };
1320 static int safety = 0;
1322 /* check if starting field still has the desired content */
1323 if (field[from_x][from_y] == fill_element)
1328 if (safety > max_fieldx * max_fieldy)
1329 Error(ERR_EXIT, "Something went wrong in 'FloodFill()'. Please debug.");
1331 old_element = field[from_x][from_y];
1332 field[from_x][from_y] = fill_element;
1334 for (i = 0; i < 4; i++)
1336 x = from_x + check[i][0];
1337 y = from_y + check[i][1];
1339 if (IN_FIELD(x, y, max_fieldx, max_fieldy) && field[x][y] == old_element)
1340 FloodFillLevel(x, y, fill_element, field, max_fieldx, max_fieldy);
1346 void SetRandomAnimationValue(int x, int y)
1348 gfx.anim_random_frame = GfxRandom[x][y];
1351 inline int getGraphicAnimationFrame(int graphic, int sync_frame)
1353 /* animation synchronized with global frame counter, not move position */
1354 if (graphic_info[graphic].anim_global_sync || sync_frame < 0)
1355 sync_frame = FrameCounter;
1357 return getAnimationFrame(graphic_info[graphic].anim_frames,
1358 graphic_info[graphic].anim_delay,
1359 graphic_info[graphic].anim_mode,
1360 graphic_info[graphic].anim_start_frame,
1364 void getSizedGraphicSourceExt(int graphic, int frame, int tilesize_raw,
1365 Bitmap **bitmap, int *x, int *y,
1366 boolean get_backside)
1370 int width_mult, width_div;
1371 int height_mult, height_div;
1375 { 15, 16, 2, 3 }, /* 1 x 1 */
1376 { 7, 8, 2, 3 }, /* 2 x 2 */
1377 { 3, 4, 2, 3 }, /* 4 x 4 */
1378 { 1, 2, 2, 3 }, /* 8 x 8 */
1379 { 0, 1, 2, 3 }, /* 16 x 16 */
1380 { 0, 1, 0, 1 }, /* 32 x 32 */
1382 struct GraphicInfo *g = &graphic_info[graphic];
1383 Bitmap *src_bitmap = g->bitmap;
1384 int tilesize = MIN(MAX(1, tilesize_raw), TILESIZE);
1385 int offset_calc_pos = log_2(tilesize);
1386 int width_mult = offset_calc[offset_calc_pos].width_mult;
1387 int width_div = offset_calc[offset_calc_pos].width_div;
1388 int height_mult = offset_calc[offset_calc_pos].height_mult;
1389 int height_div = offset_calc[offset_calc_pos].height_div;
1390 int startx = src_bitmap->width * width_mult / width_div;
1391 int starty = src_bitmap->height * height_mult / height_div;
1393 int src_x = (g->src_x + (get_backside ? g->offset2_x : 0)) *
1394 tilesize / TILESIZE;
1395 int src_y = (g->src_y + (get_backside ? g->offset2_y : 0)) *
1396 tilesize / TILESIZE;
1398 int src_x = g->src_x * tilesize / TILESIZE;
1399 int src_y = g->src_y * tilesize / TILESIZE;
1401 int width = g->width * tilesize / TILESIZE;
1402 int height = g->height * tilesize / TILESIZE;
1403 int offset_x = g->offset_x * tilesize / TILESIZE;
1404 int offset_y = g->offset_y * tilesize / TILESIZE;
1406 if (g->offset_y == 0) /* frames are ordered horizontally */
1408 int max_width = g->anim_frames_per_line * width;
1409 int pos = (src_y / height) * max_width + src_x + frame * offset_x;
1411 src_x = pos % max_width;
1412 src_y = src_y % height + pos / max_width * height;
1414 else if (g->offset_x == 0) /* frames are ordered vertically */
1416 int max_height = g->anim_frames_per_line * height;
1417 int pos = (src_x / width) * max_height + src_y + frame * offset_y;
1419 src_x = src_x % width + pos / max_height * width;
1420 src_y = pos % max_height;
1422 else /* frames are ordered diagonally */
1424 src_x = src_x + frame * offset_x;
1425 src_y = src_y + frame * offset_y;
1428 *bitmap = src_bitmap;
1429 *x = startx + src_x;
1430 *y = starty + src_y;
1433 void getFixedGraphicSourceExt(int graphic, int frame, Bitmap **bitmap,
1434 int *x, int *y, boolean get_backside)
1436 getSizedGraphicSourceExt(graphic, frame, TILESIZE, bitmap, x, y,
1440 void getSizedGraphicSource(int graphic, int frame, int tilesize_raw,
1441 Bitmap **bitmap, int *x, int *y)
1443 getSizedGraphicSourceExt(graphic, frame, tilesize_raw, bitmap, x, y, FALSE);
1446 void getFixedGraphicSource(int graphic, int frame,
1447 Bitmap **bitmap, int *x, int *y)
1449 getSizedGraphicSourceExt(graphic, frame, TILESIZE, bitmap, x, y, FALSE);
1452 void getMiniGraphicSource(int graphic, Bitmap **bitmap, int *x, int *y)
1455 getSizedGraphicSource(graphic, 0, MINI_TILESIZE, bitmap, x, y);
1457 struct GraphicInfo *g = &graphic_info[graphic];
1458 int mini_startx = 0;
1459 int mini_starty = g->bitmap->height * 2 / 3;
1461 *bitmap = g->bitmap;
1462 *x = mini_startx + g->src_x / 2;
1463 *y = mini_starty + g->src_y / 2;
1467 inline void getGraphicSourceExt(int graphic, int frame, Bitmap **bitmap,
1468 int *x, int *y, boolean get_backside)
1470 struct GraphicInfo *g = &graphic_info[graphic];
1471 int src_x = g->src_x + (get_backside ? g->offset2_x : 0);
1472 int src_y = g->src_y + (get_backside ? g->offset2_y : 0);
1475 if (TILESIZE_VAR != TILESIZE)
1476 return getSizedGraphicSourceExt(graphic, frame, TILESIZE_VAR, bitmap, x, y,
1480 *bitmap = g->bitmap;
1482 if (g->offset_y == 0) /* frames are ordered horizontally */
1484 int max_width = g->anim_frames_per_line * g->width;
1485 int pos = (src_y / g->height) * max_width + src_x + frame * g->offset_x;
1487 *x = pos % max_width;
1488 *y = src_y % g->height + pos / max_width * g->height;
1490 else if (g->offset_x == 0) /* frames are ordered vertically */
1492 int max_height = g->anim_frames_per_line * g->height;
1493 int pos = (src_x / g->width) * max_height + src_y + frame * g->offset_y;
1495 *x = src_x % g->width + pos / max_height * g->width;
1496 *y = pos % max_height;
1498 else /* frames are ordered diagonally */
1500 *x = src_x + frame * g->offset_x;
1501 *y = src_y + frame * g->offset_y;
1505 void getGraphicSource(int graphic, int frame, Bitmap **bitmap, int *x, int *y)
1507 getGraphicSourceExt(graphic, frame, bitmap, x, y, FALSE);
1510 void DrawGraphic(int x, int y, int graphic, int frame)
1513 if (!IN_SCR_FIELD(x, y))
1515 printf("DrawGraphic(): x = %d, y = %d, graphic = %d\n", x, y, graphic);
1516 printf("DrawGraphic(): This should never happen!\n");
1522 DrawGraphicExt(drawto_field, FX + x * TILEX_VAR, FY + y * TILEY_VAR, graphic,
1525 DrawGraphicExt(drawto_field, FX + x * TILEX, FY + y * TILEY, graphic, frame);
1527 MarkTileDirty(x, y);
1530 void DrawFixedGraphic(int x, int y, int graphic, int frame)
1533 if (!IN_SCR_FIELD(x, y))
1535 printf("DrawGraphic(): x = %d, y = %d, graphic = %d\n", x, y, graphic);
1536 printf("DrawGraphic(): This should never happen!\n");
1541 DrawFixedGraphicExt(drawto_field, FX + x * TILEX, FY + y * TILEY, graphic,
1543 MarkTileDirty(x, y);
1546 void DrawGraphicExt(DrawBuffer *dst_bitmap, int x, int y, int graphic,
1552 getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
1554 BlitBitmap(src_bitmap, dst_bitmap, src_x, src_y, TILEX_VAR, TILEY_VAR, x, y);
1556 BlitBitmap(src_bitmap, dst_bitmap, src_x, src_y, TILEX, TILEY, x, y);
1560 void DrawFixedGraphicExt(DrawBuffer *dst_bitmap, int x, int y, int graphic,
1566 getFixedGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
1567 BlitBitmap(src_bitmap, dst_bitmap, src_x, src_y, TILEX, TILEY, x, y);
1570 void DrawGraphicThruMask(int x, int y, int graphic, int frame)
1573 if (!IN_SCR_FIELD(x, y))
1575 printf("DrawGraphicThruMask(): x = %d,y = %d, graphic = %d\n",x,y,graphic);
1576 printf("DrawGraphicThruMask(): This should never happen!\n");
1582 DrawGraphicThruMaskExt(drawto_field, FX + x * TILEX_VAR, FY + y * TILEY_VAR,
1585 DrawGraphicThruMaskExt(drawto_field, FX + x * TILEX, FY + y * TILEY, graphic,
1588 MarkTileDirty(x, y);
1591 void DrawFixedGraphicThruMask(int x, int y, int graphic, int frame)
1594 if (!IN_SCR_FIELD(x, y))
1596 printf("DrawGraphicThruMask(): x = %d,y = %d, graphic = %d\n",x,y,graphic);
1597 printf("DrawGraphicThruMask(): This should never happen!\n");
1602 DrawFixedGraphicThruMaskExt(drawto_field, FX + x * TILEX, FY + y * TILEY,
1604 MarkTileDirty(x, y);
1607 void DrawGraphicThruMaskExt(DrawBuffer *d, int dst_x, int dst_y, int graphic,
1613 getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
1615 SetClipOrigin(src_bitmap, src_bitmap->stored_clip_gc,
1616 dst_x - src_x, dst_y - src_y);
1618 BlitBitmapMasked(src_bitmap, d, src_x, src_y, TILEX_VAR, TILEY_VAR,
1621 BlitBitmapMasked(src_bitmap, d, src_x, src_y, TILEX, TILEY, dst_x, dst_y);
1625 void DrawFixedGraphicThruMaskExt(DrawBuffer *d, int dst_x, int dst_y,
1626 int graphic, int frame)
1631 getFixedGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
1633 SetClipOrigin(src_bitmap, src_bitmap->stored_clip_gc,
1634 dst_x - src_x, dst_y - src_y);
1635 BlitBitmapMasked(src_bitmap, d, src_x, src_y, TILEX, TILEY, dst_x, dst_y);
1638 void DrawSizedGraphic(int x, int y, int graphic, int frame, int tilesize)
1640 DrawSizedGraphicExt(drawto, SX + x * tilesize, SY + y * tilesize, graphic,
1642 MarkTileDirty(x / tilesize, y / tilesize);
1645 void DrawSizedGraphicExt(DrawBuffer *d, int x, int y, int graphic, int frame,
1651 getSizedGraphicSource(graphic, frame, tilesize, &src_bitmap, &src_x, &src_y);
1652 BlitBitmap(src_bitmap, d, src_x, src_y, tilesize, tilesize, x, y);
1655 void DrawMiniGraphic(int x, int y, int graphic)
1657 DrawMiniGraphicExt(drawto, SX + x * MINI_TILEX,SY + y * MINI_TILEY, graphic);
1658 MarkTileDirty(x / 2, y / 2);
1661 void DrawMiniGraphicExt(DrawBuffer *d, int x, int y, int graphic)
1666 getMiniGraphicSource(graphic, &src_bitmap, &src_x, &src_y);
1667 BlitBitmap(src_bitmap, d, src_x, src_y, MINI_TILEX, MINI_TILEY, x, y);
1670 inline static void DrawGraphicShiftedNormal(int x, int y, int dx, int dy,
1671 int graphic, int frame,
1672 int cut_mode, int mask_mode)
1677 int width = TILEX, height = TILEY;
1680 if (dx || dy) /* shifted graphic */
1682 if (x < BX1) /* object enters playfield from the left */
1689 else if (x > BX2) /* object enters playfield from the right */
1695 else if (x==BX1 && dx < 0) /* object leaves playfield to the left */
1701 else if (x==BX2 && dx > 0) /* object leaves playfield to the right */
1703 else if (dx) /* general horizontal movement */
1704 MarkTileDirty(x + SIGN(dx), y);
1706 if (y < BY1) /* object enters playfield from the top */
1708 if (cut_mode==CUT_BELOW) /* object completely above top border */
1716 else if (y > BY2) /* object enters playfield from the bottom */
1722 else if (y==BY1 && dy < 0) /* object leaves playfield to the top */
1728 else if (dy > 0 && cut_mode == CUT_ABOVE)
1730 if (y == BY2) /* object completely above bottom border */
1736 MarkTileDirty(x, y + 1);
1737 } /* object leaves playfield to the bottom */
1738 else if (dy > 0 && (y == BY2 || cut_mode == CUT_BELOW))
1740 else if (dy) /* general vertical movement */
1741 MarkTileDirty(x, y + SIGN(dy));
1745 if (!IN_SCR_FIELD(x, y))
1747 printf("DrawGraphicShifted(): x = %d, y = %d, graphic = %d\n",x,y,graphic);
1748 printf("DrawGraphicShifted(): This should never happen!\n");
1754 width = width * TILESIZE_VAR / TILESIZE;
1755 height = height * TILESIZE_VAR / TILESIZE;
1756 cx = cx * TILESIZE_VAR / TILESIZE;
1757 cy = cy * TILESIZE_VAR / TILESIZE;
1758 dx = dx * TILESIZE_VAR / TILESIZE;
1759 dy = dy * TILESIZE_VAR / TILESIZE;
1762 if (width > 0 && height > 0)
1764 getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
1770 dst_x = FX + x * TILEX_VAR + dx;
1771 dst_y = FY + y * TILEY_VAR + dy;
1773 dst_x = FX + x * TILEX + dx;
1774 dst_y = FY + y * TILEY + dy;
1777 if (mask_mode == USE_MASKING)
1779 SetClipOrigin(src_bitmap, src_bitmap->stored_clip_gc,
1780 dst_x - src_x, dst_y - src_y);
1781 BlitBitmapMasked(src_bitmap, drawto_field, src_x, src_y, width, height,
1785 BlitBitmap(src_bitmap, drawto_field, src_x, src_y, width, height,
1788 MarkTileDirty(x, y);
1792 inline static void DrawGraphicShiftedDouble(int x, int y, int dx, int dy,
1793 int graphic, int frame,
1794 int cut_mode, int mask_mode)
1800 int width = TILEX_VAR, height = TILEY_VAR;
1802 int width = TILEX, height = TILEY;
1806 int x2 = x + SIGN(dx);
1807 int y2 = y + SIGN(dy);
1809 /* !!! DOES NOT WORK FOR SLOW MOVEMENT !!! */
1810 int sync_frame = GfxFrame[LEVELX(x)][LEVELY(y)];
1812 /* movement with two-tile animations must be sync'ed with movement position,
1813 not with current GfxFrame (which can be higher when using slow movement) */
1814 int anim_pos = (dx ? ABS(dx) : ABS(dy));
1815 int anim_frames = graphic_info[graphic].anim_frames;
1817 /* (we also need anim_delay here for movement animations with less frames) */
1818 int anim_delay = graphic_info[graphic].anim_delay;
1819 int sync_frame = anim_pos * anim_frames * anim_delay / TILESIZE;
1821 int sync_frame = anim_pos * anim_frames / TILESIZE;
1824 boolean draw_start_tile = (cut_mode != CUT_ABOVE); /* only for falling! */
1825 boolean draw_end_tile = (cut_mode != CUT_BELOW); /* only for falling! */
1827 /* re-calculate animation frame for two-tile movement animation */
1828 frame = getGraphicAnimationFrame(graphic, sync_frame);
1832 printf("::: %d, %d, %d => %d [%d]\n",
1833 anim_pos, anim_frames, anim_delay, sync_frame, graphic);
1835 printf("::: %d, %d => %d\n",
1836 anim_pos, anim_frames, sync_frame);
1841 printf("::: %d [%d, %d] [%d] [%d]\n", frame, sync_frame, dy,
1842 GfxFrame[LEVELX(x)][LEVELY(y)], mask_mode);
1845 /* check if movement start graphic inside screen area and should be drawn */
1846 if (draw_start_tile && IN_SCR_FIELD(x1, y1))
1848 getGraphicSourceExt(graphic, frame, &src_bitmap, &src_x, &src_y, TRUE);
1851 dst_x = FX + x1 * TILEX_VAR;
1852 dst_y = FY + y1 * TILEY_VAR;
1854 dst_x = FX + x1 * TILEX;
1855 dst_y = FY + y1 * TILEY;
1858 if (mask_mode == USE_MASKING)
1860 SetClipOrigin(src_bitmap, src_bitmap->stored_clip_gc,
1861 dst_x - src_x, dst_y - src_y);
1862 BlitBitmapMasked(src_bitmap, drawto_field, src_x, src_y, width, height,
1866 BlitBitmap(src_bitmap, drawto_field, src_x, src_y, width, height,
1869 MarkTileDirty(x1, y1);
1872 /* check if movement end graphic inside screen area and should be drawn */
1873 if (draw_end_tile && IN_SCR_FIELD(x2, y2))
1875 getGraphicSourceExt(graphic, frame, &src_bitmap, &src_x, &src_y, FALSE);
1878 dst_x = FX + x2 * TILEX_VAR;
1879 dst_y = FY + y2 * TILEY_VAR;
1881 dst_x = FX + x2 * TILEX;
1882 dst_y = FY + y2 * TILEY;
1885 if (mask_mode == USE_MASKING)
1887 SetClipOrigin(src_bitmap, src_bitmap->stored_clip_gc,
1888 dst_x - src_x, dst_y - src_y);
1889 BlitBitmapMasked(src_bitmap, drawto_field, src_x, src_y, width, height,
1893 BlitBitmap(src_bitmap, drawto_field, src_x, src_y, width, height,
1896 MarkTileDirty(x2, y2);
1900 static void DrawGraphicShifted(int x, int y, int dx, int dy,
1901 int graphic, int frame,
1902 int cut_mode, int mask_mode)
1906 DrawGraphic(x, y, graphic, frame);
1911 if (graphic_info[graphic].double_movement) /* EM style movement images */
1912 DrawGraphicShiftedDouble(x, y, dx, dy, graphic, frame, cut_mode,mask_mode);
1914 DrawGraphicShiftedNormal(x, y, dx, dy, graphic, frame, cut_mode,mask_mode);
1917 void DrawGraphicShiftedThruMask(int x, int y, int dx, int dy, int graphic,
1918 int frame, int cut_mode)
1920 DrawGraphicShifted(x, y, dx, dy, graphic, frame, cut_mode, USE_MASKING);
1923 void DrawScreenElementExt(int x, int y, int dx, int dy, int element,
1924 int cut_mode, int mask_mode)
1926 int lx = LEVELX(x), ly = LEVELY(y);
1930 if (IN_LEV_FIELD(lx, ly))
1932 SetRandomAnimationValue(lx, ly);
1934 graphic = el_act_dir2img(element, GfxAction[lx][ly], GfxDir[lx][ly]);
1935 frame = getGraphicAnimationFrame(graphic, GfxFrame[lx][ly]);
1937 /* do not use double (EM style) movement graphic when not moving */
1938 if (graphic_info[graphic].double_movement && !dx && !dy)
1940 graphic = el_act_dir2img(element, ACTION_DEFAULT, GfxDir[lx][ly]);
1941 frame = getGraphicAnimationFrame(graphic, GfxFrame[lx][ly]);
1944 else /* border element */
1946 graphic = el2img(element);
1947 frame = getGraphicAnimationFrame(graphic, -1);
1950 if (element == EL_EXPANDABLE_WALL)
1952 boolean left_stopped = FALSE, right_stopped = FALSE;
1954 if (!IN_LEV_FIELD(lx - 1, ly) || IS_WALL(Feld[lx - 1][ly]))
1955 left_stopped = TRUE;
1956 if (!IN_LEV_FIELD(lx + 1, ly) || IS_WALL(Feld[lx + 1][ly]))
1957 right_stopped = TRUE;
1959 if (left_stopped && right_stopped)
1961 else if (left_stopped)
1963 graphic = IMG_EXPANDABLE_WALL_GROWING_RIGHT;
1964 frame = graphic_info[graphic].anim_frames - 1;
1966 else if (right_stopped)
1968 graphic = IMG_EXPANDABLE_WALL_GROWING_LEFT;
1969 frame = graphic_info[graphic].anim_frames - 1;
1974 DrawGraphicShifted(x, y, dx, dy, graphic, frame, cut_mode, mask_mode);
1975 else if (mask_mode == USE_MASKING)
1976 DrawGraphicThruMask(x, y, graphic, frame);
1978 DrawGraphic(x, y, graphic, frame);
1981 void DrawLevelElementExt(int x, int y, int dx, int dy, int element,
1982 int cut_mode, int mask_mode)
1984 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1985 DrawScreenElementExt(SCREENX(x), SCREENY(y), dx, dy, element,
1986 cut_mode, mask_mode);
1989 void DrawScreenElementShifted(int x, int y, int dx, int dy, int element,
1992 DrawScreenElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
1995 void DrawLevelElementShifted(int x, int y, int dx, int dy, int element,
1998 DrawLevelElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
2001 void DrawLevelElementThruMask(int x, int y, int element)
2003 DrawLevelElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
2006 void DrawLevelFieldThruMask(int x, int y)
2008 DrawLevelElementExt(x, y, 0, 0, Feld[x][y], NO_CUTTING, USE_MASKING);
2011 /* !!! implementation of quicksand is totally broken !!! */
2012 #define IS_CRUMBLED_TILE(x, y, e) \
2013 (GFX_CRUMBLED(e) && (!IN_LEV_FIELD(x, y) || \
2014 !IS_MOVING(x, y) || \
2015 (e) == EL_QUICKSAND_EMPTYING || \
2016 (e) == EL_QUICKSAND_FAST_EMPTYING))
2018 static void DrawLevelFieldCrumbledInnerCorners(int x, int y, int dx, int dy,
2023 int width, height, cx, cy;
2024 int sx = SCREENX(x), sy = SCREENY(y);
2025 int crumbled_border_size = graphic_info[graphic].border_size;
2028 getGraphicSource(graphic, 0, &src_bitmap, &src_x, &src_y);
2030 for (i = 1; i < 4; i++)
2032 int dxx = (i & 1 ? dx : 0);
2033 int dyy = (i & 2 ? dy : 0);
2036 int element = (IN_LEV_FIELD(xx, yy) ? TILE_GFX_ELEMENT(xx, yy) :
2039 /* check if neighbour field is of same crumble type */
2040 boolean same = (IS_CRUMBLED_TILE(xx, yy, element) &&
2041 graphic_info[graphic].class ==
2042 graphic_info[el_act2crm(element, ACTION_DEFAULT)].class);
2044 /* return if check prevents inner corner */
2045 if (same == (dxx == dx && dyy == dy))
2049 /* if we reach this point, we have an inner corner */
2051 getGraphicSource(graphic, 1, &src_bitmap, &src_x, &src_y);
2054 width = crumbled_border_size * TILESIZE_VAR / TILESIZE;
2055 height = crumbled_border_size * TILESIZE_VAR / TILESIZE;
2056 cx = (dx > 0 ? TILEX - crumbled_border_size : 0) * TILESIZE_VAR / TILESIZE;
2057 cy = (dy > 0 ? TILEY - crumbled_border_size : 0) * TILESIZE_VAR / TILESIZE;
2059 BlitBitmap(src_bitmap, drawto_field, src_x + cx, src_y + cy,
2060 width, height, FX + sx * TILEX_VAR + cx, FY + sy * TILEY_VAR + cy);
2062 width = crumbled_border_size;
2063 height = crumbled_border_size;
2064 cx = (dx > 0 ? TILEX - crumbled_border_size : 0);
2065 cy = (dy > 0 ? TILEY - crumbled_border_size : 0);
2067 BlitBitmap(src_bitmap, drawto_field, src_x + cx, src_y + cy,
2068 width, height, FX + sx * TILEX + cx, FY + sy * TILEY + cy);
2072 static void DrawLevelFieldCrumbledBorders(int x, int y, int graphic, int frame,
2077 int width, height, bx, by, cx, cy;
2078 int sx = SCREENX(x), sy = SCREENY(y);
2079 int crumbled_border_size = graphic_info[graphic].border_size;
2082 getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
2084 /* draw simple, sloppy, non-corner-accurate crumbled border */
2087 width = (dir == 1 || dir == 2 ? crumbled_border_size : TILEX);
2088 height = (dir == 0 || dir == 3 ? crumbled_border_size : TILEY);
2089 cx = (dir == 2 ? TILEX - crumbled_border_size : 0);
2090 cy = (dir == 3 ? TILEY - crumbled_border_size : 0);
2092 if (dir == 1 || dir == 2) /* left or right crumbled border */
2094 width = crumbled_border_size;
2096 cx = (dir == 2 ? TILEX - crumbled_border_size : 0);
2099 else /* top or bottom crumbled border */
2102 height = crumbled_border_size;
2104 cy = (dir == 3 ? TILEY - crumbled_border_size : 0);
2109 BlitBitmap(src_bitmap, drawto_field,
2110 src_x + cx * TILESIZE_VAR / TILESIZE,
2111 src_y + cy * TILESIZE_VAR / TILESIZE,
2112 width * TILESIZE_VAR / TILESIZE,
2113 height * TILESIZE_VAR / TILESIZE,
2114 FX + sx * TILEX_VAR + cx * TILESIZE_VAR / TILESIZE,
2115 FY + sy * TILEY_VAR + cy * TILESIZE_VAR / TILESIZE);
2117 BlitBitmap(src_bitmap, drawto_field, src_x + cx, src_y + cy,
2118 width, height, FX + sx * TILEX + cx, FY + sy * TILEY + cy);
2121 /* (remaining middle border part must be at least as big as corner part) */
2122 if (!(graphic_info[graphic].style & STYLE_ACCURATE_BORDERS) ||
2123 crumbled_border_size >= TILESIZE / 3)
2126 /* correct corners of crumbled border, if needed */
2129 for (i = -1; i <= 1; i+=2)
2131 int xx = x + (dir == 0 || dir == 3 ? i : 0);
2132 int yy = y + (dir == 1 || dir == 2 ? i : 0);
2133 int element = (IN_LEV_FIELD(xx, yy) ? TILE_GFX_ELEMENT(xx, yy) :
2136 /* check if neighbour field is of same crumble type */
2137 if (IS_CRUMBLED_TILE(xx, yy, element) &&
2138 graphic_info[graphic].class ==
2139 graphic_info[el_act2crm(element, ACTION_DEFAULT)].class)
2141 /* no crumbled corner, but continued crumbled border */
2143 int c1 = (dir == 2 || dir == 3 ? TILESIZE - crumbled_border_size : 0);
2144 int c2 = (i == 1 ? TILESIZE - crumbled_border_size : 0);
2145 int b1 = (i == 1 ? crumbled_border_size :
2146 TILESIZE - 2 * crumbled_border_size);
2148 width = crumbled_border_size;
2149 height = crumbled_border_size;
2151 if (dir == 1 || dir == 2)
2167 BlitBitmap(src_bitmap, drawto_field,
2168 src_x + bx * TILESIZE_VAR / TILESIZE,
2169 src_y + by * TILESIZE_VAR / TILESIZE,
2170 width * TILESIZE_VAR / TILESIZE,
2171 height * TILESIZE_VAR / TILESIZE,
2172 FX + sx * TILEX_VAR + cx * TILESIZE_VAR / TILESIZE,
2173 FY + sy * TILEY_VAR + cy * TILESIZE_VAR / TILESIZE);
2175 BlitBitmap(src_bitmap, drawto_field, src_x + bx, src_y + by,
2176 width, height, FX + sx * TILEX + cx, FY + sy * TILEY + cy);
2181 if (dir == 1 || dir == 2) /* left or right crumbled border */
2183 for (i = -1; i <= 1; i+=2)
2187 int element = (IN_LEV_FIELD(xx, yy) ? TILE_GFX_ELEMENT(xx, yy) :
2190 /* check if neighbour field is of same crumble type */
2191 if (IS_CRUMBLED_TILE(xx, yy, element) &&
2192 graphic_info[graphic].class ==
2193 graphic_info[el_act2crm(element, ACTION_DEFAULT)].class)
2195 /* no crumbled corner, but continued crumbled border */
2197 width = crumbled_border_size;
2198 height = crumbled_border_size;
2199 cx = (dir == 2 ? TILEX - crumbled_border_size : 0);
2200 cy = (i == 1 ? TILEY - crumbled_border_size : 0);
2202 by = (i == 1 ? crumbled_border_size :
2203 TILEY - 2 * crumbled_border_size);
2205 BlitBitmap(src_bitmap, drawto_field, src_x + bx, src_y + by,
2206 width, height, FX + sx * TILEX + cx, FY + sy * TILEY + cy);
2210 else /* top or bottom crumbled border */
2212 for (i = -1; i <= 1; i+=2)
2216 int element = (IN_LEV_FIELD(xx, yy) ? TILE_GFX_ELEMENT(xx, yy) :
2219 /* check if neighbour field is of same crumble type */
2220 if (IS_CRUMBLED_TILE(xx, yy, element) &&
2221 graphic_info[graphic].class ==
2222 graphic_info[el_act2crm(element, ACTION_DEFAULT)].class)
2224 /* no crumbled corner, but continued crumbled border */
2226 width = crumbled_border_size;
2227 height = crumbled_border_size;
2228 cx = (i == 1 ? TILEX - crumbled_border_size : 0);
2229 cy = (dir == 3 ? TILEY - crumbled_border_size : 0);
2230 bx = (i == 1 ? crumbled_border_size :
2231 TILEX - 2 * crumbled_border_size);
2234 BlitBitmap(src_bitmap, drawto_field, src_x + bx, src_y + by,
2235 width, height, FX + sx * TILEX + cx, FY + sy * TILEY + cy);
2242 static void DrawLevelFieldCrumbledExt(int x, int y, int graphic, int frame)
2244 int sx = SCREENX(x), sy = SCREENY(y);
2247 static int xy[4][2] =
2255 if (!IN_LEV_FIELD(x, y))
2258 element = TILE_GFX_ELEMENT(x, y);
2260 /* crumble field itself */
2261 if (IS_CRUMBLED_TILE(x, y, element))
2263 if (!IN_SCR_FIELD(sx, sy))
2266 for (i = 0; i < 4; i++)
2268 int xx = x + xy[i][0];
2269 int yy = y + xy[i][1];
2271 element = (IN_LEV_FIELD(xx, yy) ? TILE_GFX_ELEMENT(xx, yy) :
2274 /* check if neighbour field is of same crumble type */
2276 if (IS_CRUMBLED_TILE(xx, yy, element) &&
2277 graphic_info[graphic].class ==
2278 graphic_info[el_act2crm(element, ACTION_DEFAULT)].class)
2281 if (IS_CRUMBLED_TILE(xx, yy, element))
2285 DrawLevelFieldCrumbledBorders(x, y, graphic, frame, i);
2288 if ((graphic_info[graphic].style & STYLE_INNER_CORNERS) &&
2289 graphic_info[graphic].anim_frames == 2)
2291 for (i = 0; i < 4; i++)
2293 int dx = (i & 1 ? +1 : -1);
2294 int dy = (i & 2 ? +1 : -1);
2296 DrawLevelFieldCrumbledInnerCorners(x, y, dx, dy, graphic);
2300 MarkTileDirty(sx, sy);
2302 else /* center field not crumbled -- crumble neighbour fields */
2304 for (i = 0; i < 4; i++)
2306 int xx = x + xy[i][0];
2307 int yy = y + xy[i][1];
2308 int sxx = sx + xy[i][0];
2309 int syy = sy + xy[i][1];
2311 if (!IN_LEV_FIELD(xx, yy) ||
2312 !IN_SCR_FIELD(sxx, syy))
2315 if (Feld[xx][yy] == EL_ELEMENT_SNAPPING)
2318 element = TILE_GFX_ELEMENT(xx, yy);
2320 if (!IS_CRUMBLED_TILE(xx, yy, element))
2323 graphic = el_act2crm(element, ACTION_DEFAULT);
2325 DrawLevelFieldCrumbledBorders(xx, yy, graphic, 0, 3 - i);
2327 MarkTileDirty(sxx, syy);
2332 void DrawLevelFieldCrumbled(int x, int y)
2336 if (!IN_LEV_FIELD(x, y))
2340 /* !!! CHECK THIS !!! */
2343 if (Feld[x][y] == EL_ELEMENT_SNAPPING &&
2344 GFX_CRUMBLED(GfxElement[x][y]))
2347 if (Feld[x][y] == EL_ELEMENT_SNAPPING &&
2348 GfxElement[x][y] != EL_UNDEFINED &&
2349 GFX_CRUMBLED(GfxElement[x][y]))
2351 DrawLevelFieldCrumbledDigging(x, y, GfxDir[x][y], GfxFrame[x][y]);
2358 graphic = el_act2crm(TILE_GFX_ELEMENT(x, y), ACTION_DEFAULT);
2360 graphic = el_act2crm(Feld[x][y], ACTION_DEFAULT);
2363 DrawLevelFieldCrumbledExt(x, y, graphic, 0);
2366 void DrawLevelFieldCrumbledDigging(int x, int y, int direction,
2369 int graphic1 = el_act_dir2img(GfxElement[x][y], ACTION_DIGGING, direction);
2370 int graphic2 = el_act_dir2crm(GfxElement[x][y], ACTION_DIGGING, direction);
2371 int frame1 = getGraphicAnimationFrame(graphic1, step_frame);
2372 int frame2 = getGraphicAnimationFrame(graphic2, step_frame);
2373 int sx = SCREENX(x), sy = SCREENY(y);
2375 DrawGraphic(sx, sy, graphic1, frame1);
2376 DrawLevelFieldCrumbledExt(x, y, graphic2, frame2);
2379 void DrawLevelFieldCrumbledNeighbours(int x, int y)
2381 int sx = SCREENX(x), sy = SCREENY(y);
2382 static int xy[4][2] =
2391 for (i = 0; i < 4; i++)
2393 int xx = x + xy[i][0];
2394 int yy = y + xy[i][1];
2395 int sxx = sx + xy[i][0];
2396 int syy = sy + xy[i][1];
2398 if (!IN_LEV_FIELD(xx, yy) ||
2399 !IN_SCR_FIELD(sxx, syy) ||
2400 !GFX_CRUMBLED(Feld[xx][yy]) ||
2404 DrawLevelField(xx, yy);
2408 static int getBorderElement(int x, int y)
2412 { EL_STEELWALL_TOPLEFT, EL_INVISIBLE_STEELWALL_TOPLEFT },
2413 { EL_STEELWALL_TOPRIGHT, EL_INVISIBLE_STEELWALL_TOPRIGHT },
2414 { EL_STEELWALL_BOTTOMLEFT, EL_INVISIBLE_STEELWALL_BOTTOMLEFT },
2415 { EL_STEELWALL_BOTTOMRIGHT, EL_INVISIBLE_STEELWALL_BOTTOMRIGHT },
2416 { EL_STEELWALL_VERTICAL, EL_INVISIBLE_STEELWALL_VERTICAL },
2417 { EL_STEELWALL_HORIZONTAL, EL_INVISIBLE_STEELWALL_HORIZONTAL },
2418 { EL_STEELWALL, EL_INVISIBLE_STEELWALL }
2420 int steel_type = (BorderElement == EL_STEELWALL ? 0 : 1);
2421 int steel_position = (x == -1 && y == -1 ? 0 :
2422 x == lev_fieldx && y == -1 ? 1 :
2423 x == -1 && y == lev_fieldy ? 2 :
2424 x == lev_fieldx && y == lev_fieldy ? 3 :
2425 x == -1 || x == lev_fieldx ? 4 :
2426 y == -1 || y == lev_fieldy ? 5 : 6);
2428 return border[steel_position][steel_type];
2431 void DrawScreenElement(int x, int y, int element)
2433 DrawScreenElementExt(x, y, 0, 0, element, NO_CUTTING, NO_MASKING);
2434 DrawLevelFieldCrumbled(LEVELX(x), LEVELY(y));
2437 void DrawLevelElement(int x, int y, int element)
2439 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
2440 DrawScreenElement(SCREENX(x), SCREENY(y), element);
2443 void DrawScreenField(int x, int y)
2445 int lx = LEVELX(x), ly = LEVELY(y);
2446 int element, content;
2448 if (!IN_LEV_FIELD(lx, ly))
2450 if (lx < -1 || lx > lev_fieldx || ly < -1 || ly > lev_fieldy)
2453 element = getBorderElement(lx, ly);
2455 DrawScreenElement(x, y, element);
2460 element = Feld[lx][ly];
2461 content = Store[lx][ly];
2463 if (IS_MOVING(lx, ly))
2465 int horiz_move = (MovDir[lx][ly] == MV_LEFT || MovDir[lx][ly] == MV_RIGHT);
2466 boolean cut_mode = NO_CUTTING;
2468 if (element == EL_QUICKSAND_EMPTYING ||
2469 element == EL_QUICKSAND_FAST_EMPTYING ||
2470 element == EL_MAGIC_WALL_EMPTYING ||
2471 element == EL_BD_MAGIC_WALL_EMPTYING ||
2472 element == EL_DC_MAGIC_WALL_EMPTYING ||
2473 element == EL_AMOEBA_DROPPING)
2474 cut_mode = CUT_ABOVE;
2475 else if (element == EL_QUICKSAND_FILLING ||
2476 element == EL_QUICKSAND_FAST_FILLING ||
2477 element == EL_MAGIC_WALL_FILLING ||
2478 element == EL_BD_MAGIC_WALL_FILLING ||
2479 element == EL_DC_MAGIC_WALL_FILLING)
2480 cut_mode = CUT_BELOW;
2483 if (lx == 9 && ly == 1)
2484 printf("::: %s [%d] [%d, %d] [%d]\n",
2485 EL_NAME(TILE_GFX_ELEMENT(lx, ly)),
2486 el_act2crm(TILE_GFX_ELEMENT(lx, ly), ACTION_DEFAULT),
2487 element_info[EL_QUICKSAND_EMPTYING].graphic[ACTION_DEFAULT],
2488 element_info[EL_QUICKSAND_EMPTYING].crumbled[ACTION_DEFAULT],
2489 GFX_CRUMBLED(TILE_GFX_ELEMENT(lx, ly)));
2492 if (cut_mode == CUT_ABOVE)
2494 DrawScreenElement(x, y, element);
2496 DrawScreenElementShifted(x, y, 0, 0, element, NO_CUTTING);
2499 DrawScreenElement(x, y, EL_EMPTY);
2502 DrawScreenElementShifted(x, y, MovPos[lx][ly], 0, element, NO_CUTTING);
2503 else if (cut_mode == NO_CUTTING)
2504 DrawScreenElementShifted(x, y, 0, MovPos[lx][ly], element, cut_mode);
2507 DrawScreenElementShifted(x, y, 0, MovPos[lx][ly], content, cut_mode);
2510 if (cut_mode == CUT_BELOW &&
2511 IN_LEV_FIELD(lx, ly + 1) && IN_SCR_FIELD(x, y + 1))
2512 DrawLevelElement(lx, ly + 1, element);
2516 if (content == EL_ACID)
2518 int dir = MovDir[lx][ly];
2519 int newlx = lx + (dir == MV_LEFT ? -1 : dir == MV_RIGHT ? +1 : 0);
2520 int newly = ly + (dir == MV_UP ? -1 : dir == MV_DOWN ? +1 : 0);
2522 DrawLevelElementThruMask(newlx, newly, EL_ACID);
2525 else if (IS_BLOCKED(lx, ly))
2530 boolean cut_mode = NO_CUTTING;
2531 int element_old, content_old;
2533 Blocked2Moving(lx, ly, &oldx, &oldy);
2536 horiz_move = (MovDir[oldx][oldy] == MV_LEFT ||
2537 MovDir[oldx][oldy] == MV_RIGHT);
2539 element_old = Feld[oldx][oldy];
2540 content_old = Store[oldx][oldy];
2542 if (element_old == EL_QUICKSAND_EMPTYING ||
2543 element_old == EL_QUICKSAND_FAST_EMPTYING ||
2544 element_old == EL_MAGIC_WALL_EMPTYING ||
2545 element_old == EL_BD_MAGIC_WALL_EMPTYING ||
2546 element_old == EL_DC_MAGIC_WALL_EMPTYING ||
2547 element_old == EL_AMOEBA_DROPPING)
2548 cut_mode = CUT_ABOVE;
2550 DrawScreenElement(x, y, EL_EMPTY);
2553 DrawScreenElementShifted(sx, sy, MovPos[oldx][oldy], 0, element_old,
2555 else if (cut_mode == NO_CUTTING)
2556 DrawScreenElementShifted(sx, sy, 0, MovPos[oldx][oldy], element_old,
2559 DrawScreenElementShifted(sx, sy, 0, MovPos[oldx][oldy], content_old,
2562 else if (IS_DRAWABLE(element))
2563 DrawScreenElement(x, y, element);
2565 DrawScreenElement(x, y, EL_EMPTY);
2568 void DrawLevelField(int x, int y)
2570 if (IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
2571 DrawScreenField(SCREENX(x), SCREENY(y));
2572 else if (IS_MOVING(x, y))
2576 Moving2Blocked(x, y, &newx, &newy);
2577 if (IN_SCR_FIELD(SCREENX(newx), SCREENY(newy)))
2578 DrawScreenField(SCREENX(newx), SCREENY(newy));
2580 else if (IS_BLOCKED(x, y))
2584 Blocked2Moving(x, y, &oldx, &oldy);
2585 if (IN_SCR_FIELD(SCREENX(oldx), SCREENY(oldy)))
2586 DrawScreenField(SCREENX(oldx), SCREENY(oldy));
2590 void DrawMiniElement(int x, int y, int element)
2594 graphic = el2edimg(element);
2595 DrawMiniGraphic(x, y, graphic);
2598 void DrawMiniElementOrWall(int sx, int sy, int scroll_x, int scroll_y)
2600 int x = sx + scroll_x, y = sy + scroll_y;
2602 if (x < -1 || x > lev_fieldx || y < -1 || y > lev_fieldy)
2603 DrawMiniElement(sx, sy, EL_EMPTY);
2604 else if (x > -1 && x < lev_fieldx && y > -1 && y < lev_fieldy)
2605 DrawMiniElement(sx, sy, Feld[x][y]);
2607 DrawMiniGraphic(sx, sy, el2edimg(getBorderElement(x, y)));
2610 void DrawEnvelopeBackgroundTiles(int graphic, int startx, int starty,
2611 int x, int y, int xsize, int ysize,
2612 int tile_width, int tile_height)
2616 int dst_x = startx + x * tile_width;
2617 int dst_y = starty + y * tile_height;
2618 int width = graphic_info[graphic].width;
2619 int height = graphic_info[graphic].height;
2620 int inner_width_raw = MAX(width - 2 * tile_width, tile_width);
2621 int inner_height_raw = MAX(height - 2 * tile_height, tile_height);
2622 int inner_width = inner_width_raw - (inner_width_raw % tile_width);
2623 int inner_height = inner_height_raw - (inner_height_raw % tile_height);
2624 int inner_sx = (width >= 3 * tile_width ? tile_width : 0);
2625 int inner_sy = (height >= 3 * tile_height ? tile_height : 0);
2626 boolean draw_masked = graphic_info[graphic].draw_masked;
2628 getFixedGraphicSource(graphic, 0, &src_bitmap, &src_x, &src_y);
2630 if (src_bitmap == NULL || width < tile_width || height < tile_height)
2632 ClearRectangle(drawto, dst_x, dst_y, tile_width, tile_height);
2636 src_x += (x == 0 ? 0 : x == xsize - 1 ? width - tile_width :
2637 inner_sx + (x - 1) * tile_width % inner_width);
2638 src_y += (y == 0 ? 0 : y == ysize - 1 ? height - tile_height :
2639 inner_sy + (y - 1) * tile_height % inner_height);
2643 SetClipOrigin(src_bitmap, src_bitmap->stored_clip_gc,
2644 dst_x - src_x, dst_y - src_y);
2645 BlitBitmapMasked(src_bitmap, drawto, src_x, src_y, tile_width, tile_height,
2649 BlitBitmap(src_bitmap, drawto, src_x, src_y, tile_width, tile_height,
2653 void DrawEnvelopeBackground(int graphic, int startx, int starty,
2654 int x, int y, int xsize, int ysize, int font_nr)
2656 int font_width = getFontWidth(font_nr);
2657 int font_height = getFontHeight(font_nr);
2659 DrawEnvelopeBackgroundTiles(graphic, startx, starty, x, y, xsize, ysize,
2660 font_width, font_height);
2663 void AnimateEnvelope(int envelope_nr, int anim_mode, int action)
2665 int graphic = IMG_BACKGROUND_ENVELOPE_1 + envelope_nr;
2666 Bitmap *src_bitmap = graphic_info[graphic].bitmap;
2667 int mask_mode = (src_bitmap != NULL ? BLIT_MASKED : BLIT_ON_BACKGROUND);
2668 boolean ffwd_delay = (tape.playing && tape.fast_forward);
2669 boolean no_delay = (tape.warp_forward);
2670 unsigned int anim_delay = 0;
2671 int frame_delay_value = (ffwd_delay ? FfwdFrameDelay : GameFrameDelay);
2672 int anim_delay_value = (no_delay ? 0 : frame_delay_value);
2673 int font_nr = FONT_ENVELOPE_1 + envelope_nr;
2674 int font_width = getFontWidth(font_nr);
2675 int font_height = getFontHeight(font_nr);
2676 int max_xsize = level.envelope[envelope_nr].xsize;
2677 int max_ysize = level.envelope[envelope_nr].ysize;
2678 int xstart = (anim_mode & ANIM_VERTICAL ? max_xsize : 0);
2679 int ystart = (anim_mode & ANIM_HORIZONTAL ? max_ysize : 0);
2680 int xend = max_xsize;
2681 int yend = (anim_mode != ANIM_DEFAULT ? max_ysize : 0);
2682 int xstep = (xstart < xend ? 1 : 0);
2683 int ystep = (ystart < yend || xstep == 0 ? 1 : 0);
2686 for (x = xstart, y = ystart; x <= xend && y <= yend; x += xstep, y += ystep)
2688 int xsize = (action == ACTION_CLOSING ? xend - (x - xstart) : x) + 2;
2689 int ysize = (action == ACTION_CLOSING ? yend - (y - ystart) : y) + 2;
2690 int sx = SX + (SXSIZE - xsize * font_width) / 2;
2691 int sy = SY + (SYSIZE - ysize * font_height) / 2;
2694 SetDrawtoField(DRAW_BUFFERED);
2697 BlitScreenToBitmap(backbuffer);
2699 BlitBitmap(fieldbuffer, backbuffer, FX, FY, SXSIZE, SYSIZE, SX, SY);
2702 SetDrawtoField(DRAW_BACKBUFFER);
2704 for (yy = 0; yy < ysize; yy++)
2705 for (xx = 0; xx < xsize; xx++)
2706 DrawEnvelopeBackground(graphic, sx, sy, xx, yy, xsize, ysize, font_nr);
2709 DrawTextBuffer(sx + font_width, sy + font_height,
2710 level.envelope[envelope_nr].text, font_nr, max_xsize,
2711 xsize - 2, ysize - 2, 0, mask_mode,
2712 level.envelope[envelope_nr].autowrap,
2713 level.envelope[envelope_nr].centered, FALSE);
2715 DrawTextToTextArea(sx + font_width, sy + font_height,
2716 level.envelope[envelope_nr].text, font_nr, max_xsize,
2717 xsize - 2, ysize - 2, mask_mode);
2720 redraw_mask |= REDRAW_FIELD | REDRAW_FROM_BACKBUFFER;
2723 WaitUntilDelayReached(&anim_delay, anim_delay_value / 2);
2727 void ShowEnvelope(int envelope_nr)
2729 int element = EL_ENVELOPE_1 + envelope_nr;
2730 int graphic = IMG_BACKGROUND_ENVELOPE_1 + envelope_nr;
2731 int sound_opening = element_info[element].sound[ACTION_OPENING];
2732 int sound_closing = element_info[element].sound[ACTION_CLOSING];
2733 boolean ffwd_delay = (tape.playing && tape.fast_forward);
2734 boolean no_delay = (tape.warp_forward);
2735 int normal_delay_value = ONE_SECOND_DELAY / (ffwd_delay ? 2 : 1);
2736 int wait_delay_value = (no_delay ? 0 : normal_delay_value);
2737 int anim_mode = graphic_info[graphic].anim_mode;
2738 int main_anim_mode = (anim_mode == ANIM_NONE ? ANIM_VERTICAL|ANIM_HORIZONTAL:
2739 anim_mode == ANIM_DEFAULT ? ANIM_VERTICAL : anim_mode);
2741 game.envelope_active = TRUE; /* needed for RedrawPlayfield() events */
2743 PlayMenuSoundStereo(sound_opening, SOUND_MIDDLE);
2745 if (anim_mode == ANIM_DEFAULT)
2746 AnimateEnvelope(envelope_nr, ANIM_DEFAULT, ACTION_OPENING);
2748 AnimateEnvelope(envelope_nr, main_anim_mode, ACTION_OPENING);
2751 Delay(wait_delay_value);
2753 WaitForEventToContinue();
2755 PlayMenuSoundStereo(sound_closing, SOUND_MIDDLE);
2757 if (anim_mode != ANIM_NONE)
2758 AnimateEnvelope(envelope_nr, main_anim_mode, ACTION_CLOSING);
2760 if (anim_mode == ANIM_DEFAULT)
2761 AnimateEnvelope(envelope_nr, ANIM_DEFAULT, ACTION_CLOSING);
2763 game.envelope_active = FALSE;
2765 SetDrawtoField(DRAW_BUFFERED);
2767 redraw_mask |= REDRAW_FIELD;
2771 static void setRequestPosition(int *x, int *y, boolean add_border_size)
2773 int border_size = request.border_size;
2774 int sx_center = (request.x != -1 ? request.x : SX + SXSIZE / 2);
2775 int sy_center = (request.y != -1 ? request.y : SY + SYSIZE / 2);
2776 int sx = sx_center - request.width / 2;
2777 int sy = sy_center - request.height / 2;
2779 if (add_border_size)
2789 void DrawEnvelopeRequest(char *text)
2791 char *text_final = text;
2792 char *text_door_style = NULL;
2793 int graphic = IMG_BACKGROUND_REQUEST;
2794 Bitmap *src_bitmap = graphic_info[graphic].bitmap;
2795 int mask_mode = (src_bitmap != NULL ? BLIT_MASKED : BLIT_ON_BACKGROUND);
2796 int font_nr = FONT_REQUEST;
2797 int font_width = getFontWidth(font_nr);
2798 int font_height = getFontHeight(font_nr);
2799 int border_size = request.border_size;
2800 int line_spacing = request.line_spacing;
2801 int line_height = font_height + line_spacing;
2802 int text_width = request.width - 2 * border_size;
2803 int text_height = request.height - 2 * border_size;
2804 int line_length = text_width / font_width;
2805 int max_lines = text_height / line_height;
2806 int width = request.width;
2807 int height = request.height;
2808 int tile_size = request.step_offset;
2809 int x_steps = width / tile_size;
2810 int y_steps = height / tile_size;
2814 if (request.wrap_single_words)
2816 char *src_text_ptr, *dst_text_ptr;
2818 text_door_style = checked_malloc(2 * strlen(text) + 1);
2820 src_text_ptr = text;
2821 dst_text_ptr = text_door_style;
2823 while (*src_text_ptr)
2825 if (*src_text_ptr == ' ' ||
2826 *src_text_ptr == '?' ||
2827 *src_text_ptr == '!')
2828 *dst_text_ptr++ = '\n';
2830 if (*src_text_ptr != ' ')
2831 *dst_text_ptr++ = *src_text_ptr;
2836 *dst_text_ptr = '\0';
2838 text_final = text_door_style;
2841 setRequestPosition(&sx, &sy, FALSE);
2843 ClearRectangle(backbuffer, 0, 0, WIN_XSIZE, WIN_YSIZE);
2845 for (y = 0; y < y_steps; y++)
2846 for (x = 0; x < x_steps; x++)
2847 DrawEnvelopeBackgroundTiles(graphic, sx, sy,
2848 x, y, x_steps, y_steps,
2849 tile_size, tile_size);
2851 DrawTextBuffer(sx + border_size, sy + border_size, text_final, font_nr,
2852 line_length, -1, max_lines, line_spacing, mask_mode,
2853 request.autowrap, request.centered, FALSE);
2855 for (i = 0; i < NUM_TOOL_BUTTONS; i++)
2856 RedrawGadget(tool_gadget[i]);
2858 // store readily prepared envelope request for later use when animating
2859 BlitBitmap(backbuffer, bitmap_db_cross, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
2863 BlitBitmap(bitmap_db_store, backbuffer, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
2864 BlitBitmap(bitmap_db_cross, backbuffer, sx, sy, width, height, sx, sy);
2866 redraw_mask = REDRAW_FIELD | REDRAW_FROM_BACKBUFFER;
2871 BlitBitmap(bitmap_db_store, backbuffer, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
2873 redraw_mask = REDRAW_FIELD | REDRAW_FROM_BACKBUFFER;
2879 if (text_door_style)
2880 free(text_door_style);
2885 void AnimateEnvelopeRequest(int anim_mode, int action)
2887 int graphic = IMG_BACKGROUND_REQUEST;
2888 boolean draw_masked = graphic_info[graphic].draw_masked;
2890 int delay_value_normal = request.step_delay;
2891 int delay_value_fast = delay_value_normal / 2;
2893 int delay_value_normal = GameFrameDelay;
2894 int delay_value_fast = FfwdFrameDelay;
2896 boolean ffwd_delay = (tape.playing && tape.fast_forward);
2897 boolean no_delay = (tape.warp_forward);
2898 int delay_value = (ffwd_delay ? delay_value_fast : delay_value_normal);
2899 int anim_delay_value = (no_delay ? 0 : delay_value + 500 * 0);
2900 unsigned int anim_delay = 0;
2902 int width = request.width;
2903 int height = request.height;
2904 int tile_size = request.step_offset;
2905 int max_xsize = width / tile_size;
2906 int max_ysize = height / tile_size;
2907 int max_xsize_inner = max_xsize - 2;
2908 int max_ysize_inner = max_ysize - 2;
2910 int xstart = (anim_mode & ANIM_VERTICAL ? max_xsize_inner : 0);
2911 int ystart = (anim_mode & ANIM_HORIZONTAL ? max_ysize_inner : 0);
2912 int xend = max_xsize_inner;
2913 int yend = (anim_mode != ANIM_DEFAULT ? max_ysize_inner : 0);
2914 int xstep = (xstart < xend ? 1 : 0);
2915 int ystep = (ystart < yend || xstep == 0 ? 1 : 0);
2918 for (x = xstart, y = ystart; x <= xend && y <= yend; x += xstep, y += ystep)
2920 int xsize = (action == ACTION_CLOSING ? xend - (x - xstart) : x) + 2;
2921 int ysize = (action == ACTION_CLOSING ? yend - (y - ystart) : y) + 2;
2922 int sx_center = (request.x != -1 ? request.x : SX + SXSIZE / 2);
2923 int sy_center = (request.y != -1 ? request.y : SY + SYSIZE / 2);
2924 int src_x = sx_center - width / 2;
2925 int src_y = sy_center - height / 2;
2926 int dst_x = sx_center - xsize * tile_size / 2;
2927 int dst_y = sy_center - ysize * tile_size / 2;
2928 int xsize_size_left = (xsize - 1) * tile_size;
2929 int ysize_size_top = (ysize - 1) * tile_size;
2930 int max_xsize_pos = (max_xsize - 1) * tile_size;
2931 int max_ysize_pos = (max_ysize - 1) * tile_size;
2934 BlitBitmap(bitmap_db_store, backbuffer, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
2937 for (yy = 0; yy < 2; yy++)
2939 for (xx = 0; xx < 2; xx++)
2941 int src_xx = src_x + xx * max_xsize_pos;
2942 int src_yy = src_y + yy * max_ysize_pos;
2943 int dst_xx = dst_x + xx * xsize_size_left;
2944 int dst_yy = dst_y + yy * ysize_size_top;
2945 int xx_size = (xx ? tile_size : xsize_size_left);
2946 int yy_size = (yy ? tile_size : ysize_size_top);
2949 BlitBitmapMasked(bitmap_db_cross, backbuffer,
2950 src_xx, src_yy, xx_size, yy_size, dst_xx, dst_yy);
2952 BlitBitmap(bitmap_db_cross, backbuffer,
2953 src_xx, src_yy, xx_size, yy_size, dst_xx, dst_yy);
2957 BlitBitmap(bitmap_db_cross, backbuffer,
2959 xsize_size_left, ysize_size_top,
2961 BlitBitmap(bitmap_db_cross, backbuffer,
2962 src_x + max_xsize_pos, src_y,
2963 tile_size, ysize_size_top,
2964 dst_x + xsize_size_left, dst_y);
2965 BlitBitmap(bitmap_db_cross, backbuffer,
2966 src_x, src_y + max_ysize_pos,
2967 xsize_size_left, tile_size,
2968 dst_x, dst_y + ysize_size_top);
2969 BlitBitmap(bitmap_db_cross, backbuffer,
2970 src_x + max_xsize_pos, src_y + max_ysize_pos,
2971 tile_size, tile_size,
2972 dst_x + xsize_size_left, dst_y + ysize_size_top);
2976 redraw_mask = REDRAW_FIELD | REDRAW_FROM_BACKBUFFER;
2977 // redraw_mask |= REDRAW_ALL | REDRAW_FROM_BACKBUFFER;
2979 redraw_mask |= REDRAW_FIELD | REDRAW_FROM_BACKBUFFER;
2989 WaitUntilDelayReached(&anim_delay, anim_delay_value / 2);
2995 void AnimateEnvelopeRequest(char *text, int anim_mode, int action)
2998 int envelope_nr = 0;
3001 int graphic = IMG_BACKGROUND_REQUEST;
3003 int graphic = IMG_BACKGROUND_ENVELOPE_1 + envelope_nr;
3005 Bitmap *src_bitmap = graphic_info[graphic].bitmap;
3006 int mask_mode = (src_bitmap != NULL ? BLIT_MASKED : BLIT_ON_BACKGROUND);
3007 boolean ffwd_delay = (tape.playing && tape.fast_forward);
3008 boolean no_delay = (tape.warp_forward);
3009 unsigned int anim_delay = 0;
3010 int frame_delay_value = (ffwd_delay ? FfwdFrameDelay : GameFrameDelay);
3011 int anim_delay_value = (no_delay ? 0 : frame_delay_value + 500 * 0);
3013 int max_word_len = maxWordLengthInString(text);
3014 int font_nr = (max_word_len > 7 ? FONT_TEXT_1 : FONT_TEXT_2);
3016 int font_nr = FONT_ENVELOPE_1 + envelope_nr;
3018 int font_width = getFontWidth(font_nr);
3019 int font_height = getFontHeight(font_nr);
3020 int line_spacing = 2 * 1;
3024 int max_xsize = DXSIZE / font_width;
3025 // int max_ysize = DYSIZE / font_height;
3026 int max_ysize = DYSIZE / (font_height + line_spacing);
3028 int max_xsize = 7; /* tools.c: MAX_REQUEST_LINE_FONT1_LEN == 7 */
3029 int max_ysize = 13; /* tools.c: MAX_REQUEST_LINES == 13 */
3033 int max_xsize = level.envelope[envelope_nr].xsize;
3034 int max_ysize = level.envelope[envelope_nr].ysize;
3036 int xstart = (anim_mode & ANIM_VERTICAL ? max_xsize : 0);
3037 int ystart = (anim_mode & ANIM_HORIZONTAL ? max_ysize : 0);
3038 int xend = max_xsize;
3039 int yend = (anim_mode != ANIM_DEFAULT ? max_ysize : 0);
3040 int xstep = (xstart < xend ? 1 : 0);
3041 int ystep = (ystart < yend || xstep == 0 ? 1 : 0);
3046 char *text_copy = getStringCopy(text);
3049 font_nr = FONT_TEXT_2;
3051 if (maxWordLengthInString(text) > 7) /* MAX_REQUEST_LINE_FONT1_LEN == 7 */
3053 max_xsize = 10; /* tools.c: MAX_REQUEST_LINE_FONT2_LEN == 10 */
3054 font_nr = FONT_TEXT_1;
3057 int max_word_len = 0;
3059 char *text_copy = getStringCopy(text);
3061 font_nr = FONT_TEXT_2;
3063 for (text_ptr = text; *text_ptr; text_ptr++)
3065 max_word_len = (*text_ptr != ' ' ? max_word_len + 1 : 0);
3067 if (max_word_len > 7) /* tools.c: MAX_REQUEST_LINE_FONT1_LEN == 7 */
3069 max_xsize = 10; /* tools.c: MAX_REQUEST_LINE_FONT2_LEN == 10 */
3070 font_nr = FONT_TEXT_1;
3079 for (text_ptr = text_copy; *text_ptr; text_ptr++)
3080 if (*text_ptr == ' ')
3085 dDX = SX + (SXSIZE - DXSIZE) / 2 - DX;
3086 dDY = SY + (SYSIZE - DYSIZE) / 2 - DY;
3088 dDX = SX + SXSIZE / 2 - max_xsize * font_width / 2 - DX;
3089 dDY = SY + SYSIZE / 2 - max_ysize * font_height / 2 - DY;
3092 for (x = xstart, y = ystart; x <= xend && y <= yend; x += xstep, y += ystep)
3094 int xsize = (action == ACTION_CLOSING ? xend - (x - xstart) : x) + 2;
3095 int ysize = (action == ACTION_CLOSING ? yend - (y - ystart) : y) + 2;
3096 int sx = SX + (SXSIZE - xsize * font_width) / 2;
3097 // int sy = SX + (SYSIZE - ysize * font_height) / 2;
3098 int sy = SY + (SYSIZE - ysize * (font_height + line_spacing)) / 2;
3102 BlitBitmap(bitmap_db_store, backbuffer, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
3104 SetDrawtoField(DRAW_BUFFERED);
3107 BlitScreenToBitmap(backbuffer);
3109 BlitBitmap(fieldbuffer, backbuffer, FX, FY, SXSIZE, SYSIZE, SX, SY);
3112 SetDrawtoField(DRAW_BACKBUFFER);
3115 for (yy = 0; yy < ysize; yy++)
3116 for (xx = 0; xx < xsize; xx++)
3117 DrawEnvelopeBackgroundTiles(graphic, sx, sy, xx, yy, xsize, ysize,
3118 getFontWidth(font_nr),
3119 getFontHeight(font_nr) + line_spacing);
3124 DrawTextBuffer(sx + font_width, sy + font_height + 8,
3125 text_copy, font_nr, max_xsize,
3126 xsize - 2, ysize - 2, line_spacing, mask_mode,
3127 FALSE, TRUE, FALSE);
3129 DrawTextBuffer(sx + font_width, sy + font_height,
3130 level.envelope[envelope_nr].text, font_nr, max_xsize,
3131 xsize - 2, ysize - 2, 0, mask_mode,
3132 level.envelope[envelope_nr].autowrap,
3133 level.envelope[envelope_nr].centered, FALSE);
3137 DrawTextToTextArea(sx + font_width, sy + font_height,
3138 level.envelope[envelope_nr].text, font_nr, max_xsize,
3139 xsize - 2, ysize - 2, mask_mode);
3142 /* copy request gadgets to door backbuffer */
3145 if ((ysize - 2) > 13)
3146 BlitBitmap(bitmap_db_door, drawto,
3147 DOOR_GFX_PAGEX1 + (DXSIZE - (xsize - 2) * font_width) / 2,
3148 DOOR_GFX_PAGEY1 + 13 * font_height,
3149 (xsize - 2) * font_width,
3150 (ysize - 2 - 13) * font_height,
3152 sy + font_height * (1 + 13));
3154 if ((ysize - 2) > 13)
3155 BlitBitmap(bitmap_db_door, drawto,
3156 DOOR_GFX_PAGEX1 + (DXSIZE - (xsize - 2) * font_width) / 2,
3157 DOOR_GFX_PAGEY1 + 11 * (font_height + line_spacing * 0),
3158 (xsize - 2) * font_width,
3159 (ysize - 2 - 13) * (font_height + line_spacing),
3161 sy + (font_height + line_spacing) * (1 + 13));
3163 if ((ysize - 2) > 13)
3164 BlitBitmap(bitmap_db_door, drawto,
3165 DOOR_GFX_PAGEX1 + (DXSIZE - (xsize - 2) * font_width) / 2,
3166 DOOR_GFX_PAGEY1 + 13 * font_height,
3167 (xsize - 2) * font_width,
3168 (ysize - 2 - 13) * font_height,
3170 sy + font_height * (1 + 13));
3174 redraw_mask = REDRAW_FIELD | REDRAW_FROM_BACKBUFFER;
3175 // redraw_mask |= REDRAW_ALL | REDRAW_FROM_BACKBUFFER;
3177 redraw_mask |= REDRAW_FIELD | REDRAW_FROM_BACKBUFFER;
3187 WaitUntilDelayReached(&anim_delay, anim_delay_value / 2);
3197 void ShowEnvelopeRequest(char *text, unsigned int req_state, int action)
3200 int last_game_status = game_status; /* save current game status */
3201 // int last_draw_background_mask = gfx.draw_background_mask;
3204 int graphic = IMG_BACKGROUND_REQUEST;
3205 int sound_opening = SND_REQUEST_OPENING;
3206 int sound_closing = SND_REQUEST_CLOSING;
3208 int envelope_nr = 0;
3209 int element = EL_ENVELOPE_1 + envelope_nr;
3210 int graphic = IMG_BACKGROUND_ENVELOPE_1 + envelope_nr;
3211 int sound_opening = element_info[element].sound[ACTION_OPENING];
3212 int sound_closing = element_info[element].sound[ACTION_CLOSING];
3215 boolean ffwd_delay = (tape.playing && tape.fast_forward);
3216 boolean no_delay = (tape.warp_forward);
3217 int normal_delay_value = ONE_SECOND_DELAY / (ffwd_delay ? 2 : 1);
3218 int wait_delay_value = (no_delay ? 0 : normal_delay_value);
3220 int anim_mode = graphic_info[graphic].anim_mode;
3221 int main_anim_mode = (anim_mode == ANIM_NONE ? ANIM_VERTICAL|ANIM_HORIZONTAL:
3222 anim_mode == ANIM_DEFAULT ? ANIM_VERTICAL : anim_mode);
3224 char *text_copy = getStringCopy(text);
3227 for (text_ptr = text_copy; *text_ptr; text_ptr++)
3228 if (*text_ptr == ' ')
3233 if (game_status == GAME_MODE_PLAYING)
3235 if (level.game_engine_type == GAME_ENGINE_TYPE_EM)
3236 BlitScreenToBitmap_EM(backbuffer);
3237 else if (level.game_engine_type == GAME_ENGINE_TYPE_SP)
3238 BlitScreenToBitmap_SP(backbuffer);
3241 BlitBitmap(fieldbuffer, backbuffer, FX, FY, SXSIZE, SYSIZE, SX, SY);
3245 SetDrawtoField(DRAW_BACKBUFFER);
3247 // SetDrawBackgroundMask(REDRAW_NONE);
3249 if (action == ACTION_OPENING)
3251 BlitBitmap(backbuffer, bitmap_db_store, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
3254 if (req_state & REQ_ASK)
3256 MapGadget(tool_gadget[TOOL_CTRL_ID_YES]);
3257 MapGadget(tool_gadget[TOOL_CTRL_ID_NO]);
3259 else if (req_state & REQ_CONFIRM)
3261 MapGadget(tool_gadget[TOOL_CTRL_ID_CONFIRM]);
3263 else if (req_state & REQ_PLAYER)
3265 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_1]);
3266 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_2]);
3267 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_3]);
3268 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_4]);
3273 DrawEnvelopeRequest(text);
3275 DrawEnvelopeRequest(text_copy);
3278 if (game_status != GAME_MODE_MAIN)
3282 /* force DOOR font inside door area */
3283 game_status = GAME_MODE_PSEUDO_DOOR;
3286 game.envelope_active = TRUE; /* needed for RedrawPlayfield() events */
3288 if (action == ACTION_OPENING)
3290 PlayMenuSoundStereo(sound_opening, SOUND_MIDDLE);
3292 if (anim_mode == ANIM_DEFAULT)
3293 AnimateEnvelopeRequest(ANIM_DEFAULT, ACTION_OPENING);
3295 AnimateEnvelopeRequest(main_anim_mode, ACTION_OPENING);
3299 Delay(wait_delay_value);
3301 WaitForEventToContinue();
3306 PlayMenuSoundStereo(sound_closing, SOUND_MIDDLE);
3308 if (anim_mode != ANIM_NONE)
3309 AnimateEnvelopeRequest(main_anim_mode, ACTION_CLOSING);
3311 if (anim_mode == ANIM_DEFAULT)
3312 AnimateEnvelopeRequest(ANIM_DEFAULT, ACTION_CLOSING);
3315 game.envelope_active = FALSE;
3318 // game_status = last_game_status; /* restore current game status */
3320 if (action == ACTION_CLOSING)
3322 if (game_status != GAME_MODE_MAIN)
3325 BlitBitmap(bitmap_db_store, backbuffer, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
3328 SetDrawtoField(DRAW_BUFFERED);
3331 // SetDrawBackgroundMask(last_draw_background_mask);
3334 redraw_mask = REDRAW_FIELD;
3335 // redraw_mask |= REDRAW_ALL;
3337 redraw_mask |= REDRAW_FIELD;
3341 if (game_status == GAME_MODE_MAIN)
3346 /* (important: after "BackToFront()", but before "SetDrawtoField()") */
3347 game_status = last_game_status; /* restore current game status */
3350 if (action == ACTION_CLOSING &&
3351 game_status == GAME_MODE_PLAYING &&
3352 level.game_engine_type == GAME_ENGINE_TYPE_RND)
3353 SetDrawtoField(DRAW_BUFFERED);
3355 if (game_status == GAME_MODE_PLAYING &&
3356 level.game_engine_type == GAME_ENGINE_TYPE_RND)
3357 SetDrawtoField(DRAW_BUFFERED);
3369 void DrawPreviewElement(int dst_x, int dst_y, int element, int tilesize)
3373 int graphic = el2preimg(element);
3375 getSizedGraphicSource(graphic, 0, tilesize, &src_bitmap, &src_x, &src_y);
3376 BlitBitmap(src_bitmap, drawto, src_x, src_y, tilesize, tilesize, dst_x,dst_y);
3384 SetMainBackgroundImage(IMG_BACKGROUND_PLAYING);
3385 SetDrawBackgroundMask(REDRAW_FIELD);
3387 SetDrawBackgroundMask(REDRAW_NONE);
3392 for (x = BX1; x <= BX2; x++)
3393 for (y = BY1; y <= BY2; y++)
3394 DrawScreenField(x, y);
3396 redraw_mask |= REDRAW_FIELD;
3399 void DrawMiniLevel(int size_x, int size_y, int scroll_x, int scroll_y)
3403 for (x = 0; x < size_x; x++)
3404 for (y = 0; y < size_y; y++)
3405 DrawMiniElementOrWall(x, y, scroll_x, scroll_y);
3407 redraw_mask |= REDRAW_FIELD;
3410 static void DrawPreviewLevelPlayfieldExt(int from_x, int from_y)
3412 boolean show_level_border = (BorderElement != EL_EMPTY);
3413 int level_xsize = lev_fieldx + (show_level_border ? 2 : 0);
3414 int level_ysize = lev_fieldy + (show_level_border ? 2 : 0);
3415 int tile_size = preview.tile_size;
3416 int preview_width = preview.xsize * tile_size;
3417 int preview_height = preview.ysize * tile_size;
3418 int real_preview_xsize = MIN(level_xsize, preview.xsize);
3419 int real_preview_ysize = MIN(level_ysize, preview.ysize);
3420 int real_preview_width = real_preview_xsize * tile_size;
3421 int real_preview_height = real_preview_ysize * tile_size;
3422 int dst_x = SX + ALIGNED_XPOS(preview.x, preview_width, preview.align);
3423 int dst_y = SY + ALIGNED_YPOS(preview.y, preview_height, preview.valign);
3427 if (!IN_GFX_FIELD_FULL(dst_x, dst_y + preview_height - 1))
3432 dst_x += (preview_width - real_preview_width) / 2;
3433 dst_y += (preview_height - real_preview_height) / 2;
3435 DrawBackground(dst_x, dst_y, real_preview_width, real_preview_height);
3437 DrawBackground(dst_x, dst_y, preview_width, preview_height);
3439 dst_x += (preview_width - real_preview_width) / 2;
3440 dst_y += (preview_height - real_preview_height) / 2;
3443 for (x = 0; x < real_preview_xsize; x++)
3445 for (y = 0; y < real_preview_ysize; y++)
3447 int lx = from_x + x + (show_level_border ? -1 : 0);
3448 int ly = from_y + y + (show_level_border ? -1 : 0);
3449 int element = (IN_LEV_FIELD(lx, ly) ? level.field[lx][ly] :
3450 getBorderElement(lx, ly));
3452 DrawPreviewElement(dst_x + x * tile_size, dst_y + y * tile_size,
3453 element, tile_size);
3457 redraw_mask |= REDRAW_MICROLEVEL;
3460 #define MICROLABEL_EMPTY 0
3461 #define MICROLABEL_LEVEL_NAME 1
3462 #define MICROLABEL_LEVEL_AUTHOR_HEAD 2
3463 #define MICROLABEL_LEVEL_AUTHOR 3
3464 #define MICROLABEL_IMPORTED_FROM_HEAD 4
3465 #define MICROLABEL_IMPORTED_FROM 5
3466 #define MICROLABEL_IMPORTED_BY_HEAD 6
3467 #define MICROLABEL_IMPORTED_BY 7
3469 static int getMaxTextLength(struct TextPosInfo *pos, int font_nr)
3471 int max_text_width = SXSIZE;
3472 int font_width = getFontWidth(font_nr);
3474 if (pos->align == ALIGN_CENTER)
3475 max_text_width = (pos->x < SXSIZE / 2 ? pos->x * 2 : (SXSIZE - pos->x) * 2);
3476 else if (pos->align == ALIGN_RIGHT)
3477 max_text_width = pos->x;
3479 max_text_width = SXSIZE - pos->x;
3481 return max_text_width / font_width;
3484 static void DrawPreviewLevelLabelExt(int mode)
3486 struct TextPosInfo *pos = &menu.main.text.level_info_2;
3487 char label_text[MAX_OUTPUT_LINESIZE + 1];
3488 int max_len_label_text;
3490 int font_nr = pos->font;
3493 if (!IN_GFX_FIELD_FULL(pos->x, pos->y + getFontHeight(pos->font)))
3496 if (mode == MICROLABEL_LEVEL_AUTHOR_HEAD ||
3497 mode == MICROLABEL_IMPORTED_FROM_HEAD ||
3498 mode == MICROLABEL_IMPORTED_BY_HEAD)
3499 font_nr = pos->font_alt;
3501 int font_nr = FONT_TEXT_2;
3504 if (mode == MICROLABEL_LEVEL_AUTHOR_HEAD ||
3505 mode == MICROLABEL_IMPORTED_FROM_HEAD ||
3506 mode == MICROLABEL_IMPORTED_BY_HEAD)
3507 font_nr = FONT_TEXT_3;
3511 max_len_label_text = getMaxTextLength(pos, font_nr);
3513 max_len_label_text = SXSIZE / getFontWidth(font_nr);
3517 if (pos->size != -1)
3518 max_len_label_text = pos->size;
3521 for (i = 0; i < max_len_label_text; i++)
3522 label_text[i] = ' ';
3523 label_text[max_len_label_text] = '\0';
3525 if (strlen(label_text) > 0)
3528 DrawTextSAligned(pos->x, pos->y, label_text, font_nr, pos->align);
3530 int lxpos = SX + (SXSIZE - getTextWidth(label_text, font_nr)) / 2;
3531 int lypos = MICROLABEL2_YPOS;
3533 DrawText(lxpos, lypos, label_text, font_nr);
3538 (mode == MICROLABEL_LEVEL_NAME ? level.name :
3539 mode == MICROLABEL_LEVEL_AUTHOR_HEAD ? "created by" :
3540 mode == MICROLABEL_LEVEL_AUTHOR ? level.author :
3541 mode == MICROLABEL_IMPORTED_FROM_HEAD ? "imported from" :
3542 mode == MICROLABEL_IMPORTED_FROM ? leveldir_current->imported_from :
3543 mode == MICROLABEL_IMPORTED_BY_HEAD ? "imported by" :
3544 mode == MICROLABEL_IMPORTED_BY ? leveldir_current->imported_by :""),
3545 max_len_label_text);
3546 label_text[max_len_label_text] = '\0';
3548 if (strlen(label_text) > 0)
3551 DrawTextSAligned(pos->x, pos->y, label_text, font_nr, pos->align);
3553 int lxpos = SX + (SXSIZE - getTextWidth(label_text, font_nr)) / 2;
3554 int lypos = MICROLABEL2_YPOS;
3556 DrawText(lxpos, lypos, label_text, font_nr);
3560 redraw_mask |= REDRAW_MICROLEVEL;
3563 static void DrawPreviewLevelExt(boolean restart)
3565 static unsigned int scroll_delay = 0;
3566 static unsigned int label_delay = 0;
3567 static int from_x, from_y, scroll_direction;
3568 static int label_state, label_counter;
3569 unsigned int scroll_delay_value = preview.step_delay;
3570 boolean show_level_border = (BorderElement != EL_EMPTY);
3571 int level_xsize = lev_fieldx + (show_level_border ? 2 : 0);
3572 int level_ysize = lev_fieldy + (show_level_border ? 2 : 0);
3573 int last_game_status = game_status; /* save current game status */
3576 /* force PREVIEW font on preview level */
3577 game_status = GAME_MODE_PSEUDO_PREVIEW;
3585 if (preview.anim_mode == ANIM_CENTERED)
3587 if (level_xsize > preview.xsize)
3588 from_x = (level_xsize - preview.xsize) / 2;
3589 if (level_ysize > preview.ysize)
3590 from_y = (level_ysize - preview.ysize) / 2;
3593 from_x += preview.xoffset;
3594 from_y += preview.yoffset;
3596 scroll_direction = MV_RIGHT;
3600 DrawPreviewLevelPlayfieldExt(from_x, from_y);
3601 DrawPreviewLevelLabelExt(label_state);
3603 /* initialize delay counters */
3604 DelayReached(&scroll_delay, 0);
3605 DelayReached(&label_delay, 0);
3607 if (leveldir_current->name)
3609 struct TextPosInfo *pos = &menu.main.text.level_info_1;
3610 char label_text[MAX_OUTPUT_LINESIZE + 1];
3612 int font_nr = pos->font;
3614 int font_nr = FONT_TEXT_1;
3617 int max_len_label_text = getMaxTextLength(pos, font_nr);
3619 int max_len_label_text = SXSIZE / getFontWidth(font_nr);
3627 if (pos->size != -1)
3628 max_len_label_text = pos->size;
3631 strncpy(label_text, leveldir_current->name, max_len_label_text);
3632 label_text[max_len_label_text] = '\0';
3635 if (IN_GFX_FIELD_FULL(pos->x, pos->y + getFontHeight(pos->font)))
3636 DrawTextSAligned(pos->x, pos->y, label_text, font_nr, pos->align);
3638 lxpos = SX + (SXSIZE - getTextWidth(label_text, font_nr)) / 2;
3639 lypos = SY + MICROLABEL1_YPOS;
3641 DrawText(lxpos, lypos, label_text, font_nr);
3645 game_status = last_game_status; /* restore current game status */
3650 /* scroll preview level, if needed */
3651 if (preview.anim_mode != ANIM_NONE &&
3652 (level_xsize > preview.xsize || level_ysize > preview.ysize) &&
3653 DelayReached(&scroll_delay, scroll_delay_value))
3655 switch (scroll_direction)
3660 from_x -= preview.step_offset;
3661 from_x = (from_x < 0 ? 0 : from_x);
3664 scroll_direction = MV_UP;
3668 if (from_x < level_xsize - preview.xsize)
3670 from_x += preview.step_offset;
3671 from_x = (from_x > level_xsize - preview.xsize ?
3672 level_xsize - preview.xsize : from_x);
3675 scroll_direction = MV_DOWN;
3681 from_y -= preview.step_offset;
3682 from_y = (from_y < 0 ? 0 : from_y);
3685 scroll_direction = MV_RIGHT;
3689 if (from_y < level_ysize - preview.ysize)
3691 from_y += preview.step_offset;
3692 from_y = (from_y > level_ysize - preview.ysize ?
3693 level_ysize - preview.ysize : from_y);
3696 scroll_direction = MV_LEFT;
3703 DrawPreviewLevelPlayfieldExt(from_x, from_y);
3706 /* !!! THIS ALL SUCKS -- SHOULD BE CLEANLY REWRITTEN !!! */
3707 /* redraw micro level label, if needed */
3708 if (!strEqual(level.name, NAMELESS_LEVEL_NAME) &&
3709 !strEqual(level.author, ANONYMOUS_NAME) &&
3710 !strEqual(level.author, leveldir_current->name) &&
3711 DelayReached(&label_delay, MICROLEVEL_LABEL_DELAY))
3713 int max_label_counter = 23;
3715 if (leveldir_current->imported_from != NULL &&
3716 strlen(leveldir_current->imported_from) > 0)
3717 max_label_counter += 14;
3718 if (leveldir_current->imported_by != NULL &&
3719 strlen(leveldir_current->imported_by) > 0)
3720 max_label_counter += 14;
3722 label_counter = (label_counter + 1) % max_label_counter;
3723 label_state = (label_counter >= 0 && label_counter <= 7 ?
3724 MICROLABEL_LEVEL_NAME :
3725 label_counter >= 9 && label_counter <= 12 ?
3726 MICROLABEL_LEVEL_AUTHOR_HEAD :
3727 label_counter >= 14 && label_counter <= 21 ?
3728 MICROLABEL_LEVEL_AUTHOR :
3729 label_counter >= 23 && label_counter <= 26 ?
3730 MICROLABEL_IMPORTED_FROM_HEAD :
3731 label_counter >= 28 && label_counter <= 35 ?
3732 MICROLABEL_IMPORTED_FROM :
3733 label_counter >= 37 && label_counter <= 40 ?
3734 MICROLABEL_IMPORTED_BY_HEAD :
3735 label_counter >= 42 && label_counter <= 49 ?
3736 MICROLABEL_IMPORTED_BY : MICROLABEL_EMPTY);
3738 if (leveldir_current->imported_from == NULL &&
3739 (label_state == MICROLABEL_IMPORTED_FROM_HEAD ||
3740 label_state == MICROLABEL_IMPORTED_FROM))
3741 label_state = (label_state == MICROLABEL_IMPORTED_FROM_HEAD ?
3742 MICROLABEL_IMPORTED_BY_HEAD : MICROLABEL_IMPORTED_BY);
3744 DrawPreviewLevelLabelExt(label_state);
3747 game_status = last_game_status; /* restore current game status */
3750 void DrawPreviewLevelInitial()
3752 DrawPreviewLevelExt(TRUE);
3755 void DrawPreviewLevelAnimation()
3757 DrawPreviewLevelExt(FALSE);
3760 inline void DrawGraphicAnimationExt(DrawBuffer *dst_bitmap, int x, int y,
3761 int graphic, int sync_frame, int mask_mode)
3763 int frame = getGraphicAnimationFrame(graphic, sync_frame);
3765 if (mask_mode == USE_MASKING)
3766 DrawGraphicThruMaskExt(dst_bitmap, x, y, graphic, frame);
3768 DrawGraphicExt(dst_bitmap, x, y, graphic, frame);
3771 inline void DrawFixedGraphicAnimationExt(DrawBuffer *dst_bitmap, int x, int y,
3772 int graphic, int sync_frame,
3775 int frame = getGraphicAnimationFrame(graphic, sync_frame);
3777 if (mask_mode == USE_MASKING)
3778 DrawFixedGraphicThruMaskExt(dst_bitmap, x, y, graphic, frame);
3780 DrawFixedGraphicExt(dst_bitmap, x, y, graphic, frame);
3783 inline void DrawGraphicAnimation(int x, int y, int graphic)
3785 int lx = LEVELX(x), ly = LEVELY(y);
3787 if (!IN_SCR_FIELD(x, y))
3791 DrawGraphicAnimationExt(drawto_field, FX + x * TILEX_VAR, FY + y * TILEY_VAR,
3792 graphic, GfxFrame[lx][ly], NO_MASKING);
3794 DrawGraphicAnimationExt(drawto_field, FX + x * TILEX, FY + y * TILEY,
3795 graphic, GfxFrame[lx][ly], NO_MASKING);
3797 MarkTileDirty(x, y);
3800 inline void DrawFixedGraphicAnimation(int x, int y, int graphic)
3802 int lx = LEVELX(x), ly = LEVELY(y);
3804 if (!IN_SCR_FIELD(x, y))
3807 DrawGraphicAnimationExt(drawto_field, FX + x * TILEX, FY + y * TILEY,
3808 graphic, GfxFrame[lx][ly], NO_MASKING);
3809 MarkTileDirty(x, y);
3812 void DrawLevelGraphicAnimation(int x, int y, int graphic)
3814 DrawGraphicAnimation(SCREENX(x), SCREENY(y), graphic);
3817 void DrawLevelElementAnimation(int x, int y, int element)
3819 int graphic = el_act_dir2img(element, GfxAction[x][y], GfxDir[x][y]);
3821 DrawGraphicAnimation(SCREENX(x), SCREENY(y), graphic);
3824 inline void DrawLevelGraphicAnimationIfNeeded(int x, int y, int graphic)
3826 int sx = SCREENX(x), sy = SCREENY(y);
3828 if (!IN_LEV_FIELD(x, y) || !IN_SCR_FIELD(sx, sy))
3831 if (!IS_NEW_FRAME(GfxFrame[x][y], graphic))
3834 DrawGraphicAnimation(sx, sy, graphic);
3837 if (GFX_CRUMBLED(TILE_GFX_ELEMENT(x, y)))
3838 DrawLevelFieldCrumbled(x, y);
3840 if (GFX_CRUMBLED(Feld[x][y]))
3841 DrawLevelFieldCrumbled(x, y);
3845 void DrawLevelElementAnimationIfNeeded(int x, int y, int element)
3847 int sx = SCREENX(x), sy = SCREENY(y);
3850 if (!IN_LEV_FIELD(x, y) || !IN_SCR_FIELD(sx, sy))
3853 graphic = el_act_dir2img(element, GfxAction[x][y], GfxDir[x][y]);
3855 if (!IS_NEW_FRAME(GfxFrame[x][y], graphic))
3858 DrawGraphicAnimation(sx, sy, graphic);
3860 if (GFX_CRUMBLED(element))
3861 DrawLevelFieldCrumbled(x, y);
3864 static int getPlayerGraphic(struct PlayerInfo *player, int move_dir)
3866 if (player->use_murphy)
3868 /* this works only because currently only one player can be "murphy" ... */
3869 static int last_horizontal_dir = MV_LEFT;
3870 int graphic = el_act_dir2img(EL_SP_MURPHY, player->GfxAction, move_dir);
3872 if (move_dir == MV_LEFT || move_dir == MV_RIGHT)
3873 last_horizontal_dir = move_dir;
3875 if (graphic == IMG_SP_MURPHY) /* undefined => use special graphic */
3877 int direction = (player->is_snapping ? move_dir : last_horizontal_dir);
3879 graphic = el_act_dir2img(EL_SP_MURPHY, player->GfxAction, direction);
3885 return el_act_dir2img(player->artwork_element, player->GfxAction,move_dir);
3888 static boolean equalGraphics(int graphic1, int graphic2)
3890 struct GraphicInfo *g1 = &graphic_info[graphic1];
3891 struct GraphicInfo *g2 = &graphic_info[graphic2];
3893 return (g1->bitmap == g2->bitmap &&
3894 g1->src_x == g2->src_x &&
3895 g1->src_y == g2->src_y &&
3896 g1->anim_frames == g2->anim_frames &&
3897 g1->anim_delay == g2->anim_delay &&
3898 g1->anim_mode == g2->anim_mode);
3901 void DrawAllPlayers()
3905 for (i = 0; i < MAX_PLAYERS; i++)
3906 if (stored_player[i].active)
3907 DrawPlayer(&stored_player[i]);
3910 void DrawPlayerField(int x, int y)
3912 if (!IS_PLAYER(x, y))
3915 DrawPlayer(PLAYERINFO(x, y));
3918 #define DRAW_PLAYER_OVER_PUSHED_ELEMENT 1
3920 void DrawPlayer(struct PlayerInfo *player)
3922 int jx = player->jx;
3923 int jy = player->jy;
3924 int move_dir = player->MovDir;
3925 int dx = (move_dir == MV_LEFT ? -1 : move_dir == MV_RIGHT ? +1 : 0);
3926 int dy = (move_dir == MV_UP ? -1 : move_dir == MV_DOWN ? +1 : 0);
3927 int last_jx = (player->is_moving ? jx - dx : jx);
3928 int last_jy = (player->is_moving ? jy - dy : jy);
3929 int next_jx = jx + dx;
3930 int next_jy = jy + dy;
3931 boolean player_is_moving = (player->MovPos ? TRUE : FALSE);
3932 boolean player_is_opaque = FALSE;
3933 int sx = SCREENX(jx), sy = SCREENY(jy);
3934 int sxx = 0, syy = 0;
3935 int element = Feld[jx][jy], last_element = Feld[last_jx][last_jy];
3937 int action = ACTION_DEFAULT;
3938 int last_player_graphic = getPlayerGraphic(player, move_dir);
3939 int last_player_frame = player->Frame;
3942 /* GfxElement[][] is set to the element the player is digging or collecting;
3943 remove also for off-screen player if the player is not moving anymore */
3944 if (IN_LEV_FIELD(jx, jy) && !player_is_moving)
3945 GfxElement[jx][jy] = EL_UNDEFINED;
3947 if (!player->active || !IN_SCR_FIELD(SCREENX(last_jx), SCREENY(last_jy)))
3951 if (!IN_LEV_FIELD(jx, jy))
3953 printf("DrawPlayerField(): x = %d, y = %d\n",jx,jy);
3954 printf("DrawPlayerField(): sx = %d, sy = %d\n",sx,sy);
3955 printf("DrawPlayerField(): This should never happen!\n");
3960 if (element == EL_EXPLOSION)
3963 action = (player->is_pushing ? ACTION_PUSHING :
3964 player->is_digging ? ACTION_DIGGING :
3965 player->is_collecting ? ACTION_COLLECTING :
3966 player->is_moving ? ACTION_MOVING :
3967 player->is_snapping ? ACTION_SNAPPING :
3968 player->is_dropping ? ACTION_DROPPING :
3969 player->is_waiting ? player->action_waiting : ACTION_DEFAULT);
3971 if (player->is_waiting)
3972 move_dir = player->dir_waiting;
3974 InitPlayerGfxAnimation(player, action, move_dir);
3976 /* ----------------------------------------------------------------------- */
3977 /* draw things in the field the player is leaving, if needed */
3978 /* ----------------------------------------------------------------------- */
3980 if (player->is_moving)
3982 if (Back[last_jx][last_jy] && IS_DRAWABLE(last_element))
3984 DrawLevelElement(last_jx, last_jy, Back[last_jx][last_jy]);
3986 if (last_element == EL_DYNAMITE_ACTIVE ||
3987 last_element == EL_EM_DYNAMITE_ACTIVE ||
3988 last_element == EL_SP_DISK_RED_ACTIVE)
3989 DrawDynamite(last_jx, last_jy);
3991 DrawLevelFieldThruMask(last_jx, last_jy);
3993 else if (last_element == EL_DYNAMITE_ACTIVE ||
3994 last_element == EL_EM_DYNAMITE_ACTIVE ||
3995 last_element == EL_SP_DISK_RED_ACTIVE)
3996 DrawDynamite(last_jx, last_jy);
3998 /* !!! this is not enough to prevent flickering of players which are
3999 moving next to each others without a free tile between them -- this
4000 can only be solved by drawing all players layer by layer (first the
4001 background, then the foreground etc.) !!! => TODO */
4002 else if (!IS_PLAYER(last_jx, last_jy))
4003 DrawLevelField(last_jx, last_jy);
4006 DrawLevelField(last_jx, last_jy);
4009 if (player->is_pushing && IN_SCR_FIELD(SCREENX(next_jx), SCREENY(next_jy)))
4010 DrawLevelElement(next_jx, next_jy, EL_EMPTY);
4013 if (!IN_SCR_FIELD(sx, sy))
4016 /* ----------------------------------------------------------------------- */
4017 /* draw things behind the player, if needed */
4018 /* ----------------------------------------------------------------------- */
4021 DrawLevelElement(jx, jy, Back[jx][jy]);
4022 else if (IS_ACTIVE_BOMB(element))
4023 DrawLevelElement(jx, jy, EL_EMPTY);
4026 if (player_is_moving && GfxElement[jx][jy] != EL_UNDEFINED)
4028 int old_element = GfxElement[jx][jy];
4029 int old_graphic = el_act_dir2img(old_element, action, move_dir);
4030 int frame = getGraphicAnimationFrame(old_graphic, player->StepFrame);
4032 if (GFX_CRUMBLED(old_element))
4033 DrawLevelFieldCrumbledDigging(jx, jy, move_dir, player->StepFrame);
4035 DrawGraphic(sx, sy, old_graphic, frame);
4037 if (graphic_info[old_graphic].anim_mode & ANIM_OPAQUE_PLAYER)
4038 player_is_opaque = TRUE;
4042 GfxElement[jx][jy] = EL_UNDEFINED;
4044 /* make sure that pushed elements are drawn with correct frame rate */
4046 graphic = el_act_dir2img(element, ACTION_PUSHING, move_dir);
4048 if (player->is_pushing && player->is_moving && !IS_ANIM_MODE_CE(graphic))
4049 GfxFrame[jx][jy] = player->StepFrame;
4051 if (player->is_pushing && player->is_moving)
4052 GfxFrame[jx][jy] = player->StepFrame;
4055 DrawLevelField(jx, jy);
4059 #if !DRAW_PLAYER_OVER_PUSHED_ELEMENT
4060 /* ----------------------------------------------------------------------- */
4061 /* draw player himself */
4062 /* ----------------------------------------------------------------------- */
4064 graphic = getPlayerGraphic(player, move_dir);
4066 /* in the case of changed player action or direction, prevent the current
4067 animation frame from being restarted for identical animations */
4068 if (player->Frame == 0 && equalGraphics(graphic, last_player_graphic))
4069 player->Frame = last_player_frame;
4071 frame = getGraphicAnimationFrame(graphic, player->Frame);
4075 if (move_dir == MV_LEFT || move_dir == MV_RIGHT)
4076 sxx = player->GfxPos;
4078 syy = player->GfxPos;
4081 if (!setup.soft_scrolling && ScreenMovPos)
4084 if (player_is_opaque)
4085 DrawGraphicShifted(sx, sy, sxx, syy, graphic, frame,NO_CUTTING,NO_MASKING);
4087 DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, frame, NO_CUTTING);
4089 if (SHIELD_ON(player))
4091 int graphic = (player->shield_deadly_time_left ? IMG_SHIELD_DEADLY_ACTIVE :
4092 IMG_SHIELD_NORMAL_ACTIVE);
4093 int frame = getGraphicAnimationFrame(graphic, -1);
4095 DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, frame, NO_CUTTING);
4099 #if DRAW_PLAYER_OVER_PUSHED_ELEMENT
4102 if (move_dir == MV_LEFT || move_dir == MV_RIGHT)
4103 sxx = player->GfxPos;
4105 syy = player->GfxPos;
4109 /* ----------------------------------------------------------------------- */
4110 /* draw things the player is pushing, if needed */
4111 /* ----------------------------------------------------------------------- */
4114 printf("::: %d, %d [%d, %d] [%d]\n",
4115 player->is_pushing, player_is_moving, player->GfxAction,
4116 player->is_moving, player_is_moving);
4120 if (player->is_pushing && player->is_moving)
4122 int px = SCREENX(jx), py = SCREENY(jy);
4123 int pxx = (TILEX - ABS(sxx)) * dx;
4124 int pyy = (TILEY - ABS(syy)) * dy;
4125 int gfx_frame = GfxFrame[jx][jy];
4131 if (!IS_MOVING(jx, jy)) /* push movement already finished */
4133 element = Feld[next_jx][next_jy];
4134 gfx_frame = GfxFrame[next_jx][next_jy];
4137 graphic = el_act_dir2img(element, ACTION_PUSHING, move_dir);
4140 sync_frame = (IS_ANIM_MODE_CE(graphic) ? gfx_frame : player->StepFrame);
4141 frame = getGraphicAnimationFrame(graphic, sync_frame);
4143 frame = getGraphicAnimationFrame(graphic, player->StepFrame);
4146 /* draw background element under pushed element (like the Sokoban field) */
4148 if (game.use_masked_pushing && IS_MOVING(jx, jy))
4150 /* this allows transparent pushing animation over non-black background */
4153 DrawLevelElement(jx, jy, Back[jx][jy]);
4155 DrawLevelElement(jx, jy, EL_EMPTY);
4157 if (Back[next_jx][next_jy])
4158 DrawLevelElement(next_jx, next_jy, Back[next_jx][next_jy]);
4160 DrawLevelElement(next_jx, next_jy, EL_EMPTY);
4162 else if (Back[next_jx][next_jy])
4163 DrawLevelElement(next_jx, next_jy, Back[next_jx][next_jy]);
4165 if (Back[next_jx][next_jy])
4166 DrawLevelElement(next_jx, next_jy, Back[next_jx][next_jy]);
4170 printf("::: %d, %d, %d, %d [%d] [%d, %d, %d] [%d] [%d, %d] [%d, %d]\n",
4171 jx, px, player->GfxPos, player->StepFrame,
4176 GfxFrame[jx][jy], GfxFrame[next_jx][next_jy]);
4180 /* do not draw (EM style) pushing animation when pushing is finished */
4181 /* (two-tile animations usually do not contain start and end frame) */
4182 if (graphic_info[graphic].double_movement && !IS_MOVING(jx, jy))
4183 DrawLevelElement(next_jx, next_jy, Feld[next_jx][next_jy]);
4185 DrawGraphicShiftedThruMask(px, py, pxx, pyy, graphic, frame, NO_CUTTING);
4187 /* masked drawing is needed for EMC style (double) movement graphics */
4188 /* !!! (ONLY WHEN DRAWING PUSHED ELEMENT OVER THE PLAYER) !!! */
4189 DrawGraphicShiftedThruMask(px, py, pxx, pyy, graphic, frame, NO_CUTTING);
4194 #if DRAW_PLAYER_OVER_PUSHED_ELEMENT
4195 /* ----------------------------------------------------------------------- */
4196 /* draw player himself */
4197 /* ----------------------------------------------------------------------- */
4199 graphic = getPlayerGraphic(player, move_dir);
4201 /* in the case of changed player action or direction, prevent the current
4202 animation frame from being restarted for identical animations */
4203 if (player->Frame == 0 && equalGraphics(graphic, last_player_graphic))
4204 player->Frame = last_player_frame;
4206 frame = getGraphicAnimationFrame(graphic, player->Frame);
4210 if (move_dir == MV_LEFT || move_dir == MV_RIGHT)
4211 sxx = player->GfxPos;
4213 syy = player->GfxPos;
4216 if (!setup.soft_scrolling && ScreenMovPos)
4219 if (player_is_opaque)
4220 DrawGraphicShifted(sx, sy, sxx, syy, graphic, frame,NO_CUTTING,NO_MASKING);
4222 DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, frame, NO_CUTTING);
4224 if (SHIELD_ON(player))
4226 int graphic = (player->shield_deadly_time_left ? IMG_SHIELD_DEADLY_ACTIVE :
4227 IMG_SHIELD_NORMAL_ACTIVE);
4228 int frame = getGraphicAnimationFrame(graphic, -1);
4230 DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, frame, NO_CUTTING);
4234 /* ----------------------------------------------------------------------- */
4235 /* draw things in front of player (active dynamite or dynabombs) */
4236 /* ----------------------------------------------------------------------- */
4238 if (IS_ACTIVE_BOMB(element))
4240 graphic = el2img(element);
4241 frame = getGraphicAnimationFrame(graphic, GfxFrame[jx][jy]);
4243 if (game.emulation == EMU_SUPAPLEX)
4244 DrawGraphic(sx, sy, IMG_SP_DISK_RED, frame);
4246 DrawGraphicThruMask(sx, sy, graphic, frame);
4249 if (player_is_moving && last_element == EL_EXPLOSION)
4251 int element = (GfxElement[last_jx][last_jy] != EL_UNDEFINED ?
4252 GfxElement[last_jx][last_jy] : EL_EMPTY);
4253 int graphic = el_act2img(element, ACTION_EXPLODING);
4254 int delay = (game.emulation == EMU_SUPAPLEX ? 3 : 2);
4255 int phase = ExplodePhase[last_jx][last_jy] - 1;
4256 int frame = getGraphicAnimationFrame(graphic, phase - delay);
4259 DrawGraphicThruMask(SCREENX(last_jx), SCREENY(last_jy), graphic, frame);
4262 /* ----------------------------------------------------------------------- */
4263 /* draw elements the player is just walking/passing through/under */
4264 /* ----------------------------------------------------------------------- */
4266 if (player_is_moving)
4268 /* handle the field the player is leaving ... */
4269 if (IS_ACCESSIBLE_INSIDE(last_element))
4270 DrawLevelField(last_jx, last_jy);
4271 else if (IS_ACCESSIBLE_UNDER(last_element))
4272 DrawLevelFieldThruMask(last_jx, last_jy);
4275 /* do not redraw accessible elements if the player is just pushing them */
4276 if (!player_is_moving || !player->is_pushing)
4278 /* ... and the field the player is entering */
4279 if (IS_ACCESSIBLE_INSIDE(element))
4280 DrawLevelField(jx, jy);
4281 else if (IS_ACCESSIBLE_UNDER(element))
4282 DrawLevelFieldThruMask(jx, jy);
4285 MarkTileDirty(sx, sy);
4288 /* ------------------------------------------------------------------------- */
4290 void WaitForEventToContinue()
4292 boolean still_wait = TRUE;
4294 /* simulate releasing mouse button over last gadget, if still pressed */
4296 HandleGadgets(-1, -1, 0);
4298 button_status = MB_RELEASED;
4314 case EVENT_BUTTONPRESS:
4315 case EVENT_KEYPRESS:
4319 case EVENT_KEYRELEASE:
4320 ClearPlayerAction();
4324 HandleOtherEvents(&event);
4328 else if (AnyJoystickButton() == JOY_BUTTON_NEW_PRESSED)
4335 /* don't eat all CPU time */
4340 #define MAX_REQUEST_LINES 13
4341 #define MAX_REQUEST_LINE_FONT1_LEN 7
4342 #define MAX_REQUEST_LINE_FONT2_LEN 10
4346 static int RequestHandleEvents(unsigned int req_state)
4348 int last_game_status = game_status; /* save current game status */
4352 button_status = MB_RELEASED;
4354 request_gadget_id = -1;
4367 case EVENT_BUTTONPRESS:
4368 case EVENT_BUTTONRELEASE:
4369 case EVENT_MOTIONNOTIFY:
4371 if (event.type == EVENT_MOTIONNOTIFY)
4373 if (!PointerInWindow(window))
4374 continue; /* window and pointer are on different screens */
4379 motion_status = TRUE;
4380 mx = ((MotionEvent *) &event)->x;
4381 my = ((MotionEvent *) &event)->y;
4385 motion_status = FALSE;
4386 mx = ((ButtonEvent *) &event)->x;
4387 my = ((ButtonEvent *) &event)->y;
4388 if (event.type == EVENT_BUTTONPRESS)
4389 button_status = ((ButtonEvent *) &event)->button;
4391 button_status = MB_RELEASED;
4394 /* this sets 'request_gadget_id' */
4395 HandleGadgets(mx, my, button_status);
4397 switch (request_gadget_id)
4399 case TOOL_CTRL_ID_YES:
4402 case TOOL_CTRL_ID_NO:
4405 case TOOL_CTRL_ID_CONFIRM:
4406 result = TRUE | FALSE;
4409 case TOOL_CTRL_ID_PLAYER_1:
4412 case TOOL_CTRL_ID_PLAYER_2:
4415 case TOOL_CTRL_ID_PLAYER_3:
4418 case TOOL_CTRL_ID_PLAYER_4:
4429 case EVENT_KEYPRESS:
4430 switch (GetEventKey((KeyEvent *)&event, TRUE))
4433 if (req_state & REQ_CONFIRM)
4442 #if defined(TARGET_SDL2)
4452 if (req_state & REQ_PLAYER)
4456 case EVENT_KEYRELEASE:
4457 ClearPlayerAction();
4461 HandleOtherEvents(&event);
4465 else if (AnyJoystickButton() == JOY_BUTTON_NEW_PRESSED)
4467 int joy = AnyJoystick();
4469 if (joy & JOY_BUTTON_1)
4471 else if (joy & JOY_BUTTON_2)
4477 if (game_status == GAME_MODE_PLAYING && local_player->LevelSolved_GameEnd)
4479 HandleGameActions();
4485 if (!PendingEvent()) /* delay only if no pending events */
4490 game_status = GAME_MODE_PSEUDO_DOOR;
4496 game_status = last_game_status; /* restore current game status */
4504 if (!PendingEvent()) /* delay only if no pending events */
4507 /* don't eat all CPU time */
4517 static boolean RequestDoor(char *text, unsigned int req_state)
4519 unsigned int old_door_state;
4520 int last_game_status = game_status; /* save current game status */
4521 int max_request_line_len = MAX_REQUEST_LINE_FONT1_LEN;
4522 int font_nr = FONT_TEXT_2;
4527 if (maxWordLengthInString(text) > MAX_REQUEST_LINE_FONT1_LEN)
4529 max_request_line_len = MAX_REQUEST_LINE_FONT2_LEN;
4530 font_nr = FONT_TEXT_1;
4533 if (game_status == GAME_MODE_PLAYING)
4535 if (level.game_engine_type == GAME_ENGINE_TYPE_EM)
4536 BlitScreenToBitmap_EM(backbuffer);
4537 else if (level.game_engine_type == GAME_ENGINE_TYPE_SP)
4538 BlitScreenToBitmap_SP(backbuffer);
4541 /* disable deactivated drawing when quick-loading level tape recording */
4542 if (tape.playing && tape.deactivate_display)
4543 TapeDeactivateDisplayOff(TRUE);
4545 SetMouseCursor(CURSOR_DEFAULT);
4547 #if defined(NETWORK_AVALIABLE)
4548 /* pause network game while waiting for request to answer */
4549 if (options.network &&
4550 game_status == GAME_MODE_PLAYING &&
4551 req_state & REQUEST_WAIT_FOR_INPUT)
4552 SendToServer_PausePlaying();
4555 old_door_state = GetDoorState();
4557 /* simulate releasing mouse button over last gadget, if still pressed */
4559 HandleGadgets(-1, -1, 0);
4563 /* draw released gadget before proceeding */
4566 if (old_door_state & DOOR_OPEN_1)
4568 CloseDoor(DOOR_CLOSE_1);
4570 /* save old door content */
4572 BlitBitmap(bitmap_db_door_1, bitmap_db_door_1,
4573 0 * DXSIZE, 0, DXSIZE, DYSIZE, 1 * DXSIZE, 0);
4575 BlitBitmap(bitmap_db_door, bitmap_db_door,
4576 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE,
4577 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1);
4581 SetDoorBackgroundImage(IMG_BACKGROUND_DOOR);
4582 SetDrawBackgroundMask(REDRAW_FIELD | REDRAW_DOOR_1);
4584 /* clear door drawing field */
4585 DrawBackground(DX, DY, DXSIZE, DYSIZE);
4587 /* force DOOR font inside door area */
4588 game_status = GAME_MODE_PSEUDO_DOOR;
4590 /* write text for request */
4591 for (text_ptr = text, ty = 0; ty < MAX_REQUEST_LINES; ty++)
4593 char text_line[max_request_line_len + 1];
4599 for (tl = 0, tx = 0; tx < max_request_line_len; tl++, tx++)
4601 tc = *(text_ptr + tx);
4602 // if (!tc || tc == ' ')
4603 if (!tc || tc == ' ' || tc == '?' || tc == '!')
4607 if ((tc == '?' || tc == '!') && tl == 0)
4617 strncpy(text_line, text_ptr, tl);
4620 DrawText(DX + (DXSIZE - tl * getFontWidth(font_nr)) / 2,
4621 DY + 8 + ty * (getFontHeight(font_nr) + 2),
4622 text_line, font_nr);
4624 text_ptr += tl + (tc == ' ' ? 1 : 0);
4625 // text_ptr += tl + (tc == ' ' || tc == '?' || tc == '!' ? 1 : 0);
4628 game_status = last_game_status; /* restore current game status */
4630 if (req_state & REQ_ASK)
4632 MapGadget(tool_gadget[TOOL_CTRL_ID_YES]);
4633 MapGadget(tool_gadget[TOOL_CTRL_ID_NO]);
4635 else if (req_state & REQ_CONFIRM)
4637 MapGadget(tool_gadget[TOOL_CTRL_ID_CONFIRM]);
4639 else if (req_state & REQ_PLAYER)
4641 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_1]);
4642 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_2]);
4643 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_3]);
4644 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_4]);
4647 /* copy request gadgets to door backbuffer */
4649 BlitBitmap(drawto, bitmap_db_door_1, DX, DY, DXSIZE, DYSIZE, 0, 0);
4651 BlitBitmap(drawto, bitmap_db_door,
4652 DX, DY, DXSIZE, DYSIZE,
4653 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
4656 OpenDoor(DOOR_OPEN_1);
4658 if (!(req_state & REQUEST_WAIT_FOR_INPUT))
4660 if (game_status == GAME_MODE_PLAYING)
4662 SetPanelBackground();
4663 SetDrawBackgroundMask(REDRAW_DOOR_1);
4667 SetDrawBackgroundMask(REDRAW_FIELD);
4673 if (game_status != GAME_MODE_MAIN)
4676 SetDrawBackgroundMask(REDRAW_FIELD | REDRAW_DOOR_1);
4678 // ---------- handle request buttons ----------
4679 result = RequestHandleEvents(req_state);
4681 if (game_status != GAME_MODE_MAIN)
4686 if (!(req_state & REQ_STAY_OPEN))
4688 CloseDoor(DOOR_CLOSE_1);
4690 if (((old_door_state & DOOR_OPEN_1) && !(req_state & REQ_STAY_CLOSED)) ||
4691 (req_state & REQ_REOPEN))
4692 OpenDoor(DOOR_OPEN_1 | DOOR_COPY_BACK);
4697 if (game_status == GAME_MODE_PLAYING)
4699 SetPanelBackground();
4700 SetDrawBackgroundMask(REDRAW_DOOR_1);
4704 SetDrawBackgroundMask(REDRAW_FIELD);
4707 #if defined(NETWORK_AVALIABLE)
4708 /* continue network game after request */
4709 if (options.network &&
4710 game_status == GAME_MODE_PLAYING &&
4711 req_state & REQUEST_WAIT_FOR_INPUT)
4712 SendToServer_ContinuePlaying();
4715 /* restore deactivated drawing when quick-loading level tape recording */
4716 if (tape.playing && tape.deactivate_display)
4717 TapeDeactivateDisplayOn();
4722 static boolean RequestEnvelope(char *text, unsigned int req_state)
4729 if (game_status == GAME_MODE_PLAYING)
4731 if (level.game_engine_type == GAME_ENGINE_TYPE_EM)
4732 BlitScreenToBitmap_EM(backbuffer);
4733 else if (level.game_engine_type == GAME_ENGINE_TYPE_SP)
4734 BlitScreenToBitmap_SP(backbuffer);
4737 /* disable deactivated drawing when quick-loading level tape recording */
4738 if (tape.playing && tape.deactivate_display)
4739 TapeDeactivateDisplayOff(TRUE);
4741 SetMouseCursor(CURSOR_DEFAULT);
4743 #if defined(NETWORK_AVALIABLE)
4744 /* pause network game while waiting for request to answer */
4745 if (options.network &&
4746 game_status == GAME_MODE_PLAYING &&
4747 req_state & REQUEST_WAIT_FOR_INPUT)
4748 SendToServer_PausePlaying();
4751 /* simulate releasing mouse button over last gadget, if still pressed */
4753 HandleGadgets(-1, -1, 0);
4757 // (replace with setting corresponding request background)
4758 // SetDoorBackgroundImage(IMG_BACKGROUND_DOOR);
4759 // SetDrawBackgroundMask(REDRAW_FIELD | REDRAW_DOOR_1);
4761 /* clear door drawing field */
4762 // DrawBackground(DX, DY, DXSIZE, DYSIZE);
4765 if (global.use_envelope_request)
4769 CreateToolButtons();
4775 if (req_state & REQ_ASK)
4777 MapGadgetExt(tool_gadget[TOOL_CTRL_ID_YES], FALSE);
4778 MapGadgetExt(tool_gadget[TOOL_CTRL_ID_NO], FALSE);
4780 else if (req_state & REQ_CONFIRM)
4782 MapGadgetExt(tool_gadget[TOOL_CTRL_ID_CONFIRM], FALSE);
4784 else if (req_state & REQ_PLAYER)
4786 MapGadgetExt(tool_gadget[TOOL_CTRL_ID_PLAYER_1], FALSE);
4787 MapGadgetExt(tool_gadget[TOOL_CTRL_ID_PLAYER_2], FALSE);
4788 MapGadgetExt(tool_gadget[TOOL_CTRL_ID_PLAYER_3], FALSE);
4789 MapGadgetExt(tool_gadget[TOOL_CTRL_ID_PLAYER_4], FALSE);
4792 if (req_state & REQ_ASK)
4794 MapGadget(tool_gadget[TOOL_CTRL_ID_YES]);
4795 MapGadget(tool_gadget[TOOL_CTRL_ID_NO]);
4797 else if (req_state & REQ_CONFIRM)
4799 MapGadget(tool_gadget[TOOL_CTRL_ID_CONFIRM]);
4801 else if (req_state & REQ_PLAYER)
4803 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_1]);
4804 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_2]);
4805 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_3]);
4806 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_4]);
4811 ShowEnvelopeRequest(text, req_state, ACTION_OPENING);
4814 for (i = 0; i < NUM_TOOL_BUTTONS; i++)
4816 if ((req_state & REQ_ASK && (i == TOOL_CTRL_ID_YES ||
4817 i == TOOL_CTRL_ID_NO)) ||
4818 (req_state & REQ_CONFIRM && i == TOOL_CTRL_ID_CONFIRM) ||
4819 (req_state & REQ_PLAYER && (i == TOOL_CTRL_ID_PLAYER_1 &&
4820 i == TOOL_CTRL_ID_PLAYER_2 &&
4821 i == TOOL_CTRL_ID_PLAYER_3 &&
4822 i == TOOL_CTRL_ID_PLAYER_4)))
4824 int x = tool_gadget[i]->x + dDX;
4825 int y = tool_gadget[i]->y + dDY;
4827 ModifyGadget(tool_gadget[i], GDI_X, x, GDI_Y, y, GDI_END);
4832 if (!(req_state & REQUEST_WAIT_FOR_INPUT))
4834 if (game_status == GAME_MODE_PLAYING)
4836 SetPanelBackground();
4837 SetDrawBackgroundMask(REDRAW_DOOR_1);
4841 SetDrawBackgroundMask(REDRAW_FIELD);
4848 if (game_status != GAME_MODE_MAIN)
4852 SetDrawBackgroundMask(REDRAW_FIELD | REDRAW_DOOR_1);
4854 // ---------- handle request buttons ----------
4855 result = RequestHandleEvents(req_state);
4857 if (game_status != GAME_MODE_MAIN)
4862 ShowEnvelopeRequest(text, req_state, ACTION_CLOSING);
4866 if (game_status == GAME_MODE_PLAYING)
4868 SetPanelBackground();
4869 SetDrawBackgroundMask(REDRAW_DOOR_1);
4873 SetDrawBackgroundMask(REDRAW_FIELD);
4876 #if defined(NETWORK_AVALIABLE)
4877 /* continue network game after request */
4878 if (options.network &&
4879 game_status == GAME_MODE_PLAYING &&
4880 req_state & REQUEST_WAIT_FOR_INPUT)
4881 SendToServer_ContinuePlaying();
4884 /* restore deactivated drawing when quick-loading level tape recording */
4885 if (tape.playing && tape.deactivate_display)
4886 TapeDeactivateDisplayOn();
4891 boolean Request(char *text, unsigned int req_state)
4893 if (global.use_envelope_request)
4894 return RequestEnvelope(text, req_state);
4896 return RequestDoor(text, req_state);
4899 #else // =====================================================================
4901 boolean Request(char *text, unsigned int req_state)
4903 int mx, my, ty, result = -1;
4904 unsigned int old_door_state;
4905 int last_game_status = game_status; /* save current game status */
4906 int max_request_line_len = MAX_REQUEST_LINE_FONT1_LEN;
4907 int font_nr = FONT_TEXT_2;
4909 int max_word_len = 0;
4915 global.use_envelope_request = 1;
4919 if (maxWordLengthInString(text) > MAX_REQUEST_LINE_FONT1_LEN)
4921 max_request_line_len = MAX_REQUEST_LINE_FONT2_LEN;
4922 font_nr = FONT_TEXT_1;
4925 for (text_ptr = text; *text_ptr; text_ptr++)
4927 max_word_len = (*text_ptr != ' ' ? max_word_len + 1 : 0);
4929 if (max_word_len > MAX_REQUEST_LINE_FONT1_LEN)
4931 max_request_line_len = MAX_REQUEST_LINE_FONT2_LEN;
4933 font_nr = FONT_TEXT_1;
4935 font_nr = FONT_LEVEL_NUMBER;
4943 if (game_status == GAME_MODE_PLAYING)
4945 if (level.game_engine_type == GAME_ENGINE_TYPE_EM)
4946 BlitScreenToBitmap_EM(backbuffer);
4947 else if (level.game_engine_type == GAME_ENGINE_TYPE_SP)
4948 BlitScreenToBitmap_SP(backbuffer);
4951 /* disable deactivated drawing when quick-loading level tape recording */
4952 if (tape.playing && tape.deactivate_display)
4953 TapeDeactivateDisplayOff(TRUE);
4955 SetMouseCursor(CURSOR_DEFAULT);
4957 #if defined(NETWORK_AVALIABLE)
4958 /* pause network game while waiting for request to answer */
4959 if (options.network &&
4960 game_status == GAME_MODE_PLAYING &&
4961 req_state & REQUEST_WAIT_FOR_INPUT)
4962 SendToServer_PausePlaying();
4965 old_door_state = GetDoorState();
4967 /* simulate releasing mouse button over last gadget, if still pressed */
4969 HandleGadgets(-1, -1, 0);
4973 /* draw released gadget before proceeding */
4977 if (old_door_state & DOOR_OPEN_1 && !global.use_envelope_request)
4979 if (old_door_state & DOOR_OPEN_1)
4983 if (!global.use_envelope_request)
4984 CloseDoor(DOOR_CLOSE_1);
4986 CloseDoor(DOOR_CLOSE_1);
4989 /* save old door content */
4990 BlitBitmap(bitmap_db_door, bitmap_db_door,
4991 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE,
4992 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1);
4996 SetDoorBackgroundImage(IMG_BACKGROUND_DOOR);
4999 SetDrawBackgroundMask(REDRAW_FIELD | REDRAW_DOOR_1);
5001 /* clear door drawing field */
5002 DrawBackground(DX, DY, DXSIZE, DYSIZE);
5004 /* force DOOR font inside door area */
5005 game_status = GAME_MODE_PSEUDO_DOOR;
5007 /* write text for request */
5008 for (text_ptr = text, ty = 0; ty < MAX_REQUEST_LINES; ty++)
5010 char text_line[max_request_line_len + 1];
5016 for (tl = 0, tx = 0; tx < max_request_line_len; tl++, tx++)
5018 tc = *(text_ptr + tx);
5019 if (!tc || tc == ' ')
5030 strncpy(text_line, text_ptr, tl);
5033 DrawText(DX + (DXSIZE - tl * getFontWidth(font_nr)) / 2,
5034 DY + 8 + ty * (getFontHeight(font_nr) + 2),
5035 text_line, font_nr);
5037 text_ptr += tl + (tc == ' ' ? 1 : 0);
5040 game_status = last_game_status; /* restore current game status */
5043 if (global.use_envelope_request)
5047 CreateToolButtons();
5051 if (req_state & REQ_ASK)
5053 MapGadget(tool_gadget[TOOL_CTRL_ID_YES]);
5054 MapGadget(tool_gadget[TOOL_CTRL_ID_NO]);
5056 else if (req_state & REQ_CONFIRM)
5058 MapGadget(tool_gadget[TOOL_CTRL_ID_CONFIRM]);
5060 else if (req_state & REQ_PLAYER)
5062 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_1]);
5063 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_2]);
5064 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_3]);
5065 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_4]);
5068 /* copy request gadgets to door backbuffer */
5069 BlitBitmap(drawto, bitmap_db_door,
5070 DX, DY, DXSIZE, DYSIZE,
5071 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
5074 if (global.use_envelope_request)
5076 ShowEnvelopeRequest(text, ACTION_OPENING);
5078 for (i = 0; i < NUM_TOOL_BUTTONS; i++)
5080 if ((req_state & REQ_ASK && (i == TOOL_CTRL_ID_YES ||
5081 i == TOOL_CTRL_ID_NO)) ||
5082 (req_state & REQ_CONFIRM && i == TOOL_CTRL_ID_CONFIRM) ||
5083 (req_state & REQ_PLAYER && (i == TOOL_CTRL_ID_PLAYER_1 &&
5084 i == TOOL_CTRL_ID_PLAYER_2 &&
5085 i == TOOL_CTRL_ID_PLAYER_3 &&
5086 i == TOOL_CTRL_ID_PLAYER_4)))
5088 int x = tool_gadget[i]->x + dDX;
5089 int y = tool_gadget[i]->y + dDY;
5091 ModifyGadget(tool_gadget[i], GDI_X, x, GDI_Y, y, GDI_END);
5098 if (!global.use_envelope_request)
5099 OpenDoor(DOOR_OPEN_1);
5101 OpenDoor(DOOR_OPEN_1);
5104 if (!(req_state & REQUEST_WAIT_FOR_INPUT))
5106 if (game_status == GAME_MODE_PLAYING)
5108 SetPanelBackground();
5109 SetDrawBackgroundMask(REDRAW_DOOR_1);
5113 SetDrawBackgroundMask(REDRAW_FIELD);
5120 if (game_status != GAME_MODE_MAIN && !global.use_envelope_request)
5123 if (game_status != GAME_MODE_MAIN)
5127 button_status = MB_RELEASED;
5129 request_gadget_id = -1;
5131 SetDrawBackgroundMask(REDRAW_FIELD | REDRAW_DOOR_1);
5143 case EVENT_BUTTONPRESS:
5144 case EVENT_BUTTONRELEASE:
5145 case EVENT_MOTIONNOTIFY:
5147 if (event.type == EVENT_MOTIONNOTIFY)
5149 if (!PointerInWindow(window))
5150 continue; /* window and pointer are on different screens */
5155 motion_status = TRUE;
5156 mx = ((MotionEvent *) &event)->x;
5157 my = ((MotionEvent *) &event)->y;
5161 motion_status = FALSE;
5162 mx = ((ButtonEvent *) &event)->x;
5163 my = ((ButtonEvent *) &event)->y;
5164 if (event.type == EVENT_BUTTONPRESS)
5165 button_status = ((ButtonEvent *) &event)->button;
5167 button_status = MB_RELEASED;
5170 /* this sets 'request_gadget_id' */
5171 HandleGadgets(mx, my, button_status);
5173 switch (request_gadget_id)
5175 case TOOL_CTRL_ID_YES:
5178 case TOOL_CTRL_ID_NO:
5181 case TOOL_CTRL_ID_CONFIRM:
5182 result = TRUE | FALSE;
5185 case TOOL_CTRL_ID_PLAYER_1:
5188 case TOOL_CTRL_ID_PLAYER_2:
5191 case TOOL_CTRL_ID_PLAYER_3:
5194 case TOOL_CTRL_ID_PLAYER_4:
5205 case EVENT_KEYPRESS:
5206 switch (GetEventKey((KeyEvent *)&event, TRUE))
5209 if (req_state & REQ_CONFIRM)
5218 #if defined(TARGET_SDL2)
5228 if (req_state & REQ_PLAYER)
5232 case EVENT_KEYRELEASE:
5233 ClearPlayerAction();
5237 HandleOtherEvents(&event);
5241 else if (AnyJoystickButton() == JOY_BUTTON_NEW_PRESSED)
5243 int joy = AnyJoystick();
5245 if (joy & JOY_BUTTON_1)
5247 else if (joy & JOY_BUTTON_2)
5253 if (game_status == GAME_MODE_PLAYING && local_player->LevelSolved_GameEnd)
5255 HandleGameActions();
5261 if (!PendingEvent()) /* delay only if no pending events */
5266 game_status = GAME_MODE_PSEUDO_DOOR;
5272 game_status = last_game_status; /* restore current game status */
5280 if (!PendingEvent()) /* delay only if no pending events */
5283 /* don't eat all CPU time */
5290 if (game_status != GAME_MODE_MAIN)
5296 if (global.use_envelope_request)
5297 ShowEnvelopeRequest(text, ACTION_CLOSING);
5301 if (!(req_state & REQ_STAY_OPEN) && !global.use_envelope_request)
5303 if (!(req_state & REQ_STAY_OPEN))
5306 CloseDoor(DOOR_CLOSE_1);
5308 if (((old_door_state & DOOR_OPEN_1) && !(req_state & REQ_STAY_CLOSED)) ||
5309 (req_state & REQ_REOPEN))
5310 OpenDoor(DOOR_OPEN_1 | DOOR_COPY_BACK);
5315 if (game_status == GAME_MODE_PLAYING)
5317 SetPanelBackground();
5318 SetDrawBackgroundMask(REDRAW_DOOR_1);
5322 SetDrawBackgroundMask(REDRAW_FIELD);
5325 #if defined(NETWORK_AVALIABLE)
5326 /* continue network game after request */
5327 if (options.network &&
5328 game_status == GAME_MODE_PLAYING &&
5329 req_state & REQUEST_WAIT_FOR_INPUT)
5330 SendToServer_ContinuePlaying();
5333 /* restore deactivated drawing when quick-loading level tape recording */
5334 if (tape.playing && tape.deactivate_display)
5335 TapeDeactivateDisplayOn();
5342 static int compareDoorPartOrderInfo(const void *object1, const void *object2)
5344 const struct DoorPartOrderInfo *dpo1 = (struct DoorPartOrderInfo *)object1;
5345 const struct DoorPartOrderInfo *dpo2 = (struct DoorPartOrderInfo *)object2;
5348 if (dpo1->sort_priority != dpo2->sort_priority)
5349 compare_result = dpo1->sort_priority - dpo2->sort_priority;
5351 compare_result = dpo1->nr - dpo2->nr;
5353 return compare_result;
5356 void InitGraphicCompatibilityInfo_Doors()
5362 struct DoorInfo *door;
5366 { DOOR_1, IMG_DOOR_1_GFX_PART_1, IMG_DOOR_1_GFX_PART_8, &door_1 },
5367 { DOOR_2, IMG_DOOR_2_GFX_PART_1, IMG_DOOR_2_GFX_PART_8, &door_2 },
5369 { -1, -1, -1, NULL }
5371 struct Rect door_rect_list[] =
5373 { DX, DY, DXSIZE, DYSIZE },
5374 { VX, VY, VXSIZE, VYSIZE }
5378 for (i = 0; doors[i].door_token != -1; i++)
5380 int door_token = doors[i].door_token;
5381 int door_index = DOOR_INDEX_FROM_TOKEN(door_token);
5382 int part_1 = doors[i].part_1;
5383 int part_8 = doors[i].part_8;
5384 int part_2 = part_1 + 1;
5385 int part_3 = part_1 + 2;
5386 struct DoorInfo *door = doors[i].door;
5387 struct Rect *door_rect = &door_rect_list[door_index];
5388 boolean door_gfx_redefined = FALSE;
5390 /* check if any door part graphic definitions have been redefined */
5392 for (j = 0; door_part_controls[j].door_token != -1; j++)
5394 struct DoorPartControlInfo *dpc = &door_part_controls[j];
5395 struct FileInfo *fi = getImageListEntryFromImageID(dpc->graphic);
5397 if (dpc->door_token == door_token && fi->redefined)
5398 door_gfx_redefined = TRUE;
5401 /* check for old-style door graphic/animation modifications */
5403 if (!door_gfx_redefined)
5405 if (door->anim_mode & ANIM_STATIC_PANEL)
5407 door->panel.step_xoffset = 0;
5408 door->panel.step_yoffset = 0;
5411 if (door->anim_mode & (ANIM_HORIZONTAL | ANIM_VERTICAL))
5413 struct GraphicInfo *g_part_1 = &graphic_info[part_1];
5414 struct GraphicInfo *g_part_2 = &graphic_info[part_2];
5415 int num_door_steps, num_panel_steps;
5417 /* remove door part graphics other than the two default wings */
5419 for (j = 0; door_part_controls[j].door_token != -1; j++)
5421 struct DoorPartControlInfo *dpc = &door_part_controls[j];
5422 struct GraphicInfo *g = &graphic_info[dpc->graphic];
5424 if (dpc->graphic >= part_3 &&
5425 dpc->graphic <= part_8)
5429 /* set graphics and screen positions of the default wings */
5431 g_part_1->width = door_rect->width;
5432 g_part_1->height = door_rect->height;
5433 g_part_2->width = door_rect->width;
5434 g_part_2->height = door_rect->height;
5435 g_part_2->src_x = door_rect->width;
5436 g_part_2->src_y = g_part_1->src_y;
5438 door->part_2.x = door->part_1.x;
5439 door->part_2.y = door->part_1.y;
5441 if (door->width != -1)
5443 g_part_1->width = door->width;
5444 g_part_2->width = door->width;
5446 // special treatment for graphics and screen position of right wing
5447 g_part_2->src_x += door_rect->width - door->width;
5448 door->part_2.x += door_rect->width - door->width;
5451 if (door->height != -1)
5453 g_part_1->height = door->height;
5454 g_part_2->height = door->height;
5456 // special treatment for graphics and screen position of bottom wing
5457 g_part_2->src_y += door_rect->height - door->height;
5458 door->part_2.y += door_rect->height - door->height;
5461 /* set animation delays for the default wings and panels */
5463 door->part_1.step_delay = door->step_delay;
5464 door->part_2.step_delay = door->step_delay;
5465 door->panel.step_delay = door->step_delay;
5467 /* set animation draw order for the default wings */
5469 door->part_1.sort_priority = 2; /* draw left wing over ... */
5470 door->part_2.sort_priority = 1; /* ... right wing */
5472 /* set animation draw offset for the default wings */
5474 if (door->anim_mode & ANIM_HORIZONTAL)
5476 door->part_1.step_xoffset = door->step_offset;
5477 door->part_1.step_yoffset = 0;
5478 door->part_2.step_xoffset = door->step_offset * -1;
5479 door->part_2.step_yoffset = 0;
5481 num_door_steps = g_part_1->width / door->step_offset;
5483 else // ANIM_VERTICAL
5485 door->part_1.step_xoffset = 0;
5486 door->part_1.step_yoffset = door->step_offset;
5487 door->part_2.step_xoffset = 0;
5488 door->part_2.step_yoffset = door->step_offset * -1;
5490 num_door_steps = g_part_1->height / door->step_offset;
5493 /* set animation draw offset for the default panels */
5495 if (door->step_offset > 1)
5497 num_panel_steps = 2 * door_rect->height / door->step_offset;
5498 door->panel.start_step = num_panel_steps - num_door_steps;
5502 num_panel_steps = door_rect->height / door->step_offset;
5503 door->panel.start_step = num_panel_steps - num_door_steps / 2;
5504 door->panel.step_delay *= 2;
5515 for (i = 0; door_part_controls[i].door_token != -1; i++)
5517 struct DoorPartControlInfo *dpc = &door_part_controls[i];
5518 struct DoorPartOrderInfo *dpo = &door_part_order[i];
5520 /* initialize "start_step_opening" and "start_step_closing", if needed */
5521 if (dpc->pos->start_step_opening == 0 &&
5522 dpc->pos->start_step_closing == 0)
5524 // dpc->pos->start_step_opening = dpc->pos->start_step;
5525 dpc->pos->start_step_closing = dpc->pos->start_step;
5528 /* fill structure for door part draw order (sorted below) */
5530 dpo->sort_priority = dpc->pos->sort_priority;
5533 struct DoorPartPosInfo *pos = dpc->pos;
5535 printf(":0: step_xoffset == %d, step_yoffset == %d\n",
5536 pos->step_xoffset, pos->step_yoffset);
5540 /* sort door part controls according to sort_priority and graphic number */
5541 qsort(door_part_order, MAX_DOOR_PARTS,
5542 sizeof(struct DoorPartOrderInfo), compareDoorPartOrderInfo);
5545 unsigned int OpenDoor(unsigned int door_state)
5547 if (door_state & DOOR_COPY_BACK)
5550 if (door_state & DOOR_OPEN_1)
5551 BlitBitmap(bitmap_db_door_1, bitmap_db_door_1,
5552 1 * DXSIZE, 0, DXSIZE, DYSIZE, 0 * DXSIZE, 0);
5554 if (door_state & DOOR_OPEN_2)
5555 BlitBitmap(bitmap_db_door_2, bitmap_db_door_2,
5556 1 * VXSIZE, 0, VXSIZE, VYSIZE, 0 * VXSIZE, 0);
5558 if (door_state & DOOR_OPEN_1)
5559 BlitBitmap(bitmap_db_door, bitmap_db_door,
5560 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE,
5561 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
5563 if (door_state & DOOR_OPEN_2)
5564 BlitBitmap(bitmap_db_door, bitmap_db_door,
5565 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY2, VXSIZE, VYSIZE,
5566 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2);
5569 door_state &= ~DOOR_COPY_BACK;
5572 return MoveDoor(door_state);
5575 unsigned int CloseDoor(unsigned int door_state)
5577 unsigned int old_door_state = GetDoorState();
5579 if (!(door_state & DOOR_NO_COPY_BACK))
5582 if (old_door_state & DOOR_OPEN_1)
5583 BlitBitmap(backbuffer, bitmap_db_door_1,
5584 DX, DY, DXSIZE, DYSIZE, 0, 0);
5586 if (old_door_state & DOOR_OPEN_2)
5587 BlitBitmap(backbuffer, bitmap_db_door_2,
5588 VX, VY, VXSIZE, VYSIZE, 0, 0);
5590 if (old_door_state & DOOR_OPEN_1)
5591 BlitBitmap(backbuffer, bitmap_db_door,
5592 DX, DY, DXSIZE, DYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
5594 if (old_door_state & DOOR_OPEN_2)
5595 BlitBitmap(backbuffer, bitmap_db_door,
5596 VX, VY, VXSIZE, VYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2);
5599 door_state &= ~DOOR_NO_COPY_BACK;
5602 return MoveDoor(door_state);
5605 unsigned int GetDoorState()
5607 return MoveDoor(DOOR_GET_STATE);
5610 unsigned int SetDoorState(unsigned int door_state)
5612 return MoveDoor(door_state | DOOR_SET_STATE);
5617 // ========== TEST 1 ===========================================================
5619 int euclid(int a, int b)
5621 return (b ? euclid(b, a % b) : a);
5624 unsigned int MoveDoor(unsigned int door_state)
5627 struct XY panel_pos_list[] =
5629 { DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1 },
5630 { DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2 },
5633 struct Rect door_rect_list[] =
5635 { DX, DY, DXSIZE, DYSIZE },
5636 { VX, VY, VXSIZE, VYSIZE }
5638 static int door1 = DOOR_OPEN_1;
5639 static int door2 = DOOR_CLOSE_2;
5640 unsigned int door_delay = 0;
5641 unsigned int door_delay_value;
5645 if (door_1.width < 0 || door_1.width > DXSIZE)
5646 door_1.width = DXSIZE;
5647 if (door_1.height < 0 || door_1.height > DYSIZE)
5648 door_1.height = DYSIZE;
5649 if (door_2.width < 0 || door_2.width > VXSIZE)
5650 door_2.width = VXSIZE;
5651 if (door_2.height < 0 || door_2.height > VYSIZE)
5652 door_2.height = VYSIZE;
5655 if (door_state == DOOR_GET_STATE)
5656 return (door1 | door2);
5658 if (door_state & DOOR_SET_STATE)
5660 if (door_state & DOOR_ACTION_1)
5661 door1 = door_state & DOOR_ACTION_1;
5662 if (door_state & DOOR_ACTION_2)
5663 door2 = door_state & DOOR_ACTION_2;
5665 return (door1 | door2);
5668 if (!(door_state & DOOR_FORCE_REDRAW))
5670 if (door1 == DOOR_OPEN_1 && door_state & DOOR_OPEN_1)
5671 door_state &= ~DOOR_OPEN_1;
5672 else if (door1 == DOOR_CLOSE_1 && door_state & DOOR_CLOSE_1)
5673 door_state &= ~DOOR_CLOSE_1;
5674 if (door2 == DOOR_OPEN_2 && door_state & DOOR_OPEN_2)
5675 door_state &= ~DOOR_OPEN_2;
5676 else if (door2 == DOOR_CLOSE_2 && door_state & DOOR_CLOSE_2)
5677 door_state &= ~DOOR_CLOSE_2;
5681 door_delay_value = (door_state & DOOR_ACTION_1 ? door_1.step_delay :
5684 if (setup.quick_doors)
5686 stepsize = 20; /* must be chosen to always draw last frame */
5687 door_delay_value = 0;
5691 if (global.autoplay_leveldir)
5693 door_state |= DOOR_NO_DELAY;
5694 door_state &= ~DOOR_CLOSE_ALL;
5698 if (game_status == GAME_MODE_EDITOR)
5699 door_state |= DOOR_NO_DELAY;
5702 if (door_state & DOOR_ACTION)
5704 boolean door_panel_drawn[NUM_DOORS];
5705 boolean panel_has_doors[NUM_DOORS];
5706 boolean door_part_skip[MAX_DOOR_PARTS];
5707 boolean door_part_done[MAX_DOOR_PARTS];
5708 boolean door_part_done_all;
5709 int num_steps[MAX_DOOR_PARTS];
5710 int max_move_delay = 0; // delay for complete animations of all doors
5711 int max_step_delay = 0; // delay (ms) between two animation frames
5712 int num_move_steps = 0; // number of animation steps for all doors
5713 int current_move_delay = 0;
5716 for (i = 0; i < NUM_DOORS; i++)
5717 panel_has_doors[i] = FALSE;
5719 for (i = 0; i < MAX_DOOR_PARTS; i++)
5721 struct DoorPartControlInfo *dpc = &door_part_controls[i];
5722 struct GraphicInfo *g = &graphic_info[dpc->graphic];
5723 int door_token = dpc->door_token;
5725 door_part_done[i] = FALSE;
5726 door_part_skip[i] = (!(door_state & door_token) ||
5731 for (i = 0; i < MAX_DOOR_PARTS; i++)
5733 struct DoorPartControlInfo *dpc = &door_part_controls[i];
5734 struct DoorPartPosInfo *pos = dpc->pos;
5735 int start_step = pos->start_step;
5737 printf("::: ---> %d: start_step == %d [%d]\n",
5738 i, start_step, door_part_done[i]);
5742 for (i = 0; i < MAX_DOOR_PARTS; i++)
5744 int nr = door_part_order[i].nr;
5745 struct DoorPartControlInfo *dpc = &door_part_controls[nr];
5746 struct DoorPartPosInfo *pos = dpc->pos;
5747 struct GraphicInfo *g = &graphic_info[dpc->graphic];
5748 int door_token = dpc->door_token;
5749 int door_index = DOOR_INDEX_FROM_TOKEN(door_token);
5750 boolean is_panel = DOOR_PART_IS_PANEL(nr);
5751 int step_xoffset = ABS(pos->step_xoffset);
5752 int step_yoffset = ABS(pos->step_yoffset);
5753 int step_delay = pos->step_delay;
5754 int current_door_state = door_state & door_token;
5755 boolean door_opening = ((current_door_state & DOOR_OPEN) != 0);
5756 boolean door_closing = ((current_door_state & DOOR_CLOSE) != 0);
5757 boolean part_opening = (is_panel ? door_closing : door_opening);
5758 int start_step = (part_opening ? pos->start_step_opening :
5759 pos->start_step_closing);
5760 float move_xsize = (step_xoffset ? g->width : 0);
5761 float move_ysize = (step_yoffset ? g->height : 0);
5762 int move_xsteps = (step_xoffset ? ceil(move_xsize / step_xoffset) : 0);
5763 int move_ysteps = (step_yoffset ? ceil(move_ysize / step_yoffset) : 0);
5764 int move_steps = (move_xsteps && move_ysteps ?
5765 MIN(move_xsteps, move_ysteps) :
5766 move_xsteps ? move_xsteps : move_ysteps) - start_step;
5767 int move_delay = move_steps * step_delay;
5769 if (door_part_skip[nr])
5773 panel_has_doors[door_index] = TRUE;
5775 max_move_delay = MAX(max_move_delay, move_delay);
5776 max_step_delay = (max_step_delay == 0 ? step_delay :
5777 euclid(max_step_delay, step_delay));
5778 num_steps[nr] = move_steps;
5782 printf("::: %d: move_delay == %d, start_step == %d [%d]\n",
5783 i, move_delay, start_step, door_part_order[i].nr);
5785 if (DOOR_PART_IS_PANEL(i))
5786 printf("::: %d: move_delay == %d, start_step == %d\n",
5787 i, move_delay, start_step);
5792 num_move_steps = max_move_delay / max_step_delay;
5794 door_delay_value = max_step_delay;
5797 door_delay_value *= 10;
5801 printf("::: num_move_steps == %d, max_move_delay == %d, max_step_delay == %d\n", num_move_steps, max_move_delay, max_step_delay);
5804 for (k = 0; k < num_move_steps; k++)
5806 door_part_done_all = TRUE;
5808 for (i = 0; i < NUM_DOORS; i++)
5809 door_panel_drawn[i] = FALSE;
5811 for (i = 0; i < MAX_DOOR_PARTS; i++)
5813 int nr = door_part_order[i].nr;
5814 struct DoorPartControlInfo *dpc = &door_part_controls[nr];
5815 struct DoorPartPosInfo *pos = dpc->pos;
5816 struct GraphicInfo *g = &graphic_info[dpc->graphic];
5817 int door_token = dpc->door_token;
5818 int door_index = DOOR_INDEX_FROM_TOKEN(door_token);
5819 boolean is_panel = DOOR_PART_IS_PANEL(nr);
5821 struct XY *panel_pos = &panel_pos_list[door_index];
5823 struct Rect *door_rect = &door_rect_list[door_index];
5824 Bitmap *bitmap_db_door = (door_token == DOOR_1 ? bitmap_db_door_1 :
5826 Bitmap *bitmap = (is_panel ? bitmap_db_door : g->bitmap);
5827 int current_door_state = door_state & door_token;
5828 boolean door_opening = ((current_door_state & DOOR_OPEN) != 0);
5829 boolean door_closing = !door_opening;
5830 boolean part_opening = (is_panel ? door_closing : door_opening);
5831 boolean part_closing = !part_opening;
5832 int start_step = (part_opening ? pos->start_step_opening :
5833 pos->start_step_closing);
5834 int step_delay = pos->step_delay;
5835 int step_factor = step_delay / max_step_delay;
5836 int k1 = (step_factor ? k / step_factor + 1 : k);
5837 int k2 = (part_opening ? k1 + start_step : num_steps[nr] - k1);
5838 int kk = (k2 < 0 ? 0 : k2);
5839 int src_x, src_y, src_xx, src_yy;
5840 int dst_x, dst_y, dst_xx, dst_yy;
5844 if (k == 0 && is_panel && door_token == DOOR_2)
5845 printf("::: %d, %d\n", g->width, g->height);
5849 if (DOOR_PART_IS_PANEL(nr))
5851 int start_step = pos->start_step;
5853 k2 = (door_closing ? k1 : num_steps[nr] - k1);// - start_step;
5854 kk = (k2 < 0 ? 0 : k2);
5860 if (nr != 16 && nr != 0)
5871 if (door_part_skip[nr])
5875 if (!(door_state & door_token))
5882 if (current_move_delay % step_delay)
5888 if (!door_panel_drawn[door_index])
5891 ClearRectangle(drawto, door_rect->x, door_rect->y,
5892 door_rect->width, door_rect->height);
5894 BlitBitmap(bitmap_db_door, drawto, panel_pos->x, panel_pos->y,
5895 door_rect->width, door_rect->height,
5896 door_rect->x, door_rect->y);
5899 door_panel_drawn[door_index] = TRUE;
5902 // draw opening or closing door parts
5904 if (pos->step_xoffset < 0) // door part on right side
5907 dst_xx = pos->x + ABS(kk * pos->step_xoffset);
5910 if (dst_xx + width > door_rect->width)
5911 width = door_rect->width - dst_xx;
5913 else // door part on left side
5916 dst_xx = pos->x - kk * pos->step_xoffset;
5920 src_xx = ABS(dst_xx);
5924 width = g->width - src_xx;
5926 // printf("::: k == %d [%d] \n", k, start_step);
5929 if (pos->step_yoffset < 0) // door part on bottom side
5932 dst_yy = pos->y + ABS(kk * pos->step_yoffset);
5935 if (dst_yy + height > door_rect->height)
5936 height = door_rect->height - dst_yy;
5938 else // door part on top side
5941 dst_yy = pos->y - kk * pos->step_yoffset;
5945 src_yy = ABS(dst_yy);
5949 height = g->height - src_yy;
5958 src_x = panel_pos->x + src_xx;
5959 src_y = panel_pos->y + src_yy;
5964 src_x = g->src_x + src_xx;
5965 src_y = g->src_y + src_yy;
5968 dst_x = door_rect->x + dst_xx;
5969 dst_y = door_rect->y + dst_yy;
5972 if (DOOR_PART_IS_PANEL(nr))
5974 printf("::: width == %d, height == %d [%d, %d] [%d, %d]\n",
5975 width, height, g->width, g->height, src_x, src_y);
5979 if (width >= 0 && width <= g->width &&
5980 height >= 0 && height <= g->height)
5982 if (is_panel || !pos->draw_masked)
5983 BlitBitmap(bitmap, drawto, src_x, src_y, width, height,
5986 BlitBitmapMasked(bitmap, drawto, src_x, src_y, width, height,
5991 if (DOOR_PART_IS_PANEL(nr))
5993 bitmap = bitmap_db_door;
5994 src_x = panel_pos->x + src_xx;
5995 src_y = panel_pos->y + src_yy;
5997 printf("::: width == %d, height == %d [%d, %d] [%d, %d]\n",
5998 width, height, g->width, g->height, src_x, src_y);
6000 if (width >= 0 && width <= g->width &&
6001 height >= 0 && height <= g->height)
6002 BlitBitmap(bitmap, drawto, src_x, src_y,
6008 redraw_mask |= REDRAW_DOOR_FROM_TOKEN(door_token);
6011 if ((part_opening && (width < 0 || height < 0)) ||
6012 (part_closing && (width >= g->width && height >= g->height)))
6013 door_part_done[nr] = TRUE;
6015 if ((door_opening && (width < 0 || height < 0)) ||
6016 (door_closing && (width >= g->width && height >= g->height)))
6017 door_part_done[nr] = TRUE;
6021 // continue door part animations, but not panel after door has closed
6022 if (!door_part_done[nr] &&
6023 !(is_panel && door_closing && panel_has_doors[door_index]))
6024 door_part_done_all = FALSE;
6026 // continue door part animations, but not panel after door has closed
6027 if (!door_part_done[nr] && !(is_panel && door_closing))
6028 door_part_done_all = FALSE;
6032 if (!door_part_done[nr])
6033 printf("::: k == %d, nr == %d\n", k, nr);
6037 if (!(door_state & DOOR_NO_DELAY))
6041 if (game_status == GAME_MODE_MAIN)
6044 WaitUntilDelayReached(&door_delay, door_delay_value);
6046 current_move_delay += max_step_delay;
6050 door_part_done_all = TRUE;
6052 for (i = 0; i < MAX_DOOR_PARTS; i++)
6053 if (!door_part_done[i] &&
6054 !(DOOR_PART_IS_PANEL(i) && door_closing))
6055 door_part_done_all = FALSE;
6058 if (door_part_done_all)
6064 if (door_state & DOOR_ACTION_1)
6065 door1 = door_state & DOOR_ACTION_1;
6066 if (door_state & DOOR_ACTION_2)
6067 door2 = door_state & DOOR_ACTION_2;
6070 printf("::: DOORS DONE %08x\n", door_state);
6072 printf("::: GO!\n");
6075 return (door1 | door2);
6080 // ========== OLD ==============================================================
6082 unsigned int MoveDoor(unsigned int door_state)
6084 static int door1 = DOOR_OPEN_1;
6085 static int door2 = DOOR_CLOSE_2;
6086 unsigned int door_delay = 0;
6087 unsigned int door_delay_value;
6091 if (door_1.width < 0 || door_1.width > DXSIZE)
6092 door_1.width = DXSIZE;
6093 if (door_1.height < 0 || door_1.height > DYSIZE)
6094 door_1.height = DYSIZE;
6095 if (door_2.width < 0 || door_2.width > VXSIZE)
6096 door_2.width = VXSIZE;
6097 if (door_2.height < 0 || door_2.height > VYSIZE)
6098 door_2.height = VYSIZE;
6101 if (door_state == DOOR_GET_STATE)
6102 return (door1 | door2);
6104 if (door_state & DOOR_SET_STATE)
6106 if (door_state & DOOR_ACTION_1)
6107 door1 = door_state & DOOR_ACTION_1;
6108 if (door_state & DOOR_ACTION_2)
6109 door2 = door_state & DOOR_ACTION_2;
6111 return (door1 | door2);
6114 if (!(door_state & DOOR_FORCE_REDRAW))
6116 if (door1 == DOOR_OPEN_1 && door_state & DOOR_OPEN_1)
6117 door_state &= ~DOOR_OPEN_1;
6118 else if (door1 == DOOR_CLOSE_1 && door_state & DOOR_CLOSE_1)
6119 door_state &= ~DOOR_CLOSE_1;
6120 if (door2 == DOOR_OPEN_2 && door_state & DOOR_OPEN_2)
6121 door_state &= ~DOOR_OPEN_2;
6122 else if (door2 == DOOR_CLOSE_2 && door_state & DOOR_CLOSE_2)
6123 door_state &= ~DOOR_CLOSE_2;
6126 door_delay_value = (door_state & DOOR_ACTION_1 ? door_1.step_delay :
6129 // door_delay_value *= 4; // !!! TEST ONLY !!!
6131 if (setup.quick_doors)
6133 stepsize = 20; /* must be chosen to always draw last frame */
6134 door_delay_value = 0;
6137 if (global.autoplay_leveldir)
6139 door_state |= DOOR_NO_DELAY;
6140 door_state &= ~DOOR_CLOSE_ALL;
6144 if (game_status == GAME_MODE_EDITOR)
6145 door_state |= DOOR_NO_DELAY;
6148 if (door_state & DOOR_ACTION)
6151 struct GraphicInfo *g1_left = &graphic_info[IMG_DOOR_1_WING_LEFT];
6152 struct GraphicInfo *g1_right = &graphic_info[IMG_DOOR_1_WING_RIGHT];
6153 struct GraphicInfo *g2_left = &graphic_info[IMG_DOOR_2_WING_LEFT];
6154 struct GraphicInfo *g2_right = &graphic_info[IMG_DOOR_2_WING_RIGHT];
6155 int door_1_left_width = g1_left->width;
6156 int door_1_left_height = g1_left->height;
6157 int door_1_right_width = g1_right->width;
6158 int door_1_right_height = g1_right->height;
6159 int door_2_left_width = g2_left->width;
6160 int door_2_left_height = g2_left->height;
6161 int door_2_right_width = g2_right->width;
6162 int door_2_right_height = g2_right->height;
6163 int door_1_width = MAX(door_1_left_width, door_1_right_width);
6164 int door_1_height = MAX(door_1_left_height, door_1_right_height);
6165 int door_2_width = MAX(door_2_left_width, door_2_right_width);
6166 int door_2_height = MAX(door_2_left_height, door_2_right_height);
6168 boolean handle_door_1 = (door_state & DOOR_ACTION_1);
6169 boolean handle_door_2 = (door_state & DOOR_ACTION_2);
6170 boolean door_1_done = (!handle_door_1);
6171 boolean door_2_done = (!handle_door_2);
6172 boolean door_1_vertical = (door_1.anim_mode & ANIM_VERTICAL);
6173 boolean door_2_vertical = (door_2.anim_mode & ANIM_VERTICAL);
6176 int door_size_1 = (door_1_vertical ? door_1_height : door_1_width);
6177 int door_size_2 = (door_2_vertical ? door_2_height : door_2_width);
6179 int door_size_1 = (door_1_vertical ? DYSIZE : DXSIZE);
6180 int door_size_2 = (door_2_vertical ? VYSIZE : VXSIZE);
6183 int door_size_1 = (door_1_vertical ? door_1.height : door_1.width);
6184 int door_size_2 = (door_2_vertical ? door_2.height : door_2.width);
6186 int max_door_size_1 = (door_1_vertical ? DYSIZE : DXSIZE);
6187 int max_door_size_2 = (door_2_vertical ? VYSIZE : VXSIZE);
6188 // int door_size = (handle_door_1 ? door_size_1 : door_size_2);
6189 int door_size = (handle_door_2 ? door_size_2 : door_size_1);
6190 int max_door_size = (handle_door_1 ? max_door_size_1 : max_door_size_2);
6191 int door_skip = max_door_size - door_size;
6192 int end = door_size;
6193 int start = ((door_state & DOOR_NO_DELAY) ? end : 0);
6196 if (!(door_state & DOOR_NO_DELAY) && !setup.quick_doors)
6198 /* opening door sound has priority over simultaneously closing door */
6199 if (door_state & (DOOR_OPEN_1 | DOOR_OPEN_2))
6200 PlayMenuSoundStereo(SND_DOOR_OPENING, SOUND_MIDDLE);
6201 else if (door_state & (DOOR_CLOSE_1 | DOOR_CLOSE_2))
6202 PlayMenuSoundStereo(SND_DOOR_CLOSING, SOUND_MIDDLE);
6205 for (k = start; k <= end && !(door_1_done && door_2_done); k += stepsize)
6209 Bitmap *bitmap = graphic_info[IMG_GLOBAL_DOOR].bitmap;
6210 GC gc = bitmap->stored_clip_gc;
6213 if (door_state & DOOR_ACTION_1 &&
6214 x * door_1.step_offset <= door_size_1)
6216 int a = MIN(x * door_1.step_offset, end);
6217 int p = (door_state & DOOR_OPEN_1 ? end - a : a);
6221 int i = p + door_skip;
6225 struct GraphicInfo *g_left = &graphic_info[IMG_DOOR_1_WING_LEFT];
6226 struct GraphicInfo *g_right = &graphic_info[IMG_DOOR_1_WING_RIGHT];
6227 Bitmap *bm_left = g_left->bitmap;
6228 Bitmap *bm_right = g_right->bitmap;
6229 GC gc_left = bm_left->stored_clip_gc;
6230 GC gc_right = bm_right->stored_clip_gc;
6233 int classic_dxsize = 100;
6234 int classic_dysize = 280;
6235 boolean classic_door_1_size = (DXSIZE == classic_dxsize &&
6236 DYSIZE == classic_dysize);
6238 if (door_1.anim_mode & ANIM_STATIC_PANEL)
6240 BlitBitmap(bitmap_db_door, drawto,
6241 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1,
6242 DXSIZE, DYSIZE, DX, DY);
6246 BlitBitmap(bitmap_db_door, drawto,
6247 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1 + p / 2,
6248 DXSIZE, DYSIZE - p / 2, DX, DY);
6251 // printf("::: p == %d\n", p);
6252 ClearRectangle(drawto, DX, DY + DYSIZE - p / 2, DXSIZE, p / 2);
6256 if (door_1.anim_mode & ANIM_HORIZONTAL && x <= DXSIZE)
6259 int src1_x = g_right->src_x;
6260 int src1_y = g_right->src_y;
6261 int src2_x = g_left->src_x + g_left->width - i;
6262 int src2_y = g_left->src_y;
6263 int dst1_x = DX + DXSIZE - i;
6268 int height = DYSIZE;
6270 SetClipOrigin(bm_right, gc_right, dst1_x - src1_x, dst1_y - src1_y);
6271 BlitBitmapMasked(bm_right, drawto, src1_x, src1_y, width, height,
6274 SetClipOrigin(bm_left, gc_left, dst2_x - src2_x, dst2_y - src2_y);
6275 BlitBitmapMasked(bm_left, drawto, src2_x, src2_y, width, height,
6278 int src1_x = DXSIZE, src1_y = DOOR_GFX_PAGEY1;
6279 int src2_x = DXSIZE - i, src2_y = DOOR_GFX_PAGEY1;
6280 int dst1_x = DX + DXSIZE - i, dst1_y = DY;
6281 int dst2_x = DX, dst2_y = DY;
6282 int width = i, height = DYSIZE;
6284 SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y);
6285 BlitBitmapMasked(bitmap, drawto, src1_x, src1_y, width, height,
6288 SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y);
6289 BlitBitmapMasked(bitmap, drawto, src2_x, src2_y, width, height,
6293 else if (door_1.anim_mode & ANIM_VERTICAL && x <= DYSIZE)
6296 int src1_x = g_right->src_x;
6297 int src1_y = g_right->src_y;
6298 int src2_x = g_left->src_x;
6299 int src2_y = g_left->src_y + g_left->height - i;
6301 int dst1_y = DY + DYSIZE - i;
6307 SetClipOrigin(bm_right, gc_right, dst1_x - src1_x, dst1_y - src1_y);
6308 BlitBitmapMasked(bm_right, drawto, src1_x, src1_y, width, height,
6311 SetClipOrigin(bm_left, gc_left, dst2_x - src2_x, dst2_y - src2_y);
6312 BlitBitmapMasked(bm_left, drawto, src2_x, src2_y, width, height,
6315 int src1_x = DXSIZE, src1_y = DOOR_GFX_PAGEY1;
6316 int src2_x = 0, src2_y = DOOR_GFX_PAGEY1 + DYSIZE - i;
6317 int dst1_x = DX, dst1_y = DY + DYSIZE - i;
6318 int dst2_x = DX, dst2_y = DY;
6319 int width = DXSIZE, height = i;
6321 SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y);
6322 BlitBitmapMasked(bitmap, drawto, src1_x, src1_y, width, height,
6325 SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y);
6326 BlitBitmapMasked(bitmap, drawto, src2_x, src2_y, width, height,
6330 else if (classic_door_1_size && x <= DXSIZE) /* ANIM_DEFAULT */
6332 int j = (door_1.anim_mode == ANIM_DEFAULT ? (DXSIZE - i) / 3 : 0);
6335 int src1_x = g_right->src_x;
6336 int src1_y = g_right->src_y;
6337 int src2_x = g_left->src_x + g_left->width - i;
6338 int src2_y = g_left->src_y;
6339 int dst1_x = DX + DXSIZE - i;
6344 int height1 = 63, height2 = DYSIZE / 2 - height1;
6345 int ypos1 = 0, ypos2 = height2;
6346 int ypos3 = DYSIZE / 2, ypos4 = DYSIZE - height2;
6348 SetClipOrigin(bm_right, gc_right,
6349 dst1_x - src1_x, dst1_y - src1_y + j);
6350 BlitBitmapMasked(bm_right, drawto,
6351 src1_x, src1_y + ypos1, width, height2,
6352 dst1_x, dst1_y + ypos1 + j);
6353 BlitBitmapMasked(bm_right, drawto,
6354 src1_x, src1_y + ypos3, width, height1,
6355 dst1_x, dst1_y + ypos3 + j);
6356 SetClipOrigin(bm_left, gc_left,
6357 dst2_x - src2_x, dst2_y - src2_y - j);
6358 BlitBitmapMasked(bm_left, drawto,
6359 src2_x, src2_y + ypos1 + j, width, height2 - j,
6360 dst2_x, dst2_y + ypos1);
6361 BlitBitmapMasked(bm_left, drawto,
6362 src2_x, src2_y + ypos3, width, height1,
6363 dst2_x, dst2_y + ypos3 - j);
6365 SetClipOrigin(bm_left, gc_left,
6366 dst2_x - src2_x, dst2_y - src2_y - j);
6367 BlitBitmapMasked(bm_left, drawto,
6368 src2_x, src2_y + ypos2, width, height1,
6369 dst2_x, dst2_y + ypos2 - j);
6370 BlitBitmapMasked(bm_left, drawto,
6371 src2_x, src2_y + ypos4, width, height2,
6372 dst2_x, dst2_y + ypos4 - j);
6373 SetClipOrigin(bm_right, gc_right,
6374 dst1_x - src1_x, dst1_y - src1_y + j);
6375 BlitBitmapMasked(bm_right, drawto,
6376 src1_x, src1_y + ypos2, width, height1,
6377 dst1_x, dst1_y + ypos2 + j);
6378 BlitBitmapMasked(bm_right, drawto,
6379 src1_x, src1_y + ypos4, width, height2 - j,
6380 dst1_x, dst1_y + ypos4 + j);
6383 int src1_x = DXSIZE, src1_y = DOOR_GFX_PAGEY1;
6384 int src2_x = DXSIZE - i, src2_y = DOOR_GFX_PAGEY1;
6385 int dst1_x = DX + DXSIZE - i, dst1_y = DY;
6386 int dst2_x = DX, dst2_y = DY;
6387 int width = i, height = DYSIZE;
6388 int ypos1 = 63, ypos2 = 77, ypos3 = 140, ypos4 = 203;
6390 SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y + j);
6391 BlitBitmapMasked(bitmap, drawto,
6392 src1_x, src1_y, width, ypos2,
6393 dst1_x, dst1_y + j);
6394 BlitBitmapMasked(bitmap, drawto,
6395 src1_x, src1_y + ypos3, width, ypos1,
6396 dst1_x, dst1_y + ypos3 + j);
6397 SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y - j);
6398 BlitBitmapMasked(bitmap, drawto,
6399 src2_x, src2_y + j, width, ypos2 - j,
6401 BlitBitmapMasked(bitmap, drawto,
6402 src2_x, src2_y + ypos3, width, ypos1,
6403 dst2_x, dst2_y + ypos3 - j);
6405 SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y - j);
6406 BlitBitmapMasked(bitmap, drawto,
6407 src2_x, src2_y + ypos2, width, ypos1,
6408 dst2_x, dst2_y + ypos2 - j);
6409 BlitBitmapMasked(bitmap, drawto,
6410 src2_x, src2_y + ypos4, width, ypos2,
6411 dst2_x, dst2_y + ypos4 - j);
6412 SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y + j);
6413 BlitBitmapMasked(bitmap, drawto,
6414 src1_x, src1_y + ypos2, width, ypos1,
6415 dst1_x, dst1_y + ypos2 + j);
6416 BlitBitmapMasked(bitmap, drawto,
6417 src1_x, src1_y + ypos4, width, ypos2 - j,
6418 dst1_x, dst1_y + ypos4 + j);
6421 SetClipOrigin(bitmap, gc, DX - i, (DY + j) - DOOR_GFX_PAGEY1);
6422 BlitBitmapMasked(bitmap, drawto,
6423 DXSIZE, DOOR_GFX_PAGEY1, i, 77,
6424 DX + DXSIZE - i, DY + j);
6425 BlitBitmapMasked(bitmap, drawto,
6426 DXSIZE, DOOR_GFX_PAGEY1 + 140, i, 63,
6427 DX + DXSIZE - i, DY + 140 + j);
6428 SetClipOrigin(bitmap, gc, DX - DXSIZE + i,
6429 DY - (DOOR_GFX_PAGEY1 + j));
6430 BlitBitmapMasked(bitmap, drawto,
6431 DXSIZE - i, DOOR_GFX_PAGEY1 + j, i, 77 - j,
6433 BlitBitmapMasked(bitmap, drawto,
6434 DXSIZE-i, DOOR_GFX_PAGEY1 + 140, i, 63,
6437 BlitBitmapMasked(bitmap, drawto,
6438 DXSIZE - i, DOOR_GFX_PAGEY1 + 77, i, 63,
6440 BlitBitmapMasked(bitmap, drawto,
6441 DXSIZE - i, DOOR_GFX_PAGEY1 + 203, i, 77,
6443 SetClipOrigin(bitmap, gc, DX - i, (DY + j) - DOOR_GFX_PAGEY1);
6444 BlitBitmapMasked(bitmap, drawto,
6445 DXSIZE, DOOR_GFX_PAGEY1 + 77, i, 63,
6446 DX + DXSIZE - i, DY + 77 + j);
6447 BlitBitmapMasked(bitmap, drawto,
6448 DXSIZE, DOOR_GFX_PAGEY1 + 203, i, 77 - j,
6449 DX + DXSIZE - i, DY + 203 + j);
6454 redraw_mask |= REDRAW_DOOR_1;
6455 door_1_done = (a == end);
6458 if (door_state & DOOR_ACTION_2 &&
6459 x * door_2.step_offset <= door_size_2)
6461 int a = MIN(x * door_2.step_offset, door_size);
6462 int p = (door_state & DOOR_OPEN_2 ? door_size - a : a);
6463 int i = p + door_skip;
6466 struct GraphicInfo *g_left = &graphic_info[IMG_DOOR_2_WING_LEFT];
6467 struct GraphicInfo *g_right = &graphic_info[IMG_DOOR_2_WING_RIGHT];
6468 Bitmap *bm_left = g_left->bitmap;
6469 Bitmap *bm_right = g_right->bitmap;
6470 GC gc_left = bm_left->stored_clip_gc;
6471 GC gc_right = bm_right->stored_clip_gc;
6474 int classic_vxsize = 100;
6475 int classic_vysize = 100;
6476 boolean classic_door_2_size = (VXSIZE == classic_vxsize &&
6477 VYSIZE == classic_vysize);
6479 if (door_2.anim_mode & ANIM_STATIC_PANEL)
6481 BlitBitmap(bitmap_db_door, drawto,
6482 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2,
6483 VXSIZE, VYSIZE, VX, VY);
6485 else if (x <= VYSIZE)
6487 BlitBitmap(bitmap_db_door, drawto,
6488 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2 + p / 2,
6489 VXSIZE, VYSIZE - p / 2, VX, VY);
6491 ClearRectangle(drawto, VX, VY + VYSIZE - p / 2, VXSIZE, p / 2);
6494 if (door_2.anim_mode & ANIM_HORIZONTAL && x <= VXSIZE)
6497 int src1_x = g_right->src_x;
6498 int src1_y = g_right->src_y;
6499 int src2_x = g_left->src_x + g_left->width - i;
6500 int src2_y = g_left->src_y;
6501 int dst1_x = VX + VXSIZE - i;
6506 int height = VYSIZE;
6508 SetClipOrigin(bm_right, gc_right, dst1_x - src1_x, dst1_y - src1_y);
6509 BlitBitmapMasked(bm_right, drawto, src1_x, src1_y, width, height,
6512 SetClipOrigin(bm_left, gc_left, dst2_x - src2_x, dst2_y - src2_y);
6513 BlitBitmapMasked(bm_left, drawto, src2_x, src2_y, width, height,
6516 int src1_x = VXSIZE, src1_y = DOOR_GFX_PAGEY2;
6517 int src2_x = VXSIZE - i, src2_y = DOOR_GFX_PAGEY2;
6518 int dst1_x = VX + VXSIZE - i, dst1_y = VY;
6519 int dst2_x = VX, dst2_y = VY;
6520 int width = i, height = VYSIZE;
6522 SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y);
6523 BlitBitmapMasked(bitmap, drawto, src1_x, src1_y, width, height,
6526 SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y);
6527 BlitBitmapMasked(bitmap, drawto, src2_x, src2_y, width, height,
6531 else if (door_2.anim_mode & ANIM_VERTICAL && x <= VYSIZE)
6534 int src1_x = g_right->src_x;
6535 int src1_y = g_right->src_y;
6536 int src2_x = g_left->src_x;
6537 int src2_y = g_left->src_y + g_left->height - i;
6539 int dst1_y = VY + VYSIZE - i;
6545 SetClipOrigin(bm_right, gc_right, dst1_x - src1_x, dst1_y - src1_y);
6546 BlitBitmapMasked(bm_right, drawto, src1_x, src1_y, width, height,
6549 SetClipOrigin(bm_left, gc_left, dst2_x - src2_x, dst2_y - src2_y);
6550 BlitBitmapMasked(bm_left, drawto, src2_x, src2_y, width, height,
6553 int src1_x = VXSIZE, src1_y = DOOR_GFX_PAGEY2;
6554 int src2_x = 0, src2_y = DOOR_GFX_PAGEY2 + VYSIZE - i;
6555 int dst1_x = VX, dst1_y = VY + VYSIZE - i;
6556 int dst2_x = VX, dst2_y = VY;
6557 int width = VXSIZE, height = i;
6559 SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y);
6560 BlitBitmapMasked(bitmap, drawto, src1_x, src1_y, width, height,
6563 SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y);
6564 BlitBitmapMasked(bitmap, drawto, src2_x, src2_y, width, height,
6568 else if (classic_door_2_size && x <= VXSIZE) /* ANIM_DEFAULT */
6570 int j = (door_2.anim_mode == ANIM_DEFAULT ? (VXSIZE - i) / 3 : 0);
6573 int src1_x = g_right->src_x;
6574 int src1_y = g_right->src_y;
6575 int src2_x = g_left->src_x + g_left->width - i;
6576 int src2_y = g_left->src_y;
6577 int dst1_x = VX + VXSIZE - i;
6582 int height = VYSIZE / 2;
6583 int ypos1 = 0, ypos2 = VYSIZE / 2;
6585 SetClipOrigin(bm_right, gc_right,
6586 dst1_x - src1_x, dst1_y - src1_y + j);
6587 BlitBitmapMasked(bm_right, drawto,
6588 src1_x, src1_y + ypos1, width, height,
6589 dst1_x, dst1_y + ypos1 + j);
6590 SetClipOrigin(bm_left, gc_left,
6591 dst2_x - src2_x, dst2_y - src2_y - j);
6592 BlitBitmapMasked(bm_left, drawto,
6593 src2_x, src2_y + ypos1 + j, width, height - j,
6594 dst2_x, dst2_y + ypos1);
6596 SetClipOrigin(bm_left, gc_left,
6597 dst2_x - src2_x, dst2_y - src2_y - j);
6598 BlitBitmapMasked(bm_left, drawto,
6599 src2_x, src2_y + ypos2, width, height,
6600 dst2_x, dst2_y + ypos2 - j);
6601 SetClipOrigin(bm_right, gc_right,
6602 dst1_x - src1_x, dst1_y - src1_y + j);
6603 BlitBitmapMasked(bm_right, drawto,
6604 src1_x, src1_y + ypos2, width, height - j,
6605 dst1_x, dst1_y + ypos2 + j);
6607 int src1_x = VXSIZE, src1_y = DOOR_GFX_PAGEY2;
6608 int src2_x = VXSIZE - i, src2_y = DOOR_GFX_PAGEY2;
6609 int dst1_x = VX + VXSIZE - i, dst1_y = VY;
6610 int dst2_x = VX, dst2_y = VY;
6611 int width = i, height = VYSIZE;
6612 int ypos = VYSIZE / 2;
6614 SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y + j);
6615 BlitBitmapMasked(bitmap, drawto,
6616 src1_x, src1_y, width, ypos,
6617 dst1_x, dst1_y + j);
6618 SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src1_y - j);
6619 BlitBitmapMasked(bitmap, drawto,
6620 src2_x, src2_y + j, width, ypos - j,
6623 SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src1_y - j);
6624 BlitBitmapMasked(bitmap, drawto,
6625 src2_x, src2_y + ypos, width, ypos,
6626 dst2_x, dst2_y + ypos - j);
6627 SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y + j);
6628 BlitBitmapMasked(bitmap, drawto,
6629 src1_x, src1_y + ypos, width, ypos - j,
6630 dst1_x, dst1_y + ypos + j);
6633 SetClipOrigin(bitmap, gc, VX - i, (VY + j) - DOOR_GFX_PAGEY2);
6634 BlitBitmapMasked(bitmap, drawto,
6635 VXSIZE, DOOR_GFX_PAGEY2, i, VYSIZE / 2,
6636 VX + VXSIZE - i, VY + j);
6637 SetClipOrigin(bitmap, gc,
6638 VX - VXSIZE + i, VY - (DOOR_GFX_PAGEY2 + j));
6639 BlitBitmapMasked(bitmap, drawto,
6640 VXSIZE - i, DOOR_GFX_PAGEY2 + j, i, VYSIZE / 2 - j,
6643 BlitBitmapMasked(bitmap, drawto,
6644 VXSIZE - i, DOOR_GFX_PAGEY2 + VYSIZE / 2,
6645 i, VYSIZE / 2, VX, VY + VYSIZE / 2 - j);
6646 SetClipOrigin(bitmap, gc, VX - i, (VY + j) - DOOR_GFX_PAGEY2);
6647 BlitBitmapMasked(bitmap, drawto,
6648 VXSIZE, DOOR_GFX_PAGEY2 + VYSIZE / 2,
6650 VX + VXSIZE - i, VY + VYSIZE / 2 + j);
6655 redraw_mask |= REDRAW_DOOR_2;
6656 door_2_done = (a == VXSIZE);
6659 if (!(door_state & DOOR_NO_DELAY))
6663 if (game_status == GAME_MODE_MAIN)
6666 WaitUntilDelayReached(&door_delay, door_delay_value);
6671 if (door_state & DOOR_ACTION_1)
6672 door1 = door_state & DOOR_ACTION_1;
6673 if (door_state & DOOR_ACTION_2)
6674 door2 = door_state & DOOR_ACTION_2;
6676 return (door1 | door2);
6681 void DrawSpecialEditorDoor()
6684 struct GraphicInfo *gfx1 = &graphic_info[IMG_DOOR_2_TOP_BORDER_CORRECTION];
6685 int top_border_width = gfx1->width;
6686 int top_border_height = gfx1->height;
6687 int outer_border = viewport.door_2[GAME_MODE_EDITOR].border_size;
6688 int ex = EX - outer_border;
6689 int ey = EY - outer_border;
6690 int vy = VY - outer_border;
6691 int exsize = EXSIZE + 2 * outer_border;
6693 CloseDoor(DOOR_CLOSE_2);
6695 /* draw bigger level editor toolbox window */
6696 BlitBitmap(gfx1->bitmap, drawto, gfx1->src_x, gfx1->src_y,
6697 top_border_width, top_border_height, ex, ey - top_border_height);
6698 BlitBitmap(graphic_info[IMG_GLOBAL_BORDER].bitmap, drawto, ex, vy,
6699 exsize, EYSIZE - VYSIZE + outer_border, ex, ey);
6701 /* draw bigger level editor toolbox window */
6702 BlitBitmap(graphic_info[IMG_GLOBAL_DOOR].bitmap, drawto,
6703 DOOR_GFX_PAGEX7, 0, EXSIZE + 8, 8,
6705 BlitBitmap(graphic_info[IMG_GLOBAL_BORDER].bitmap, drawto,
6706 EX - 6, VY - 4, EXSIZE + 12, EYSIZE - VYSIZE + 4,
6710 redraw_mask |= REDRAW_ALL;
6713 void UndrawSpecialEditorDoor()
6716 struct GraphicInfo *gfx1 = &graphic_info[IMG_DOOR_2_TOP_BORDER_CORRECTION];
6717 int top_border_width = gfx1->width;
6718 int top_border_height = gfx1->height;
6719 int outer_border = viewport.door_2[GAME_MODE_EDITOR].border_size;
6720 int ex = EX - outer_border;
6721 int ey = EY - outer_border;
6722 int ey_top = ey - top_border_height;
6723 int exsize = EXSIZE + 2 * outer_border;
6724 int eysize = EYSIZE + 2 * outer_border;
6726 /* draw normal tape recorder window */
6727 if (graphic_info[IMG_GLOBAL_BORDER].bitmap)
6729 BlitBitmap(graphic_info[IMG_GLOBAL_BORDER].bitmap, drawto,
6730 ex, ey_top, top_border_width, top_border_height,
6732 BlitBitmap(graphic_info[IMG_GLOBAL_BORDER].bitmap, drawto,
6733 ex, ey, exsize, eysize, ex, ey);
6737 // if screen background is set to "[NONE]", clear editor toolbox window
6738 ClearRectangle(drawto, ex, ey_top, top_border_width, top_border_height);
6739 ClearRectangle(drawto, ex, ey, exsize, eysize);
6742 /* draw normal tape recorder window */
6743 BlitBitmap(graphic_info[IMG_GLOBAL_BORDER].bitmap, drawto,
6744 EX - 6, EY - 12, EXSIZE + 12, EYSIZE - VYSIZE + 12,
6748 redraw_mask |= REDRAW_ALL;
6752 /* ---------- new tool button stuff ---------------------------------------- */
6759 struct TextPosInfo *pos;
6762 } toolbutton_info[NUM_TOOL_BUTTONS] =
6765 IMG_REQUEST_BUTTON_GFX_YES, &request.button.yes,
6766 TOOL_CTRL_ID_YES, "yes"
6769 IMG_REQUEST_BUTTON_GFX_NO, &request.button.no,
6770 TOOL_CTRL_ID_NO, "no"
6773 IMG_REQUEST_BUTTON_GFX_CONFIRM, &request.button.confirm,
6774 TOOL_CTRL_ID_CONFIRM, "confirm"
6777 IMG_REQUEST_BUTTON_GFX_PLAYER_1, &request.button.player_1,
6778 TOOL_CTRL_ID_PLAYER_1, "player 1"
6781 IMG_REQUEST_BUTTON_GFX_PLAYER_2, &request.button.player_2,
6782 TOOL_CTRL_ID_PLAYER_2, "player 2"
6785 IMG_REQUEST_BUTTON_GFX_PLAYER_3, &request.button.player_3,
6786 TOOL_CTRL_ID_PLAYER_3, "player 3"
6789 IMG_REQUEST_BUTTON_GFX_PLAYER_4, &request.button.player_4,
6790 TOOL_CTRL_ID_PLAYER_4, "player 4"
6794 void CreateToolButtons()
6798 for (i = 0; i < NUM_TOOL_BUTTONS; i++)
6800 struct GraphicInfo *gfx = &graphic_info[toolbutton_info[i].graphic];
6801 struct TextPosInfo *pos = toolbutton_info[i].pos;
6802 struct GadgetInfo *gi;
6803 Bitmap *deco_bitmap = None;
6804 int deco_x = 0, deco_y = 0, deco_xpos = 0, deco_ypos = 0;
6805 unsigned int event_mask = GD_EVENT_RELEASED;
6808 int gd_x = gfx->src_x;
6809 int gd_y = gfx->src_y;
6810 int gd_xp = gfx->src_x + gfx->pressed_xoffset;
6811 int gd_yp = gfx->src_y + gfx->pressed_yoffset;
6814 if (global.use_envelope_request)
6815 setRequestPosition(&dx, &dy, TRUE);
6817 if (id >= TOOL_CTRL_ID_PLAYER_1 && id <= TOOL_CTRL_ID_PLAYER_4)
6819 int player_nr = id - TOOL_CTRL_ID_PLAYER_1;
6821 getSizedGraphicSource(PLAYER_NR_GFX(IMG_PLAYER_1, player_nr), 0,
6822 pos->size, &deco_bitmap, &deco_x, &deco_y);
6823 deco_xpos = (gfx->width - pos->size) / 2;
6824 deco_ypos = (gfx->height - pos->size) / 2;
6827 gi = CreateGadget(GDI_CUSTOM_ID, id,
6828 GDI_INFO_TEXT, toolbutton_info[i].infotext,
6829 GDI_X, dx + GDI_ACTIVE_POS(pos->x),
6830 GDI_Y, dy + GDI_ACTIVE_POS(pos->y),
6831 GDI_WIDTH, gfx->width,
6832 GDI_HEIGHT, gfx->height,
6833 GDI_TYPE, GD_TYPE_NORMAL_BUTTON,
6834 GDI_STATE, GD_BUTTON_UNPRESSED,
6835 GDI_DESIGN_UNPRESSED, gfx->bitmap, gd_x, gd_y,
6836 GDI_DESIGN_PRESSED, gfx->bitmap, gd_xp, gd_yp,
6837 GDI_DECORATION_DESIGN, deco_bitmap, deco_x, deco_y,
6838 GDI_DECORATION_POSITION, deco_xpos, deco_ypos,
6839 GDI_DECORATION_SIZE, pos->size, pos->size,
6840 GDI_DECORATION_SHIFTING, 1, 1,
6841 GDI_DIRECT_DRAW, FALSE,
6842 GDI_EVENT_MASK, event_mask,
6843 GDI_CALLBACK_ACTION, HandleToolButtons,
6847 Error(ERR_EXIT, "cannot create gadget");
6849 tool_gadget[id] = gi;
6855 /* graphic position values for tool buttons */
6856 #define TOOL_BUTTON_YES_XPOS 2
6857 #define TOOL_BUTTON_YES_YPOS 250
6858 #define TOOL_BUTTON_YES_GFX_YPOS 0
6859 #define TOOL_BUTTON_YES_XSIZE 46
6860 #define TOOL_BUTTON_YES_YSIZE 28
6861 #define TOOL_BUTTON_NO_XPOS 52
6862 #define TOOL_BUTTON_NO_YPOS TOOL_BUTTON_YES_YPOS
6863 #define TOOL_BUTTON_NO_GFX_YPOS TOOL_BUTTON_YES_GFX_YPOS
6864 #define TOOL_BUTTON_NO_XSIZE TOOL_BUTTON_YES_XSIZE
6865 #define TOOL_BUTTON_NO_YSIZE TOOL_BUTTON_YES_YSIZE
6866 #define TOOL_BUTTON_CONFIRM_XPOS TOOL_BUTTON_YES_XPOS
6867 #define TOOL_BUTTON_CONFIRM_YPOS TOOL_BUTTON_YES_YPOS
6868 #define TOOL_BUTTON_CONFIRM_GFX_YPOS 30
6869 #define TOOL_BUTTON_CONFIRM_XSIZE 96
6870 #define TOOL_BUTTON_CONFIRM_YSIZE TOOL_BUTTON_YES_YSIZE
6871 #define TOOL_BUTTON_PLAYER_XSIZE 30
6872 #define TOOL_BUTTON_PLAYER_YSIZE 30
6873 #define TOOL_BUTTON_PLAYER_GFX_XPOS 5
6874 #define TOOL_BUTTON_PLAYER_GFX_YPOS 185
6875 #define TOOL_BUTTON_PLAYER_XPOS (5 + TOOL_BUTTON_PLAYER_XSIZE / 2)
6876 #define TOOL_BUTTON_PLAYER_YPOS (215 - TOOL_BUTTON_PLAYER_YSIZE / 2)
6877 #define TOOL_BUTTON_PLAYER1_XPOS (TOOL_BUTTON_PLAYER_XPOS \
6878 + 0 * TOOL_BUTTON_PLAYER_XSIZE)
6879 #define TOOL_BUTTON_PLAYER2_XPOS (TOOL_BUTTON_PLAYER_XPOS \
6880 + 1 * TOOL_BUTTON_PLAYER_XSIZE)
6881 #define TOOL_BUTTON_PLAYER3_XPOS (TOOL_BUTTON_PLAYER_XPOS \
6882 + 0 * TOOL_BUTTON_PLAYER_XSIZE)
6883 #define TOOL_BUTTON_PLAYER4_XPOS (TOOL_BUTTON_PLAYER_XPOS \
6884 + 1 * TOOL_BUTTON_PLAYER_XSIZE)
6885 #define TOOL_BUTTON_PLAYER1_YPOS (TOOL_BUTTON_PLAYER_YPOS \
6886 + 0 * TOOL_BUTTON_PLAYER_YSIZE)
6887 #define TOOL_BUTTON_PLAYER2_YPOS (TOOL_BUTTON_PLAYER_YPOS \
6888 + 0 * TOOL_BUTTON_PLAYER_YSIZE)
6889 #define TOOL_BUTTON_PLAYER3_YPOS (TOOL_BUTTON_PLAYER_YPOS \
6890 + 1 * TOOL_BUTTON_PLAYER_YSIZE)
6891 #define TOOL_BUTTON_PLAYER4_YPOS (TOOL_BUTTON_PLAYER_YPOS \
6892 + 1 * TOOL_BUTTON_PLAYER_YSIZE)
6901 } toolbutton_info[NUM_TOOL_BUTTONS] =
6904 TOOL_BUTTON_YES_XPOS, TOOL_BUTTON_YES_GFX_YPOS,
6905 TOOL_BUTTON_YES_XPOS, TOOL_BUTTON_YES_YPOS,
6906 TOOL_BUTTON_YES_XSIZE, TOOL_BUTTON_YES_YSIZE,
6911 TOOL_BUTTON_NO_XPOS, TOOL_BUTTON_NO_GFX_YPOS,
6912 TOOL_BUTTON_NO_XPOS, TOOL_BUTTON_NO_YPOS,
6913 TOOL_BUTTON_NO_XSIZE, TOOL_BUTTON_NO_YSIZE,
6918 TOOL_BUTTON_CONFIRM_XPOS, TOOL_BUTTON_CONFIRM_GFX_YPOS,
6919 TOOL_BUTTON_CONFIRM_XPOS, TOOL_BUTTON_CONFIRM_YPOS,
6920 TOOL_BUTTON_CONFIRM_XSIZE, TOOL_BUTTON_CONFIRM_YSIZE,
6921 TOOL_CTRL_ID_CONFIRM,
6925 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
6926 TOOL_BUTTON_PLAYER1_XPOS, TOOL_BUTTON_PLAYER1_YPOS,
6927 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
6928 TOOL_CTRL_ID_PLAYER_1,
6932 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
6933 TOOL_BUTTON_PLAYER2_XPOS, TOOL_BUTTON_PLAYER2_YPOS,
6934 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
6935 TOOL_CTRL_ID_PLAYER_2,
6939 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
6940 TOOL_BUTTON_PLAYER3_XPOS, TOOL_BUTTON_PLAYER3_YPOS,
6941 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
6942 TOOL_CTRL_ID_PLAYER_3,
6946 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
6947 TOOL_BUTTON_PLAYER4_XPOS, TOOL_BUTTON_PLAYER4_YPOS,
6948 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
6949 TOOL_CTRL_ID_PLAYER_4,
6954 void CreateToolButtons()
6958 for (i = 0; i < NUM_TOOL_BUTTONS; i++)
6960 Bitmap *gd_bitmap = graphic_info[IMG_GLOBAL_DOOR].bitmap;
6961 Bitmap *deco_bitmap = None;
6962 int deco_x = 0, deco_y = 0, deco_xpos = 0, deco_ypos = 0;
6963 struct GadgetInfo *gi;
6964 unsigned int event_mask;
6965 int gd_xoffset, gd_yoffset;
6966 int gd_x1, gd_x2, gd_y;
6969 event_mask = GD_EVENT_RELEASED;
6971 gd_xoffset = toolbutton_info[i].xpos;
6972 gd_yoffset = toolbutton_info[i].ypos;
6973 gd_x1 = DOOR_GFX_PAGEX4 + gd_xoffset;
6974 gd_x2 = DOOR_GFX_PAGEX3 + gd_xoffset;
6975 gd_y = DOOR_GFX_PAGEY1 + gd_yoffset;
6977 if (id >= TOOL_CTRL_ID_PLAYER_1 && id <= TOOL_CTRL_ID_PLAYER_4)
6979 int player_nr = id - TOOL_CTRL_ID_PLAYER_1;
6981 getMiniGraphicSource(PLAYER_NR_GFX(IMG_PLAYER_1, player_nr),
6982 &deco_bitmap, &deco_x, &deco_y);
6983 deco_xpos = (toolbutton_info[i].width - MINI_TILEX) / 2;
6984 deco_ypos = (toolbutton_info[i].height - MINI_TILEY) / 2;
6987 gi = CreateGadget(GDI_CUSTOM_ID, id,
6988 GDI_INFO_TEXT, toolbutton_info[i].infotext,
6989 GDI_X, DX + GDI_ACTIVE_POS(toolbutton_info[i].x),
6990 GDI_Y, DY + GDI_ACTIVE_POS(toolbutton_info[i].y),
6991 GDI_WIDTH, toolbutton_info[i].width,
6992 GDI_HEIGHT, toolbutton_info[i].height,
6993 GDI_TYPE, GD_TYPE_NORMAL_BUTTON,
6994 GDI_STATE, GD_BUTTON_UNPRESSED,
6995 GDI_DESIGN_UNPRESSED, gd_bitmap, gd_x1, gd_y,
6996 GDI_DESIGN_PRESSED, gd_bitmap, gd_x2, gd_y,
6997 GDI_DECORATION_DESIGN, deco_bitmap, deco_x, deco_y,
6998 GDI_DECORATION_POSITION, deco_xpos, deco_ypos,
6999 GDI_DECORATION_SIZE, MINI_TILEX, MINI_TILEY,
7000 GDI_DECORATION_SHIFTING, 1, 1,
7001 GDI_DIRECT_DRAW, FALSE,
7002 GDI_EVENT_MASK, event_mask,
7003 GDI_CALLBACK_ACTION, HandleToolButtons,
7007 Error(ERR_EXIT, "cannot create gadget");
7009 tool_gadget[id] = gi;
7015 void FreeToolButtons()
7019 for (i = 0; i < NUM_TOOL_BUTTONS; i++)
7020 FreeGadget(tool_gadget[i]);
7023 static void UnmapToolButtons()
7027 for (i = 0; i < NUM_TOOL_BUTTONS; i++)
7028 UnmapGadget(tool_gadget[i]);
7031 static void HandleToolButtons(struct GadgetInfo *gi)
7033 request_gadget_id = gi->custom_id;
7036 static struct Mapping_EM_to_RND_object
7039 boolean is_rnd_to_em_mapping; /* unique mapping EM <-> RND */
7040 boolean is_backside; /* backside of moving element */
7046 em_object_mapping_list[] =
7049 Xblank, TRUE, FALSE,
7053 Yacid_splash_eB, FALSE, FALSE,
7054 EL_ACID_SPLASH_RIGHT, -1, -1
7057 Yacid_splash_wB, FALSE, FALSE,
7058 EL_ACID_SPLASH_LEFT, -1, -1
7061 #ifdef EM_ENGINE_BAD_ROLL
7063 Xstone_force_e, FALSE, FALSE,
7064 EL_ROCK, -1, MV_BIT_RIGHT
7067 Xstone_force_w, FALSE, FALSE,
7068 EL_ROCK, -1, MV_BIT_LEFT
7071 Xnut_force_e, FALSE, FALSE,
7072 EL_NUT, -1, MV_BIT_RIGHT
7075 Xnut_force_w, FALSE, FALSE,
7076 EL_NUT, -1, MV_BIT_LEFT
7079 Xspring_force_e, FALSE, FALSE,
7080 EL_SPRING, -1, MV_BIT_RIGHT
7083 Xspring_force_w, FALSE, FALSE,
7084 EL_SPRING, -1, MV_BIT_LEFT
7087 Xemerald_force_e, FALSE, FALSE,
7088 EL_EMERALD, -1, MV_BIT_RIGHT
7091 Xemerald_force_w, FALSE, FALSE,
7092 EL_EMERALD, -1, MV_BIT_LEFT
7095 Xdiamond_force_e, FALSE, FALSE,
7096 EL_DIAMOND, -1, MV_BIT_RIGHT
7099 Xdiamond_force_w, FALSE, FALSE,
7100 EL_DIAMOND, -1, MV_BIT_LEFT
7103 Xbomb_force_e, FALSE, FALSE,
7104 EL_BOMB, -1, MV_BIT_RIGHT
7107 Xbomb_force_w, FALSE, FALSE,
7108 EL_BOMB, -1, MV_BIT_LEFT
7110 #endif /* EM_ENGINE_BAD_ROLL */
7113 Xstone, TRUE, FALSE,
7117 Xstone_pause, FALSE, FALSE,
7121 Xstone_fall, FALSE, FALSE,
7125 Ystone_s, FALSE, FALSE,
7126 EL_ROCK, ACTION_FALLING, -1
7129 Ystone_sB, FALSE, TRUE,
7130 EL_ROCK, ACTION_FALLING, -1
7133 Ystone_e, FALSE, FALSE,
7134 EL_ROCK, ACTION_MOVING, MV_BIT_RIGHT
7137 Ystone_eB, FALSE, TRUE,
7138 EL_ROCK, ACTION_MOVING, MV_BIT_RIGHT
7141 Ystone_w, FALSE, FALSE,
7142 EL_ROCK, ACTION_MOVING, MV_BIT_LEFT
7145 Ystone_wB, FALSE, TRUE,
7146 EL_ROCK, ACTION_MOVING, MV_BIT_LEFT
7153 Xnut_pause, FALSE, FALSE,
7157 Xnut_fall, FALSE, FALSE,
7161 Ynut_s, FALSE, FALSE,
7162 EL_NUT, ACTION_FALLING, -1
7165 Ynut_sB, FALSE, TRUE,
7166 EL_NUT, ACTION_FALLING, -1
7169 Ynut_e, FALSE, FALSE,
7170 EL_NUT, ACTION_MOVING, MV_BIT_RIGHT
7173 Ynut_eB, FALSE, TRUE,
7174 EL_NUT, ACTION_MOVING, MV_BIT_RIGHT
7177 Ynut_w, FALSE, FALSE,
7178 EL_NUT, ACTION_MOVING, MV_BIT_LEFT
7181 Ynut_wB, FALSE, TRUE,
7182 EL_NUT, ACTION_MOVING, MV_BIT_LEFT
7185 Xbug_n, TRUE, FALSE,
7189 Xbug_e, TRUE, FALSE,
7190 EL_BUG_RIGHT, -1, -1
7193 Xbug_s, TRUE, FALSE,
7197 Xbug_w, TRUE, FALSE,
7201 Xbug_gon, FALSE, FALSE,
7205 Xbug_goe, FALSE, FALSE,
7206 EL_BUG_RIGHT, -1, -1
7209 Xbug_gos, FALSE, FALSE,
7213 Xbug_gow, FALSE, FALSE,
7217 Ybug_n, FALSE, FALSE,
7218 EL_BUG, ACTION_MOVING, MV_BIT_UP
7221 Ybug_nB, FALSE, TRUE,
7222 EL_BUG, ACTION_MOVING, MV_BIT_UP
7225 Ybug_e, FALSE, FALSE,
7226 EL_BUG, ACTION_MOVING, MV_BIT_RIGHT
7229 Ybug_eB, FALSE, TRUE,
7230 EL_BUG, ACTION_MOVING, MV_BIT_RIGHT
7233 Ybug_s, FALSE, FALSE,
7234 EL_BUG, ACTION_MOVING, MV_BIT_DOWN
7237 Ybug_sB, FALSE, TRUE,
7238 EL_BUG, ACTION_MOVING, MV_BIT_DOWN
7241 Ybug_w, FALSE, FALSE,
7242 EL_BUG, ACTION_MOVING, MV_BIT_LEFT
7245 Ybug_wB, FALSE, TRUE,
7246 EL_BUG, ACTION_MOVING, MV_BIT_LEFT
7249 Ybug_w_n, FALSE, FALSE,
7250 EL_BUG, ACTION_TURNING_FROM_LEFT, MV_BIT_UP
7253 Ybug_n_e, FALSE, FALSE,
7254 EL_BUG, ACTION_TURNING_FROM_UP, MV_BIT_RIGHT
7257 Ybug_e_s, FALSE, FALSE,
7258 EL_BUG, ACTION_TURNING_FROM_RIGHT, MV_BIT_DOWN
7261 Ybug_s_w, FALSE, FALSE,
7262 EL_BUG, ACTION_TURNING_FROM_DOWN, MV_BIT_LEFT
7265 Ybug_e_n, FALSE, FALSE,
7266 EL_BUG, ACTION_TURNING_FROM_RIGHT, MV_BIT_UP
7269 Ybug_s_e, FALSE, FALSE,
7270 EL_BUG, ACTION_TURNING_FROM_DOWN, MV_BIT_RIGHT
7273 Ybug_w_s, FALSE, FALSE,
7274 EL_BUG, ACTION_TURNING_FROM_LEFT, MV_BIT_DOWN
7277 Ybug_n_w, FALSE, FALSE,
7278 EL_BUG, ACTION_TURNING_FROM_UP, MV_BIT_LEFT
7281 Ybug_stone, FALSE, FALSE,
7282 EL_BUG, ACTION_SMASHED_BY_ROCK, -1
7285 Ybug_spring, FALSE, FALSE,
7286 EL_BUG, ACTION_SMASHED_BY_SPRING, -1
7289 Xtank_n, TRUE, FALSE,
7290 EL_SPACESHIP_UP, -1, -1
7293 Xtank_e, TRUE, FALSE,
7294 EL_SPACESHIP_RIGHT, -1, -1
7297 Xtank_s, TRUE, FALSE,
7298 EL_SPACESHIP_DOWN, -1, -1
7301 Xtank_w, TRUE, FALSE,
7302 EL_SPACESHIP_LEFT, -1, -1
7305 Xtank_gon, FALSE, FALSE,
7306 EL_SPACESHIP_UP, -1, -1
7309 Xtank_goe, FALSE, FALSE,
7310 EL_SPACESHIP_RIGHT, -1, -1
7313 Xtank_gos, FALSE, FALSE,
7314 EL_SPACESHIP_DOWN, -1, -1
7317 Xtank_gow, FALSE, FALSE,
7318 EL_SPACESHIP_LEFT, -1, -1
7321 Ytank_n, FALSE, FALSE,
7322 EL_SPACESHIP, ACTION_MOVING, MV_BIT_UP
7325 Ytank_nB, FALSE, TRUE,
7326 EL_SPACESHIP, ACTION_MOVING, MV_BIT_UP
7329 Ytank_e, FALSE, FALSE,
7330 EL_SPACESHIP, ACTION_MOVING, MV_BIT_RIGHT
7333 Ytank_eB, FALSE, TRUE,
7334 EL_SPACESHIP, ACTION_MOVING, MV_BIT_RIGHT
7337 Ytank_s, FALSE, FALSE,
7338 EL_SPACESHIP, ACTION_MOVING, MV_BIT_DOWN
7341 Ytank_sB, FALSE, TRUE,
7342 EL_SPACESHIP, ACTION_MOVING, MV_BIT_DOWN
7345 Ytank_w, FALSE, FALSE,
7346 EL_SPACESHIP, ACTION_MOVING, MV_BIT_LEFT
7349 Ytank_wB, FALSE, TRUE,
7350 EL_SPACESHIP, ACTION_MOVING, MV_BIT_LEFT
7353 Ytank_w_n, FALSE, FALSE,
7354 EL_SPACESHIP, ACTION_TURNING_FROM_LEFT, MV_BIT_UP
7357 Ytank_n_e, FALSE, FALSE,
7358 EL_SPACESHIP, ACTION_TURNING_FROM_UP, MV_BIT_RIGHT
7361 Ytank_e_s, FALSE, FALSE,
7362 EL_SPACESHIP, ACTION_TURNING_FROM_RIGHT, MV_BIT_DOWN
7365 Ytank_s_w, FALSE, FALSE,
7366 EL_SPACESHIP, ACTION_TURNING_FROM_DOWN, MV_BIT_LEFT
7369 Ytank_e_n, FALSE, FALSE,
7370 EL_SPACESHIP, ACTION_TURNING_FROM_RIGHT, MV_BIT_UP
7373 Ytank_s_e, FALSE, FALSE,
7374 EL_SPACESHIP, ACTION_TURNING_FROM_DOWN, MV_BIT_RIGHT
7377 Ytank_w_s, FALSE, FALSE,
7378 EL_SPACESHIP, ACTION_TURNING_FROM_LEFT, MV_BIT_DOWN
7381 Ytank_n_w, FALSE, FALSE,
7382 EL_SPACESHIP, ACTION_TURNING_FROM_UP, MV_BIT_LEFT
7385 Ytank_stone, FALSE, FALSE,
7386 EL_SPACESHIP, ACTION_SMASHED_BY_ROCK, -1
7389 Ytank_spring, FALSE, FALSE,
7390 EL_SPACESHIP, ACTION_SMASHED_BY_SPRING, -1
7393 Xandroid, TRUE, FALSE,
7394 EL_EMC_ANDROID, ACTION_ACTIVE, -1
7397 Xandroid_1_n, FALSE, FALSE,
7398 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_UP
7401 Xandroid_2_n, FALSE, FALSE,
7402 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_UP
7405 Xandroid_1_e, FALSE, FALSE,
7406 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_RIGHT
7409 Xandroid_2_e, FALSE, FALSE,
7410 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_RIGHT
7413 Xandroid_1_w, FALSE, FALSE,
7414 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_LEFT
7417 Xandroid_2_w, FALSE, FALSE,
7418 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_LEFT
7421 Xandroid_1_s, FALSE, FALSE,
7422 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_DOWN
7425 Xandroid_2_s, FALSE, FALSE,
7426 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_DOWN
7429 Yandroid_n, FALSE, FALSE,
7430 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_UP
7433 Yandroid_nB, FALSE, TRUE,
7434 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_UP
7437 Yandroid_ne, FALSE, FALSE,
7438 EL_EMC_ANDROID, ACTION_GROWING, MV_BIT_UPRIGHT
7441 Yandroid_neB, FALSE, TRUE,
7442 EL_EMC_ANDROID, ACTION_SHRINKING, MV_BIT_UPRIGHT
7445 Yandroid_e, FALSE, FALSE,
7446 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_RIGHT
7449 Yandroid_eB, FALSE, TRUE,
7450 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_RIGHT
7453 Yandroid_se, FALSE, FALSE,
7454 EL_EMC_ANDROID, ACTION_GROWING, MV_BIT_DOWNRIGHT
7457 Yandroid_seB, FALSE, TRUE,
7458 EL_EMC_ANDROID, ACTION_SHRINKING, MV_BIT_DOWNRIGHT
7461 Yandroid_s, FALSE, FALSE,
7462 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_DOWN
7465 Yandroid_sB, FALSE, TRUE,
7466 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_DOWN
7469 Yandroid_sw, FALSE, FALSE,
7470 EL_EMC_ANDROID, ACTION_GROWING, MV_BIT_DOWNLEFT
7473 Yandroid_swB, FALSE, TRUE,
7474 EL_EMC_ANDROID, ACTION_SHRINKING, MV_BIT_DOWNLEFT
7477 Yandroid_w, FALSE, FALSE,
7478 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_LEFT
7481 Yandroid_wB, FALSE, TRUE,
7482 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_LEFT
7485 Yandroid_nw, FALSE, FALSE,
7486 EL_EMC_ANDROID, ACTION_GROWING, MV_BIT_UPLEFT
7489 Yandroid_nwB, FALSE, TRUE,
7490 EL_EMC_ANDROID, ACTION_SHRINKING, MV_BIT_UPLEFT
7493 Xspring, TRUE, FALSE,
7497 Xspring_pause, FALSE, FALSE,
7501 Xspring_e, FALSE, FALSE,
7505 Xspring_w, FALSE, FALSE,
7509 Xspring_fall, FALSE, FALSE,
7513 Yspring_s, FALSE, FALSE,
7514 EL_SPRING, ACTION_FALLING, -1
7517 Yspring_sB, FALSE, TRUE,
7518 EL_SPRING, ACTION_FALLING, -1
7521 Yspring_e, FALSE, FALSE,
7522 EL_SPRING, ACTION_MOVING, MV_BIT_RIGHT
7525 Yspring_eB, FALSE, TRUE,
7526 EL_SPRING, ACTION_MOVING, MV_BIT_RIGHT
7529 Yspring_w, FALSE, FALSE,
7530 EL_SPRING, ACTION_MOVING, MV_BIT_LEFT
7533 Yspring_wB, FALSE, TRUE,
7534 EL_SPRING, ACTION_MOVING, MV_BIT_LEFT
7537 Yspring_kill_e, FALSE, FALSE,
7538 EL_SPRING, ACTION_EATING, MV_BIT_RIGHT
7541 Yspring_kill_eB, FALSE, TRUE,
7542 EL_SPRING, ACTION_EATING, MV_BIT_RIGHT
7545 Yspring_kill_w, FALSE, FALSE,
7546 EL_SPRING, ACTION_EATING, MV_BIT_LEFT
7549 Yspring_kill_wB, FALSE, TRUE,
7550 EL_SPRING, ACTION_EATING, MV_BIT_LEFT
7553 Xeater_n, TRUE, FALSE,
7554 EL_YAMYAM_UP, -1, -1
7557 Xeater_e, TRUE, FALSE,
7558 EL_YAMYAM_RIGHT, -1, -1
7561 Xeater_w, TRUE, FALSE,
7562 EL_YAMYAM_LEFT, -1, -1
7565 Xeater_s, TRUE, FALSE,
7566 EL_YAMYAM_DOWN, -1, -1
7569 Yeater_n, FALSE, FALSE,
7570 EL_YAMYAM, ACTION_MOVING, MV_BIT_UP
7573 Yeater_nB, FALSE, TRUE,
7574 EL_YAMYAM, ACTION_MOVING, MV_BIT_UP
7577 Yeater_e, FALSE, FALSE,
7578 EL_YAMYAM, ACTION_MOVING, MV_BIT_RIGHT
7581 Yeater_eB, FALSE, TRUE,
7582 EL_YAMYAM, ACTION_MOVING, MV_BIT_RIGHT
7585 Yeater_s, FALSE, FALSE,
7586 EL_YAMYAM, ACTION_MOVING, MV_BIT_DOWN
7589 Yeater_sB, FALSE, TRUE,
7590 EL_YAMYAM, ACTION_MOVING, MV_BIT_DOWN
7593 Yeater_w, FALSE, FALSE,
7594 EL_YAMYAM, ACTION_MOVING, MV_BIT_LEFT
7597 Yeater_wB, FALSE, TRUE,
7598 EL_YAMYAM, ACTION_MOVING, MV_BIT_LEFT
7601 Yeater_stone, FALSE, FALSE,
7602 EL_YAMYAM, ACTION_SMASHED_BY_ROCK, -1
7605 Yeater_spring, FALSE, FALSE,
7606 EL_YAMYAM, ACTION_SMASHED_BY_SPRING, -1
7609 Xalien, TRUE, FALSE,
7613 Xalien_pause, FALSE, FALSE,
7617 Yalien_n, FALSE, FALSE,
7618 EL_ROBOT, ACTION_MOVING, MV_BIT_UP
7621 Yalien_nB, FALSE, TRUE,
7622 EL_ROBOT, ACTION_MOVING, MV_BIT_UP
7625 Yalien_e, FALSE, FALSE,
7626 EL_ROBOT, ACTION_MOVING, MV_BIT_RIGHT
7629 Yalien_eB, FALSE, TRUE,
7630 EL_ROBOT, ACTION_MOVING, MV_BIT_RIGHT
7633 Yalien_s, FALSE, FALSE,
7634 EL_ROBOT, ACTION_MOVING, MV_BIT_DOWN
7637 Yalien_sB, FALSE, TRUE,
7638 EL_ROBOT, ACTION_MOVING, MV_BIT_DOWN
7641 Yalien_w, FALSE, FALSE,
7642 EL_ROBOT, ACTION_MOVING, MV_BIT_LEFT
7645 Yalien_wB, FALSE, TRUE,
7646 EL_ROBOT, ACTION_MOVING, MV_BIT_LEFT
7649 Yalien_stone, FALSE, FALSE,
7650 EL_ROBOT, ACTION_SMASHED_BY_ROCK, -1
7653 Yalien_spring, FALSE, FALSE,
7654 EL_ROBOT, ACTION_SMASHED_BY_SPRING, -1
7657 Xemerald, TRUE, FALSE,
7661 Xemerald_pause, FALSE, FALSE,
7665 Xemerald_fall, FALSE, FALSE,
7669 Xemerald_shine, FALSE, FALSE,
7670 EL_EMERALD, ACTION_TWINKLING, -1
7673 Yemerald_s, FALSE, FALSE,
7674 EL_EMERALD, ACTION_FALLING, -1
7677 Yemerald_sB, FALSE, TRUE,
7678 EL_EMERALD, ACTION_FALLING, -1
7681 Yemerald_e, FALSE, FALSE,
7682 EL_EMERALD, ACTION_MOVING, MV_BIT_RIGHT
7685 Yemerald_eB, FALSE, TRUE,
7686 EL_EMERALD, ACTION_MOVING, MV_BIT_RIGHT
7689 Yemerald_w, FALSE, FALSE,
7690 EL_EMERALD, ACTION_MOVING, MV_BIT_LEFT
7693 Yemerald_wB, FALSE, TRUE,
7694 EL_EMERALD, ACTION_MOVING, MV_BIT_LEFT
7697 Yemerald_eat, FALSE, FALSE,
7698 EL_EMERALD, ACTION_COLLECTING, -1
7701 Yemerald_stone, FALSE, FALSE,
7702 EL_NUT, ACTION_BREAKING, -1
7705 Xdiamond, TRUE, FALSE,
7709 Xdiamond_pause, FALSE, FALSE,
7713 Xdiamond_fall, FALSE, FALSE,
7717 Xdiamond_shine, FALSE, FALSE,
7718 EL_DIAMOND, ACTION_TWINKLING, -1
7721 Ydiamond_s, FALSE, FALSE,
7722 EL_DIAMOND, ACTION_FALLING, -1
7725 Ydiamond_sB, FALSE, TRUE,
7726 EL_DIAMOND, ACTION_FALLING, -1
7729 Ydiamond_e, FALSE, FALSE,
7730 EL_DIAMOND, ACTION_MOVING, MV_BIT_RIGHT
7733 Ydiamond_eB, FALSE, TRUE,
7734 EL_DIAMOND, ACTION_MOVING, MV_BIT_RIGHT
7737 Ydiamond_w, FALSE, FALSE,
7738 EL_DIAMOND, ACTION_MOVING, MV_BIT_LEFT
7741 Ydiamond_wB, FALSE, TRUE,
7742 EL_DIAMOND, ACTION_MOVING, MV_BIT_LEFT
7745 Ydiamond_eat, FALSE, FALSE,
7746 EL_DIAMOND, ACTION_COLLECTING, -1
7749 Ydiamond_stone, FALSE, FALSE,
7750 EL_DIAMOND, ACTION_SMASHED_BY_ROCK, -1
7753 Xdrip_fall, TRUE, FALSE,
7754 EL_AMOEBA_DROP, -1, -1
7757 Xdrip_stretch, FALSE, FALSE,
7758 EL_AMOEBA_DROP, ACTION_FALLING, -1
7761 Xdrip_stretchB, FALSE, TRUE,
7762 EL_AMOEBA_DROP, ACTION_FALLING, -1
7765 Xdrip_eat, FALSE, FALSE,
7766 EL_AMOEBA_DROP, ACTION_GROWING, -1
7769 Ydrip_s1, FALSE, FALSE,
7770 EL_AMOEBA_DROP, ACTION_FALLING, -1
7773 Ydrip_s1B, FALSE, TRUE,
7774 EL_AMOEBA_DROP, ACTION_FALLING, -1
7777 Ydrip_s2, FALSE, FALSE,
7778 EL_AMOEBA_DROP, ACTION_FALLING, -1
7781 Ydrip_s2B, FALSE, TRUE,
7782 EL_AMOEBA_DROP, ACTION_FALLING, -1
7789 Xbomb_pause, FALSE, FALSE,
7793 Xbomb_fall, FALSE, FALSE,
7797 Ybomb_s, FALSE, FALSE,
7798 EL_BOMB, ACTION_FALLING, -1
7801 Ybomb_sB, FALSE, TRUE,
7802 EL_BOMB, ACTION_FALLING, -1
7805 Ybomb_e, FALSE, FALSE,
7806 EL_BOMB, ACTION_MOVING, MV_BIT_RIGHT
7809 Ybomb_eB, FALSE, TRUE,
7810 EL_BOMB, ACTION_MOVING, MV_BIT_RIGHT
7813 Ybomb_w, FALSE, FALSE,
7814 EL_BOMB, ACTION_MOVING, MV_BIT_LEFT
7817 Ybomb_wB, FALSE, TRUE,
7818 EL_BOMB, ACTION_MOVING, MV_BIT_LEFT
7821 Ybomb_eat, FALSE, FALSE,
7822 EL_BOMB, ACTION_ACTIVATING, -1
7825 Xballoon, TRUE, FALSE,
7829 Yballoon_n, FALSE, FALSE,
7830 EL_BALLOON, ACTION_MOVING, MV_BIT_UP
7833 Yballoon_nB, FALSE, TRUE,
7834 EL_BALLOON, ACTION_MOVING, MV_BIT_UP
7837 Yballoon_e, FALSE, FALSE,
7838 EL_BALLOON, ACTION_MOVING, MV_BIT_RIGHT
7841 Yballoon_eB, FALSE, TRUE,
7842 EL_BALLOON, ACTION_MOVING, MV_BIT_RIGHT
7845 Yballoon_s, FALSE, FALSE,
7846 EL_BALLOON, ACTION_MOVING, MV_BIT_DOWN
7849 Yballoon_sB, FALSE, TRUE,
7850 EL_BALLOON, ACTION_MOVING, MV_BIT_DOWN
7853 Yballoon_w, FALSE, FALSE,
7854 EL_BALLOON, ACTION_MOVING, MV_BIT_LEFT
7857 Yballoon_wB, FALSE, TRUE,
7858 EL_BALLOON, ACTION_MOVING, MV_BIT_LEFT
7861 Xgrass, TRUE, FALSE,
7862 EL_EMC_GRASS, -1, -1
7865 Ygrass_nB, FALSE, FALSE,
7866 EL_EMC_GRASS, ACTION_DIGGING, MV_BIT_UP
7869 Ygrass_eB, FALSE, FALSE,
7870 EL_EMC_GRASS, ACTION_DIGGING, MV_BIT_RIGHT
7873 Ygrass_sB, FALSE, FALSE,
7874 EL_EMC_GRASS, ACTION_DIGGING, MV_BIT_DOWN
7877 Ygrass_wB, FALSE, FALSE,
7878 EL_EMC_GRASS, ACTION_DIGGING, MV_BIT_LEFT
7885 Ydirt_nB, FALSE, FALSE,
7886 EL_SAND, ACTION_DIGGING, MV_BIT_UP
7889 Ydirt_eB, FALSE, FALSE,
7890 EL_SAND, ACTION_DIGGING, MV_BIT_RIGHT
7893 Ydirt_sB, FALSE, FALSE,
7894 EL_SAND, ACTION_DIGGING, MV_BIT_DOWN
7897 Ydirt_wB, FALSE, FALSE,
7898 EL_SAND, ACTION_DIGGING, MV_BIT_LEFT
7901 Xacid_ne, TRUE, FALSE,
7902 EL_ACID_POOL_TOPRIGHT, -1, -1
7905 Xacid_se, TRUE, FALSE,
7906 EL_ACID_POOL_BOTTOMRIGHT, -1, -1
7909 Xacid_s, TRUE, FALSE,
7910 EL_ACID_POOL_BOTTOM, -1, -1
7913 Xacid_sw, TRUE, FALSE,
7914 EL_ACID_POOL_BOTTOMLEFT, -1, -1
7917 Xacid_nw, TRUE, FALSE,
7918 EL_ACID_POOL_TOPLEFT, -1, -1
7921 Xacid_1, TRUE, FALSE,
7925 Xacid_2, FALSE, FALSE,
7929 Xacid_3, FALSE, FALSE,
7933 Xacid_4, FALSE, FALSE,
7937 Xacid_5, FALSE, FALSE,
7941 Xacid_6, FALSE, FALSE,
7945 Xacid_7, FALSE, FALSE,
7949 Xacid_8, FALSE, FALSE,
7953 Xball_1, TRUE, FALSE,
7954 EL_EMC_MAGIC_BALL, -1, -1
7957 Xball_1B, FALSE, FALSE,
7958 EL_EMC_MAGIC_BALL, ACTION_ACTIVE, -1
7961 Xball_2, FALSE, FALSE,
7962 EL_EMC_MAGIC_BALL, ACTION_ACTIVE, -1
7965 Xball_2B, FALSE, FALSE,
7966 EL_EMC_MAGIC_BALL, ACTION_ACTIVE, -1
7969 Yball_eat, FALSE, FALSE,
7970 EL_EMC_MAGIC_BALL, ACTION_DROPPING, -1
7973 Ykey_1_eat, FALSE, FALSE,
7974 EL_EM_KEY_1, ACTION_COLLECTING, -1
7977 Ykey_2_eat, FALSE, FALSE,
7978 EL_EM_KEY_2, ACTION_COLLECTING, -1
7981 Ykey_3_eat, FALSE, FALSE,
7982 EL_EM_KEY_3, ACTION_COLLECTING, -1
7985 Ykey_4_eat, FALSE, FALSE,
7986 EL_EM_KEY_4, ACTION_COLLECTING, -1
7989 Ykey_5_eat, FALSE, FALSE,
7990 EL_EMC_KEY_5, ACTION_COLLECTING, -1
7993 Ykey_6_eat, FALSE, FALSE,
7994 EL_EMC_KEY_6, ACTION_COLLECTING, -1
7997 Ykey_7_eat, FALSE, FALSE,
7998 EL_EMC_KEY_7, ACTION_COLLECTING, -1
8001 Ykey_8_eat, FALSE, FALSE,
8002 EL_EMC_KEY_8, ACTION_COLLECTING, -1
8005 Ylenses_eat, FALSE, FALSE,
8006 EL_EMC_LENSES, ACTION_COLLECTING, -1
8009 Ymagnify_eat, FALSE, FALSE,
8010 EL_EMC_MAGNIFIER, ACTION_COLLECTING, -1
8013 Ygrass_eat, FALSE, FALSE,
8014 EL_EMC_GRASS, ACTION_SNAPPING, -1
8017 Ydirt_eat, FALSE, FALSE,
8018 EL_SAND, ACTION_SNAPPING, -1
8021 Xgrow_ns, TRUE, FALSE,
8022 EL_EXPANDABLE_WALL_VERTICAL, -1, -1
8025 Ygrow_ns_eat, FALSE, FALSE,
8026 EL_EXPANDABLE_WALL_VERTICAL, ACTION_GROWING, -1
8029 Xgrow_ew, TRUE, FALSE,
8030 EL_EXPANDABLE_WALL_HORIZONTAL, -1, -1
8033 Ygrow_ew_eat, FALSE, FALSE,
8034 EL_EXPANDABLE_WALL_HORIZONTAL, ACTION_GROWING, -1
8037 Xwonderwall, TRUE, FALSE,
8038 EL_MAGIC_WALL, -1, -1
8041 XwonderwallB, FALSE, FALSE,
8042 EL_MAGIC_WALL, ACTION_ACTIVE, -1
8045 Xamoeba_1, TRUE, FALSE,
8046 EL_AMOEBA_DRY, ACTION_OTHER, -1
8049 Xamoeba_2, FALSE, FALSE,
8050 EL_AMOEBA_DRY, ACTION_OTHER, -1
8053 Xamoeba_3, FALSE, FALSE,
8054 EL_AMOEBA_DRY, ACTION_OTHER, -1
8057 Xamoeba_4, FALSE, FALSE,
8058 EL_AMOEBA_DRY, ACTION_OTHER, -1
8061 Xamoeba_5, TRUE, FALSE,
8062 EL_AMOEBA_WET, ACTION_OTHER, -1
8065 Xamoeba_6, FALSE, FALSE,
8066 EL_AMOEBA_WET, ACTION_OTHER, -1
8069 Xamoeba_7, FALSE, FALSE,
8070 EL_AMOEBA_WET, ACTION_OTHER, -1
8073 Xamoeba_8, FALSE, FALSE,
8074 EL_AMOEBA_WET, ACTION_OTHER, -1
8077 Xdoor_1, TRUE, FALSE,
8078 EL_EM_GATE_1, -1, -1
8081 Xdoor_2, TRUE, FALSE,
8082 EL_EM_GATE_2, -1, -1
8085 Xdoor_3, TRUE, FALSE,
8086 EL_EM_GATE_3, -1, -1
8089 Xdoor_4, TRUE, FALSE,
8090 EL_EM_GATE_4, -1, -1
8093 Xdoor_5, TRUE, FALSE,
8094 EL_EMC_GATE_5, -1, -1
8097 Xdoor_6, TRUE, FALSE,
8098 EL_EMC_GATE_6, -1, -1
8101 Xdoor_7, TRUE, FALSE,
8102 EL_EMC_GATE_7, -1, -1
8105 Xdoor_8, TRUE, FALSE,
8106 EL_EMC_GATE_8, -1, -1
8109 Xkey_1, TRUE, FALSE,
8113 Xkey_2, TRUE, FALSE,
8117 Xkey_3, TRUE, FALSE,
8121 Xkey_4, TRUE, FALSE,
8125 Xkey_5, TRUE, FALSE,
8126 EL_EMC_KEY_5, -1, -1
8129 Xkey_6, TRUE, FALSE,
8130 EL_EMC_KEY_6, -1, -1
8133 Xkey_7, TRUE, FALSE,
8134 EL_EMC_KEY_7, -1, -1
8137 Xkey_8, TRUE, FALSE,
8138 EL_EMC_KEY_8, -1, -1
8141 Xwind_n, TRUE, FALSE,
8142 EL_BALLOON_SWITCH_UP, -1, -1
8145 Xwind_e, TRUE, FALSE,
8146 EL_BALLOON_SWITCH_RIGHT, -1, -1
8149 Xwind_s, TRUE, FALSE,
8150 EL_BALLOON_SWITCH_DOWN, -1, -1
8153 Xwind_w, TRUE, FALSE,
8154 EL_BALLOON_SWITCH_LEFT, -1, -1
8157 Xwind_nesw, TRUE, FALSE,
8158 EL_BALLOON_SWITCH_ANY, -1, -1
8161 Xwind_stop, TRUE, FALSE,
8162 EL_BALLOON_SWITCH_NONE, -1, -1
8166 EL_EM_EXIT_CLOSED, -1, -1
8169 Xexit_1, TRUE, FALSE,
8170 EL_EM_EXIT_OPEN, -1, -1
8173 Xexit_2, FALSE, FALSE,
8174 EL_EM_EXIT_OPEN, -1, -1
8177 Xexit_3, FALSE, FALSE,
8178 EL_EM_EXIT_OPEN, -1, -1
8181 Xdynamite, TRUE, FALSE,
8182 EL_EM_DYNAMITE, -1, -1
8185 Ydynamite_eat, FALSE, FALSE,
8186 EL_EM_DYNAMITE, ACTION_COLLECTING, -1
8189 Xdynamite_1, TRUE, FALSE,
8190 EL_EM_DYNAMITE_ACTIVE, -1, -1
8193 Xdynamite_2, FALSE, FALSE,
8194 EL_EM_DYNAMITE_ACTIVE, -1, -1
8197 Xdynamite_3, FALSE, FALSE,
8198 EL_EM_DYNAMITE_ACTIVE, -1, -1
8201 Xdynamite_4, FALSE, FALSE,
8202 EL_EM_DYNAMITE_ACTIVE, -1, -1
8205 Xbumper, TRUE, FALSE,
8206 EL_EMC_SPRING_BUMPER, -1, -1
8209 XbumperB, FALSE, FALSE,
8210 EL_EMC_SPRING_BUMPER, ACTION_ACTIVE, -1
8213 Xwheel, TRUE, FALSE,
8214 EL_ROBOT_WHEEL, -1, -1
8217 XwheelB, FALSE, FALSE,
8218 EL_ROBOT_WHEEL, ACTION_ACTIVE, -1
8221 Xswitch, TRUE, FALSE,
8222 EL_EMC_MAGIC_BALL_SWITCH, -1, -1
8225 XswitchB, FALSE, FALSE,
8226 EL_EMC_MAGIC_BALL_SWITCH, ACTION_ACTIVE, -1
8230 EL_QUICKSAND_EMPTY, -1, -1
8233 Xsand_stone, TRUE, FALSE,
8234 EL_QUICKSAND_FULL, -1, -1
8237 Xsand_stonein_1, FALSE, TRUE,
8238 EL_ROCK, ACTION_FILLING, -1
8241 Xsand_stonein_2, FALSE, TRUE,
8242 EL_ROCK, ACTION_FILLING, -1
8245 Xsand_stonein_3, FALSE, TRUE,
8246 EL_ROCK, ACTION_FILLING, -1
8249 Xsand_stonein_4, FALSE, TRUE,
8250 EL_ROCK, ACTION_FILLING, -1
8254 Xsand_stonesand_1, FALSE, FALSE,
8255 EL_QUICKSAND_EMPTYING, -1, -1
8258 Xsand_stonesand_2, FALSE, FALSE,
8259 EL_QUICKSAND_EMPTYING, -1, -1
8262 Xsand_stonesand_3, FALSE, FALSE,
8263 EL_QUICKSAND_EMPTYING, -1, -1
8266 Xsand_stonesand_4, FALSE, FALSE,
8267 EL_QUICKSAND_EMPTYING, -1, -1
8270 Xsand_stonesand_quickout_1, FALSE, FALSE,
8271 EL_QUICKSAND_EMPTYING, -1, -1
8274 Xsand_stonesand_quickout_2, FALSE, FALSE,
8275 EL_QUICKSAND_EMPTYING, -1, -1
8279 Xsand_stonesand_1, FALSE, FALSE,
8280 EL_QUICKSAND_FULL, -1, -1
8283 Xsand_stonesand_2, FALSE, FALSE,
8284 EL_QUICKSAND_FULL, -1, -1
8287 Xsand_stonesand_3, FALSE, FALSE,
8288 EL_QUICKSAND_FULL, -1, -1
8291 Xsand_stonesand_4, FALSE, FALSE,
8292 EL_QUICKSAND_FULL, -1, -1
8296 Xsand_stoneout_1, FALSE, FALSE,
8297 EL_ROCK, ACTION_EMPTYING, -1
8300 Xsand_stoneout_2, FALSE, FALSE,
8301 EL_ROCK, ACTION_EMPTYING, -1
8305 Xsand_sandstone_1, FALSE, FALSE,
8306 EL_QUICKSAND_FILLING, -1, -1
8309 Xsand_sandstone_2, FALSE, FALSE,
8310 EL_QUICKSAND_FILLING, -1, -1
8313 Xsand_sandstone_3, FALSE, FALSE,
8314 EL_QUICKSAND_FILLING, -1, -1
8317 Xsand_sandstone_4, FALSE, FALSE,
8318 EL_QUICKSAND_FILLING, -1, -1
8322 Xsand_sandstone_1, FALSE, FALSE,
8323 EL_QUICKSAND_FULL, -1, -1
8326 Xsand_sandstone_2, FALSE, FALSE,
8327 EL_QUICKSAND_FULL, -1, -1
8330 Xsand_sandstone_3, FALSE, FALSE,
8331 EL_QUICKSAND_FULL, -1, -1
8334 Xsand_sandstone_4, FALSE, FALSE,
8335 EL_QUICKSAND_FULL, -1, -1
8339 Xplant, TRUE, FALSE,
8340 EL_EMC_PLANT, -1, -1
8343 Yplant, FALSE, FALSE,
8344 EL_EMC_PLANT, -1, -1
8347 Xlenses, TRUE, FALSE,
8348 EL_EMC_LENSES, -1, -1
8351 Xmagnify, TRUE, FALSE,
8352 EL_EMC_MAGNIFIER, -1, -1
8355 Xdripper, TRUE, FALSE,
8356 EL_EMC_DRIPPER, -1, -1
8359 XdripperB, FALSE, FALSE,
8360 EL_EMC_DRIPPER, ACTION_ACTIVE, -1
8363 Xfake_blank, TRUE, FALSE,
8364 EL_INVISIBLE_WALL, -1, -1
8367 Xfake_blankB, FALSE, FALSE,
8368 EL_INVISIBLE_WALL, ACTION_ACTIVE, -1
8371 Xfake_grass, TRUE, FALSE,
8372 EL_EMC_FAKE_GRASS, -1, -1
8375 Xfake_grassB, FALSE, FALSE,
8376 EL_EMC_FAKE_GRASS, ACTION_ACTIVE, -1
8379 Xfake_door_1, TRUE, FALSE,
8380 EL_EM_GATE_1_GRAY, -1, -1
8383 Xfake_door_2, TRUE, FALSE,
8384 EL_EM_GATE_2_GRAY, -1, -1
8387 Xfake_door_3, TRUE, FALSE,
8388 EL_EM_GATE_3_GRAY, -1, -1
8391 Xfake_door_4, TRUE, FALSE,
8392 EL_EM_GATE_4_GRAY, -1, -1
8395 Xfake_door_5, TRUE, FALSE,
8396 EL_EMC_GATE_5_GRAY, -1, -1
8399 Xfake_door_6, TRUE, FALSE,
8400 EL_EMC_GATE_6_GRAY, -1, -1
8403 Xfake_door_7, TRUE, FALSE,
8404 EL_EMC_GATE_7_GRAY, -1, -1
8407 Xfake_door_8, TRUE, FALSE,
8408 EL_EMC_GATE_8_GRAY, -1, -1
8411 Xfake_acid_1, TRUE, FALSE,
8412 EL_EMC_FAKE_ACID, -1, -1
8415 Xfake_acid_2, FALSE, FALSE,
8416 EL_EMC_FAKE_ACID, -1, -1
8419 Xfake_acid_3, FALSE, FALSE,
8420 EL_EMC_FAKE_ACID, -1, -1
8423 Xfake_acid_4, FALSE, FALSE,
8424 EL_EMC_FAKE_ACID, -1, -1
8427 Xfake_acid_5, FALSE, FALSE,
8428 EL_EMC_FAKE_ACID, -1, -1
8431 Xfake_acid_6, FALSE, FALSE,
8432 EL_EMC_FAKE_ACID, -1, -1
8435 Xfake_acid_7, FALSE, FALSE,
8436 EL_EMC_FAKE_ACID, -1, -1
8439 Xfake_acid_8, FALSE, FALSE,
8440 EL_EMC_FAKE_ACID, -1, -1
8443 Xsteel_1, TRUE, FALSE,
8444 EL_STEELWALL, -1, -1
8447 Xsteel_2, TRUE, FALSE,
8448 EL_EMC_STEELWALL_2, -1, -1
8451 Xsteel_3, TRUE, FALSE,
8452 EL_EMC_STEELWALL_3, -1, -1
8455 Xsteel_4, TRUE, FALSE,
8456 EL_EMC_STEELWALL_4, -1, -1
8459 Xwall_1, TRUE, FALSE,
8463 Xwall_2, TRUE, FALSE,
8464 EL_EMC_WALL_14, -1, -1
8467 Xwall_3, TRUE, FALSE,
8468 EL_EMC_WALL_15, -1, -1
8471 Xwall_4, TRUE, FALSE,
8472 EL_EMC_WALL_16, -1, -1
8475 Xround_wall_1, TRUE, FALSE,
8476 EL_WALL_SLIPPERY, -1, -1
8479 Xround_wall_2, TRUE, FALSE,
8480 EL_EMC_WALL_SLIPPERY_2, -1, -1
8483 Xround_wall_3, TRUE, FALSE,
8484 EL_EMC_WALL_SLIPPERY_3, -1, -1
8487 Xround_wall_4, TRUE, FALSE,
8488 EL_EMC_WALL_SLIPPERY_4, -1, -1
8491 Xdecor_1, TRUE, FALSE,
8492 EL_EMC_WALL_8, -1, -1
8495 Xdecor_2, TRUE, FALSE,
8496 EL_EMC_WALL_6, -1, -1
8499 Xdecor_3, TRUE, FALSE,
8500 EL_EMC_WALL_4, -1, -1
8503 Xdecor_4, TRUE, FALSE,
8504 EL_EMC_WALL_7, -1, -1
8507 Xdecor_5, TRUE, FALSE,
8508 EL_EMC_WALL_5, -1, -1
8511 Xdecor_6, TRUE, FALSE,
8512 EL_EMC_WALL_9, -1, -1
8515 Xdecor_7, TRUE, FALSE,
8516 EL_EMC_WALL_10, -1, -1
8519 Xdecor_8, TRUE, FALSE,
8520 EL_EMC_WALL_1, -1, -1
8523 Xdecor_9, TRUE, FALSE,
8524 EL_EMC_WALL_2, -1, -1
8527 Xdecor_10, TRUE, FALSE,
8528 EL_EMC_WALL_3, -1, -1
8531 Xdecor_11, TRUE, FALSE,
8532 EL_EMC_WALL_11, -1, -1
8535 Xdecor_12, TRUE, FALSE,
8536 EL_EMC_WALL_12, -1, -1
8539 Xalpha_0, TRUE, FALSE,
8540 EL_CHAR('0'), -1, -1
8543 Xalpha_1, TRUE, FALSE,
8544 EL_CHAR('1'), -1, -1
8547 Xalpha_2, TRUE, FALSE,
8548 EL_CHAR('2'), -1, -1
8551 Xalpha_3, TRUE, FALSE,
8552 EL_CHAR('3'), -1, -1
8555 Xalpha_4, TRUE, FALSE,
8556 EL_CHAR('4'), -1, -1
8559 Xalpha_5, TRUE, FALSE,
8560 EL_CHAR('5'), -1, -1
8563 Xalpha_6, TRUE, FALSE,
8564 EL_CHAR('6'), -1, -1
8567 Xalpha_7, TRUE, FALSE,
8568 EL_CHAR('7'), -1, -1
8571 Xalpha_8, TRUE, FALSE,
8572 EL_CHAR('8'), -1, -1
8575 Xalpha_9, TRUE, FALSE,
8576 EL_CHAR('9'), -1, -1
8579 Xalpha_excla, TRUE, FALSE,
8580 EL_CHAR('!'), -1, -1
8583 Xalpha_quote, TRUE, FALSE,
8584 EL_CHAR('"'), -1, -1
8587 Xalpha_comma, TRUE, FALSE,
8588 EL_CHAR(','), -1, -1
8591 Xalpha_minus, TRUE, FALSE,
8592 EL_CHAR('-'), -1, -1
8595 Xalpha_perio, TRUE, FALSE,
8596 EL_CHAR('.'), -1, -1
8599 Xalpha_colon, TRUE, FALSE,
8600 EL_CHAR(':'), -1, -1
8603 Xalpha_quest, TRUE, FALSE,
8604 EL_CHAR('?'), -1, -1
8607 Xalpha_a, TRUE, FALSE,
8608 EL_CHAR('A'), -1, -1
8611 Xalpha_b, TRUE, FALSE,
8612 EL_CHAR('B'), -1, -1
8615 Xalpha_c, TRUE, FALSE,
8616 EL_CHAR('C'), -1, -1
8619 Xalpha_d, TRUE, FALSE,
8620 EL_CHAR('D'), -1, -1
8623 Xalpha_e, TRUE, FALSE,
8624 EL_CHAR('E'), -1, -1
8627 Xalpha_f, TRUE, FALSE,
8628 EL_CHAR('F'), -1, -1
8631 Xalpha_g, TRUE, FALSE,
8632 EL_CHAR('G'), -1, -1
8635 Xalpha_h, TRUE, FALSE,
8636 EL_CHAR('H'), -1, -1
8639 Xalpha_i, TRUE, FALSE,
8640 EL_CHAR('I'), -1, -1
8643 Xalpha_j, TRUE, FALSE,
8644 EL_CHAR('J'), -1, -1
8647 Xalpha_k, TRUE, FALSE,
8648 EL_CHAR('K'), -1, -1
8651 Xalpha_l, TRUE, FALSE,
8652 EL_CHAR('L'), -1, -1
8655 Xalpha_m, TRUE, FALSE,
8656 EL_CHAR('M'), -1, -1
8659 Xalpha_n, TRUE, FALSE,
8660 EL_CHAR('N'), -1, -1
8663 Xalpha_o, TRUE, FALSE,
8664 EL_CHAR('O'), -1, -1
8667 Xalpha_p, TRUE, FALSE,
8668 EL_CHAR('P'), -1, -1
8671 Xalpha_q, TRUE, FALSE,
8672 EL_CHAR('Q'), -1, -1
8675 Xalpha_r, TRUE, FALSE,
8676 EL_CHAR('R'), -1, -1
8679 Xalpha_s, TRUE, FALSE,
8680 EL_CHAR('S'), -1, -1
8683 Xalpha_t, TRUE, FALSE,
8684 EL_CHAR('T'), -1, -1
8687 Xalpha_u, TRUE, FALSE,
8688 EL_CHAR('U'), -1, -1
8691 Xalpha_v, TRUE, FALSE,
8692 EL_CHAR('V'), -1, -1
8695 Xalpha_w, TRUE, FALSE,
8696 EL_CHAR('W'), -1, -1
8699 Xalpha_x, TRUE, FALSE,
8700 EL_CHAR('X'), -1, -1
8703 Xalpha_y, TRUE, FALSE,
8704 EL_CHAR('Y'), -1, -1
8707 Xalpha_z, TRUE, FALSE,
8708 EL_CHAR('Z'), -1, -1
8711 Xalpha_arrow_e, TRUE, FALSE,
8712 EL_CHAR('>'), -1, -1
8715 Xalpha_arrow_w, TRUE, FALSE,
8716 EL_CHAR('<'), -1, -1
8719 Xalpha_copyr, TRUE, FALSE,
8720 EL_CHAR('©'), -1, -1
8724 Xboom_bug, FALSE, FALSE,
8725 EL_BUG, ACTION_EXPLODING, -1
8728 Xboom_bomb, FALSE, FALSE,
8729 EL_BOMB, ACTION_EXPLODING, -1
8732 Xboom_android, FALSE, FALSE,
8733 EL_EMC_ANDROID, ACTION_OTHER, -1
8736 Xboom_1, FALSE, FALSE,
8737 EL_DEFAULT, ACTION_EXPLODING, -1
8740 Xboom_2, FALSE, FALSE,
8741 EL_DEFAULT, ACTION_EXPLODING, -1
8744 Znormal, FALSE, FALSE,
8748 Zdynamite, FALSE, FALSE,
8752 Zplayer, FALSE, FALSE,
8756 ZBORDER, FALSE, FALSE,
8766 static struct Mapping_EM_to_RND_player
8775 em_player_mapping_list[] =
8779 EL_PLAYER_1, ACTION_MOVING, MV_BIT_UP,
8783 EL_PLAYER_1, ACTION_MOVING, MV_BIT_RIGHT,
8787 EL_PLAYER_1, ACTION_MOVING, MV_BIT_DOWN,
8791 EL_PLAYER_1, ACTION_MOVING, MV_BIT_LEFT,
8795 EL_PLAYER_1, ACTION_PUSHING, MV_BIT_UP,
8799 EL_PLAYER_1, ACTION_PUSHING, MV_BIT_RIGHT,
8803 EL_PLAYER_1, ACTION_PUSHING, MV_BIT_DOWN,
8807 EL_PLAYER_1, ACTION_PUSHING, MV_BIT_LEFT,
8811 EL_PLAYER_1, ACTION_SNAPPING, MV_BIT_UP,
8815 EL_PLAYER_1, ACTION_SNAPPING, MV_BIT_RIGHT,
8819 EL_PLAYER_1, ACTION_SNAPPING, MV_BIT_DOWN,
8823 EL_PLAYER_1, ACTION_SNAPPING, MV_BIT_LEFT,
8827 EL_PLAYER_2, ACTION_MOVING, MV_BIT_UP,
8831 EL_PLAYER_2, ACTION_MOVING, MV_BIT_RIGHT,
8835 EL_PLAYER_2, ACTION_MOVING, MV_BIT_DOWN,
8839 EL_PLAYER_2, ACTION_MOVING, MV_BIT_LEFT,
8843 EL_PLAYER_2, ACTION_PUSHING, MV_BIT_UP,
8847 EL_PLAYER_2, ACTION_PUSHING, MV_BIT_RIGHT,
8851 EL_PLAYER_2, ACTION_PUSHING, MV_BIT_DOWN,
8855 EL_PLAYER_2, ACTION_PUSHING, MV_BIT_LEFT,
8859 EL_PLAYER_2, ACTION_SNAPPING, MV_BIT_UP,
8863 EL_PLAYER_2, ACTION_SNAPPING, MV_BIT_RIGHT,
8867 EL_PLAYER_2, ACTION_SNAPPING, MV_BIT_DOWN,
8871 EL_PLAYER_2, ACTION_SNAPPING, MV_BIT_LEFT,
8875 EL_PLAYER_1, ACTION_DEFAULT, -1,
8879 EL_PLAYER_2, ACTION_DEFAULT, -1,
8883 EL_PLAYER_3, ACTION_MOVING, MV_BIT_UP,
8887 EL_PLAYER_3, ACTION_MOVING, MV_BIT_RIGHT,
8891 EL_PLAYER_3, ACTION_MOVING, MV_BIT_DOWN,
8895 EL_PLAYER_3, ACTION_MOVING, MV_BIT_LEFT,
8899 EL_PLAYER_3, ACTION_PUSHING, MV_BIT_UP,
8903 EL_PLAYER_3, ACTION_PUSHING, MV_BIT_RIGHT,
8907 EL_PLAYER_3, ACTION_PUSHING, MV_BIT_DOWN,
8911 EL_PLAYER_3, ACTION_PUSHING, MV_BIT_LEFT,
8915 EL_PLAYER_3, ACTION_SNAPPING, MV_BIT_UP,
8919 EL_PLAYER_3, ACTION_SNAPPING, MV_BIT_RIGHT,
8923 EL_PLAYER_3, ACTION_SNAPPING, MV_BIT_DOWN,
8927 EL_PLAYER_3, ACTION_SNAPPING, MV_BIT_LEFT,
8931 EL_PLAYER_4, ACTION_MOVING, MV_BIT_UP,
8935 EL_PLAYER_4, ACTION_MOVING, MV_BIT_RIGHT,
8939 EL_PLAYER_4, ACTION_MOVING, MV_BIT_DOWN,
8943 EL_PLAYER_4, ACTION_MOVING, MV_BIT_LEFT,
8947 EL_PLAYER_4, ACTION_PUSHING, MV_BIT_UP,
8951 EL_PLAYER_4, ACTION_PUSHING, MV_BIT_RIGHT,
8955 EL_PLAYER_4, ACTION_PUSHING, MV_BIT_DOWN,
8959 EL_PLAYER_4, ACTION_PUSHING, MV_BIT_LEFT,
8963 EL_PLAYER_4, ACTION_SNAPPING, MV_BIT_UP,
8967 EL_PLAYER_4, ACTION_SNAPPING, MV_BIT_RIGHT,
8971 EL_PLAYER_4, ACTION_SNAPPING, MV_BIT_DOWN,
8975 EL_PLAYER_4, ACTION_SNAPPING, MV_BIT_LEFT,
8979 EL_PLAYER_3, ACTION_DEFAULT, -1,
8983 EL_PLAYER_4, ACTION_DEFAULT, -1,
8992 int map_element_RND_to_EM(int element_rnd)
8994 static unsigned short mapping_RND_to_EM[NUM_FILE_ELEMENTS];
8995 static boolean mapping_initialized = FALSE;
8997 if (!mapping_initialized)
9001 /* return "Xalpha_quest" for all undefined elements in mapping array */
9002 for (i = 0; i < NUM_FILE_ELEMENTS; i++)
9003 mapping_RND_to_EM[i] = Xalpha_quest;
9005 for (i = 0; em_object_mapping_list[i].element_em != -1; i++)
9006 if (em_object_mapping_list[i].is_rnd_to_em_mapping)
9007 mapping_RND_to_EM[em_object_mapping_list[i].element_rnd] =
9008 em_object_mapping_list[i].element_em;
9010 mapping_initialized = TRUE;
9013 if (element_rnd >= 0 && element_rnd < NUM_FILE_ELEMENTS)
9014 return mapping_RND_to_EM[element_rnd];
9016 Error(ERR_WARN, "invalid RND level element %d", element_rnd);
9021 int map_element_EM_to_RND(int element_em)
9023 static unsigned short mapping_EM_to_RND[TILE_MAX];
9024 static boolean mapping_initialized = FALSE;
9026 if (!mapping_initialized)
9030 /* return "EL_UNKNOWN" for all undefined elements in mapping array */
9031 for (i = 0; i < TILE_MAX; i++)
9032 mapping_EM_to_RND[i] = EL_UNKNOWN;
9034 for (i = 0; em_object_mapping_list[i].element_em != -1; i++)
9035 mapping_EM_to_RND[em_object_mapping_list[i].element_em] =
9036 em_object_mapping_list[i].element_rnd;
9038 mapping_initialized = TRUE;
9041 if (element_em >= 0 && element_em < TILE_MAX)
9042 return mapping_EM_to_RND[element_em];
9044 Error(ERR_WARN, "invalid EM level element %d", element_em);
9049 void map_android_clone_elements_RND_to_EM(struct LevelInfo *level)
9051 struct LevelInfo_EM *level_em = level->native_em_level;
9052 struct LEVEL *lev = level_em->lev;
9055 for (i = 0; i < TILE_MAX; i++)
9056 lev->android_array[i] = Xblank;
9058 for (i = 0; i < level->num_android_clone_elements; i++)
9060 int element_rnd = level->android_clone_element[i];
9061 int element_em = map_element_RND_to_EM(element_rnd);
9063 for (j = 0; em_object_mapping_list[j].element_em != -1; j++)
9064 if (em_object_mapping_list[j].element_rnd == element_rnd)
9065 lev->android_array[em_object_mapping_list[j].element_em] = element_em;
9069 void map_android_clone_elements_EM_to_RND(struct LevelInfo *level)
9071 struct LevelInfo_EM *level_em = level->native_em_level;
9072 struct LEVEL *lev = level_em->lev;
9075 level->num_android_clone_elements = 0;
9077 for (i = 0; i < TILE_MAX; i++)
9079 int element_em = lev->android_array[i];
9081 boolean element_found = FALSE;
9083 if (element_em == Xblank)
9086 element_rnd = map_element_EM_to_RND(element_em);
9088 for (j = 0; j < level->num_android_clone_elements; j++)
9089 if (level->android_clone_element[j] == element_rnd)
9090 element_found = TRUE;
9094 level->android_clone_element[level->num_android_clone_elements++] =
9097 if (level->num_android_clone_elements == MAX_ANDROID_ELEMENTS)
9102 if (level->num_android_clone_elements == 0)
9104 level->num_android_clone_elements = 1;
9105 level->android_clone_element[0] = EL_EMPTY;
9109 int map_direction_RND_to_EM(int direction)
9111 return (direction == MV_UP ? 0 :
9112 direction == MV_RIGHT ? 1 :
9113 direction == MV_DOWN ? 2 :
9114 direction == MV_LEFT ? 3 :
9118 int map_direction_EM_to_RND(int direction)
9120 return (direction == 0 ? MV_UP :
9121 direction == 1 ? MV_RIGHT :
9122 direction == 2 ? MV_DOWN :
9123 direction == 3 ? MV_LEFT :
9127 int map_element_RND_to_SP(int element_rnd)
9129 int element_sp = 0x20; /* map unknown elements to yellow "hardware" */
9131 if (element_rnd >= EL_SP_START &&
9132 element_rnd <= EL_SP_END)
9133 element_sp = element_rnd - EL_SP_START;
9134 else if (element_rnd == EL_EMPTY_SPACE)
9136 else if (element_rnd == EL_INVISIBLE_WALL)
9142 int map_element_SP_to_RND(int element_sp)
9144 int element_rnd = EL_UNKNOWN;
9146 if (element_sp >= 0x00 &&
9148 element_rnd = EL_SP_START + element_sp;
9149 else if (element_sp == 0x28)
9150 element_rnd = EL_INVISIBLE_WALL;
9155 int map_action_SP_to_RND(int action_sp)
9159 case actActive: return ACTION_ACTIVE;
9160 case actImpact: return ACTION_IMPACT;
9161 case actExploding: return ACTION_EXPLODING;
9162 case actDigging: return ACTION_DIGGING;
9163 case actSnapping: return ACTION_SNAPPING;
9164 case actCollecting: return ACTION_COLLECTING;
9165 case actPassing: return ACTION_PASSING;
9166 case actPushing: return ACTION_PUSHING;
9167 case actDropping: return ACTION_DROPPING;
9169 default: return ACTION_DEFAULT;
9173 int get_next_element(int element)
9177 case EL_QUICKSAND_FILLING: return EL_QUICKSAND_FULL;
9178 case EL_QUICKSAND_EMPTYING: return EL_QUICKSAND_EMPTY;
9179 case EL_QUICKSAND_FAST_FILLING: return EL_QUICKSAND_FAST_FULL;
9180 case EL_QUICKSAND_FAST_EMPTYING: return EL_QUICKSAND_FAST_EMPTY;
9181 case EL_MAGIC_WALL_FILLING: return EL_MAGIC_WALL_FULL;
9182 case EL_MAGIC_WALL_EMPTYING: return EL_MAGIC_WALL_ACTIVE;
9183 case EL_BD_MAGIC_WALL_FILLING: return EL_BD_MAGIC_WALL_FULL;
9184 case EL_BD_MAGIC_WALL_EMPTYING: return EL_BD_MAGIC_WALL_ACTIVE;
9185 case EL_DC_MAGIC_WALL_FILLING: return EL_DC_MAGIC_WALL_FULL;
9186 case EL_DC_MAGIC_WALL_EMPTYING: return EL_DC_MAGIC_WALL_ACTIVE;
9187 case EL_AMOEBA_DROPPING: return EL_AMOEBA_WET;
9189 default: return element;
9194 int el_act_dir2img(int element, int action, int direction)
9196 element = GFX_ELEMENT(element);
9198 if (direction == MV_NONE)
9199 return element_info[element].graphic[action];
9201 direction = MV_DIR_TO_BIT(direction);
9203 return element_info[element].direction_graphic[action][direction];
9206 int el_act_dir2img(int element, int action, int direction)
9208 element = GFX_ELEMENT(element);
9209 direction = MV_DIR_TO_BIT(direction); /* default: MV_NONE => MV_DOWN */
9211 /* direction_graphic[][] == graphic[] for undefined direction graphics */
9212 return element_info[element].direction_graphic[action][direction];
9217 static int el_act_dir2crm(int element, int action, int direction)
9219 element = GFX_ELEMENT(element);
9221 if (direction == MV_NONE)
9222 return element_info[element].crumbled[action];
9224 direction = MV_DIR_TO_BIT(direction);
9226 return element_info[element].direction_crumbled[action][direction];
9229 static int el_act_dir2crm(int element, int action, int direction)
9231 element = GFX_ELEMENT(element);
9232 direction = MV_DIR_TO_BIT(direction); /* default: MV_NONE => MV_DOWN */
9234 /* direction_graphic[][] == graphic[] for undefined direction graphics */
9235 return element_info[element].direction_crumbled[action][direction];
9239 int el_act2img(int element, int action)
9241 element = GFX_ELEMENT(element);
9243 return element_info[element].graphic[action];
9246 int el_act2crm(int element, int action)
9248 element = GFX_ELEMENT(element);
9250 return element_info[element].crumbled[action];
9253 int el_dir2img(int element, int direction)
9255 element = GFX_ELEMENT(element);
9257 return el_act_dir2img(element, ACTION_DEFAULT, direction);
9260 int el2baseimg(int element)
9262 return element_info[element].graphic[ACTION_DEFAULT];
9265 int el2img(int element)
9267 element = GFX_ELEMENT(element);
9269 return element_info[element].graphic[ACTION_DEFAULT];
9272 int el2edimg(int element)
9274 element = GFX_ELEMENT(element);
9276 return element_info[element].special_graphic[GFX_SPECIAL_ARG_EDITOR];
9279 int el2preimg(int element)
9281 element = GFX_ELEMENT(element);
9283 return element_info[element].special_graphic[GFX_SPECIAL_ARG_PREVIEW];
9286 int el2panelimg(int element)
9288 element = GFX_ELEMENT(element);
9290 return element_info[element].special_graphic[GFX_SPECIAL_ARG_PANEL];
9293 int font2baseimg(int font_nr)
9295 return font_info[font_nr].special_graphic[GFX_SPECIAL_ARG_DEFAULT];
9298 int getBeltNrFromBeltElement(int element)
9300 return (element < EL_CONVEYOR_BELT_2_LEFT ? 0 :
9301 element < EL_CONVEYOR_BELT_3_LEFT ? 1 :
9302 element < EL_CONVEYOR_BELT_4_LEFT ? 2 : 3);
9305 int getBeltNrFromBeltActiveElement(int element)
9307 return (element < EL_CONVEYOR_BELT_2_LEFT_ACTIVE ? 0 :
9308 element < EL_CONVEYOR_BELT_3_LEFT_ACTIVE ? 1 :
9309 element < EL_CONVEYOR_BELT_4_LEFT_ACTIVE ? 2 : 3);
9312 int getBeltNrFromBeltSwitchElement(int element)
9314 return (element < EL_CONVEYOR_BELT_2_SWITCH_LEFT ? 0 :
9315 element < EL_CONVEYOR_BELT_3_SWITCH_LEFT ? 1 :
9316 element < EL_CONVEYOR_BELT_4_SWITCH_LEFT ? 2 : 3);
9319 int getBeltDirNrFromBeltElement(int element)
9321 static int belt_base_element[4] =
9323 EL_CONVEYOR_BELT_1_LEFT,
9324 EL_CONVEYOR_BELT_2_LEFT,
9325 EL_CONVEYOR_BELT_3_LEFT,
9326 EL_CONVEYOR_BELT_4_LEFT
9329 int belt_nr = getBeltNrFromBeltElement(element);
9330 int belt_dir_nr = element - belt_base_element[belt_nr];
9332 return (belt_dir_nr % 3);
9335 int getBeltDirNrFromBeltSwitchElement(int element)
9337 static int belt_base_element[4] =
9339 EL_CONVEYOR_BELT_1_SWITCH_LEFT,
9340 EL_CONVEYOR_BELT_2_SWITCH_LEFT,
9341 EL_CONVEYOR_BELT_3_SWITCH_LEFT,
9342 EL_CONVEYOR_BELT_4_SWITCH_LEFT
9345 int belt_nr = getBeltNrFromBeltSwitchElement(element);
9346 int belt_dir_nr = element - belt_base_element[belt_nr];
9348 return (belt_dir_nr % 3);
9351 int getBeltDirFromBeltElement(int element)
9353 static int belt_move_dir[3] =
9360 int belt_dir_nr = getBeltDirNrFromBeltElement(element);
9362 return belt_move_dir[belt_dir_nr];
9365 int getBeltDirFromBeltSwitchElement(int element)
9367 static int belt_move_dir[3] =
9374 int belt_dir_nr = getBeltDirNrFromBeltSwitchElement(element);
9376 return belt_move_dir[belt_dir_nr];
9379 int getBeltElementFromBeltNrAndBeltDirNr(int belt_nr, int belt_dir_nr)
9381 static int belt_base_element[4] =
9383 EL_CONVEYOR_BELT_1_LEFT,
9384 EL_CONVEYOR_BELT_2_LEFT,
9385 EL_CONVEYOR_BELT_3_LEFT,
9386 EL_CONVEYOR_BELT_4_LEFT
9389 return belt_base_element[belt_nr] + belt_dir_nr;
9392 int getBeltElementFromBeltNrAndBeltDir(int belt_nr, int belt_dir)
9394 int belt_dir_nr = (belt_dir == MV_LEFT ? 0 : belt_dir == MV_RIGHT ? 2 : 1);
9396 return getBeltElementFromBeltNrAndBeltDirNr(belt_nr, belt_dir_nr);
9399 int getBeltSwitchElementFromBeltNrAndBeltDirNr(int belt_nr, int belt_dir_nr)
9401 static int belt_base_element[4] =
9403 EL_CONVEYOR_BELT_1_SWITCH_LEFT,
9404 EL_CONVEYOR_BELT_2_SWITCH_LEFT,
9405 EL_CONVEYOR_BELT_3_SWITCH_LEFT,
9406 EL_CONVEYOR_BELT_4_SWITCH_LEFT
9409 return belt_base_element[belt_nr] + belt_dir_nr;
9412 int getBeltSwitchElementFromBeltNrAndBeltDir(int belt_nr, int belt_dir)
9414 int belt_dir_nr = (belt_dir == MV_LEFT ? 0 : belt_dir == MV_RIGHT ? 2 : 1);
9416 return getBeltSwitchElementFromBeltNrAndBeltDirNr(belt_nr, belt_dir_nr);
9420 boolean getTeamMode_EM()
9422 return game.team_mode;
9425 int getNumActivePlayers_EM()
9428 int num_players = 0;
9432 return (setup.team_mode ? MAX_PLAYERS : 1);
9434 for (i = 0; i < MAX_PLAYERS; i++)
9435 if (tape.player_participates[i])
9438 return (num_players > 1 ? MAX_PLAYERS : 1);
9442 int num_players = 0;
9445 /* when recording game, activate all connected players */
9449 for (i = 0; i < MAX_PLAYERS; i++)
9450 if (tape.player_participates[i])
9458 int getGameFrameDelay_EM(int native_em_game_frame_delay)
9460 int game_frame_delay_value;
9462 game_frame_delay_value =
9463 (tape.playing && tape.fast_forward ? FfwdFrameDelay :
9464 GameFrameDelay == GAME_FRAME_DELAY ? native_em_game_frame_delay :
9467 if (tape.playing && tape.warp_forward && !tape.pausing)
9468 game_frame_delay_value = 0;
9470 return game_frame_delay_value;
9473 unsigned int InitRND(int seed)
9475 if (level.game_engine_type == GAME_ENGINE_TYPE_EM)
9476 return InitEngineRandom_EM(seed);
9477 else if (level.game_engine_type == GAME_ENGINE_TYPE_SP)
9478 return InitEngineRandom_SP(seed);
9480 return InitEngineRandom_RND(seed);
9484 static struct Mapping_EM_to_RND_object object_mapping[TILE_MAX];
9485 static struct Mapping_EM_to_RND_player player_mapping[MAX_PLAYERS][SPR_MAX];
9488 inline static int get_effective_element_EM(int tile, int frame_em)
9490 int element = object_mapping[tile].element_rnd;
9491 int action = object_mapping[tile].action;
9492 boolean is_backside = object_mapping[tile].is_backside;
9493 boolean action_removing = (action == ACTION_DIGGING ||
9494 action == ACTION_SNAPPING ||
9495 action == ACTION_COLLECTING);
9501 case Yacid_splash_eB:
9502 case Yacid_splash_wB:
9503 return (frame_em > 5 ? EL_EMPTY : element);
9507 case Ydiamond_stone:
9508 // if (!game.use_native_emc_graphics_engine)
9516 else /* frame_em == 7 */
9520 case Yacid_splash_eB:
9521 case Yacid_splash_wB:
9524 case Yemerald_stone:
9527 case Ydiamond_stone:
9531 case Xdrip_stretchB:
9550 case Xsand_stonein_1:
9551 case Xsand_stonein_2:
9552 case Xsand_stonein_3:
9553 case Xsand_stonein_4:
9557 return (is_backside || action_removing ? EL_EMPTY : element);
9562 inline static boolean check_linear_animation_EM(int tile)
9566 case Xsand_stonesand_1:
9567 case Xsand_stonesand_quickout_1:
9568 case Xsand_sandstone_1:
9569 case Xsand_stonein_1:
9570 case Xsand_stoneout_1:
9590 case Yacid_splash_eB:
9591 case Yacid_splash_wB:
9592 case Yemerald_stone:
9600 inline static void set_crumbled_graphics_EM(struct GraphicInfo_EM *g_em,
9601 boolean has_crumbled_graphics,
9602 int crumbled, int sync_frame)
9604 /* if element can be crumbled, but certain action graphics are just empty
9605 space (like instantly snapping sand to empty space in 1 frame), do not
9606 treat these empty space graphics as crumbled graphics in EMC engine */
9607 if (crumbled == IMG_EMPTY_SPACE)
9608 has_crumbled_graphics = FALSE;
9610 if (has_crumbled_graphics)
9612 struct GraphicInfo *g_crumbled = &graphic_info[crumbled];
9613 int frame_crumbled = getAnimationFrame(g_crumbled->anim_frames,
9614 g_crumbled->anim_delay,
9615 g_crumbled->anim_mode,
9616 g_crumbled->anim_start_frame,
9619 getGraphicSource(crumbled, frame_crumbled, &g_em->crumbled_bitmap,
9620 &g_em->crumbled_src_x, &g_em->crumbled_src_y);
9622 g_em->crumbled_border_size = graphic_info[crumbled].border_size;
9624 g_em->has_crumbled_graphics = TRUE;
9628 g_em->crumbled_bitmap = NULL;
9629 g_em->crumbled_src_x = 0;
9630 g_em->crumbled_src_y = 0;
9631 g_em->crumbled_border_size = 0;
9633 g_em->has_crumbled_graphics = FALSE;
9637 void ResetGfxAnimation_EM(int x, int y, int tile)
9642 void SetGfxAnimation_EM(struct GraphicInfo_EM *g_em,
9643 int tile, int frame_em, int x, int y)
9645 int action = object_mapping[tile].action;
9647 int direction = object_mapping[tile].direction;
9648 int effective_element = get_effective_element_EM(tile, frame_em);
9649 int graphic = (direction == MV_NONE ?
9650 el_act2img(effective_element, action) :
9651 el_act_dir2img(effective_element, action, direction));
9652 struct GraphicInfo *g = &graphic_info[graphic];
9655 boolean action_removing = (action == ACTION_DIGGING ||
9656 action == ACTION_SNAPPING ||
9657 action == ACTION_COLLECTING);
9658 boolean action_moving = (action == ACTION_FALLING ||
9659 action == ACTION_MOVING ||
9660 action == ACTION_PUSHING ||
9661 action == ACTION_EATING ||
9662 action == ACTION_FILLING ||
9663 action == ACTION_EMPTYING);
9664 boolean action_falling = (action == ACTION_FALLING ||
9665 action == ACTION_FILLING ||
9666 action == ACTION_EMPTYING);
9668 /* special case: graphic uses "2nd movement tile" and has defined
9669 7 frames for movement animation (or less) => use default graphic
9670 for last (8th) frame which ends the movement animation */
9671 if (g->double_movement && g->anim_frames < 8 && frame_em == 7)
9673 action = ACTION_DEFAULT; /* (keep action_* unchanged for now) */
9674 graphic = (direction == MV_NONE ?
9675 el_act2img(effective_element, action) :
9676 el_act_dir2img(effective_element, action, direction));
9678 g = &graphic_info[graphic];
9682 if (tile == Xsand_stonesand_1 ||
9683 tile == Xsand_stonesand_2 ||
9684 tile == Xsand_stonesand_3 ||
9685 tile == Xsand_stonesand_4)
9686 printf("::: 1: quicksand frame %d [%d]\n", GfxFrame[x][y], tile);
9690 if ((action_removing || check_linear_animation_EM(tile)) && frame_em == 0)
9694 // printf("::: resetting... [%d]\n", tile);
9697 if (action_removing || check_linear_animation_EM(tile))
9699 GfxFrame[x][y] = frame_em;
9701 // printf("::: resetting... [%d]\n", tile);
9704 else if (action_moving)
9706 boolean is_backside = object_mapping[tile].is_backside;
9710 int direction = object_mapping[tile].direction;
9711 int move_dir = (action_falling ? MV_DOWN : direction);
9716 /* !!! TEST !!! NEW !!! DOES NOT WORK RIGHT YET !!! */
9717 if (g->double_movement && frame_em == 0)
9721 // printf("::: resetting... [%d]\n", tile);
9725 if (move_dir == MV_LEFT)
9726 GfxFrame[x - 1][y] = GfxFrame[x][y];
9727 else if (move_dir == MV_RIGHT)
9728 GfxFrame[x + 1][y] = GfxFrame[x][y];
9729 else if (move_dir == MV_UP)
9730 GfxFrame[x][y - 1] = GfxFrame[x][y];
9731 else if (move_dir == MV_DOWN)
9732 GfxFrame[x][y + 1] = GfxFrame[x][y];
9739 /* special case: animation for Xsand_stonesand_quickout_1/2 twice as fast */
9740 if (tile == Xsand_stonesand_quickout_1 ||
9741 tile == Xsand_stonesand_quickout_2)
9746 if (tile == Xsand_stonesand_1 ||
9747 tile == Xsand_stonesand_2 ||
9748 tile == Xsand_stonesand_3 ||
9749 tile == Xsand_stonesand_4)
9750 printf("::: 2: quicksand frame %d [%d]\n", GfxFrame[x][y], tile);
9754 if (graphic_info[graphic].anim_global_sync)
9755 sync_frame = FrameCounter;
9756 else if (IN_FIELD(x, y, MAX_LEV_FIELDX, MAX_LEV_FIELDY))
9757 sync_frame = GfxFrame[x][y];
9759 sync_frame = 0; /* playfield border (pseudo steel) */
9761 SetRandomAnimationValue(x, y);
9763 int frame = getAnimationFrame(g->anim_frames,
9766 g->anim_start_frame,
9769 g_em->unique_identifier =
9770 (graphic << 16) | ((frame % 8) << 12) | (g_em->width << 6) | g_em->height;
9774 void getGraphicSourceObjectExt_EM(struct GraphicInfo_EM *g_em,
9775 int tile, int frame_em, int x, int y)
9777 int action = object_mapping[tile].action;
9778 int direction = object_mapping[tile].direction;
9779 boolean is_backside = object_mapping[tile].is_backside;
9780 int effective_element = get_effective_element_EM(tile, frame_em);
9782 int effective_action = action;
9784 int effective_action = (frame_em < 7 ? action : ACTION_DEFAULT);
9786 int graphic = (direction == MV_NONE ?
9787 el_act2img(effective_element, effective_action) :
9788 el_act_dir2img(effective_element, effective_action,
9790 int crumbled = (direction == MV_NONE ?
9791 el_act2crm(effective_element, effective_action) :
9792 el_act_dir2crm(effective_element, effective_action,
9794 int base_graphic = el_act2img(effective_element, ACTION_DEFAULT);
9795 int base_crumbled = el_act2crm(effective_element, ACTION_DEFAULT);
9796 boolean has_crumbled_graphics = (base_crumbled != base_graphic);
9797 struct GraphicInfo *g = &graphic_info[graphic];
9799 struct GraphicInfo *g_crumbled = &graphic_info[crumbled];
9803 /* special case: graphic uses "2nd movement tile" and has defined
9804 7 frames for movement animation (or less) => use default graphic
9805 for last (8th) frame which ends the movement animation */
9806 if (g->double_movement && g->anim_frames < 8 && frame_em == 7)
9808 effective_action = ACTION_DEFAULT;
9809 graphic = (direction == MV_NONE ?
9810 el_act2img(effective_element, effective_action) :
9811 el_act_dir2img(effective_element, effective_action,
9813 crumbled = (direction == MV_NONE ?
9814 el_act2crm(effective_element, effective_action) :
9815 el_act_dir2crm(effective_element, effective_action,
9818 g = &graphic_info[graphic];
9828 if (frame_em == 0) /* reset animation frame for certain elements */
9830 if (check_linear_animation_EM(tile))
9835 if (graphic_info[graphic].anim_global_sync)
9836 sync_frame = FrameCounter;
9837 else if (IN_FIELD(x, y, MAX_LEV_FIELDX, MAX_LEV_FIELDY))
9838 sync_frame = GfxFrame[x][y];
9840 sync_frame = 0; /* playfield border (pseudo steel) */
9842 SetRandomAnimationValue(x, y);
9847 int xxx_sync_frame = (i == Xdrip_stretch ? 7 :
9848 i == Xdrip_stretchB ? 7 :
9849 i == Ydrip_s2 ? j + 8 :
9850 i == Ydrip_s2B ? j + 8 :
9859 i == Xfake_acid_1 ? 0 :
9860 i == Xfake_acid_2 ? 10 :
9861 i == Xfake_acid_3 ? 20 :
9862 i == Xfake_acid_4 ? 30 :
9863 i == Xfake_acid_5 ? 40 :
9864 i == Xfake_acid_6 ? 50 :
9865 i == Xfake_acid_7 ? 60 :
9866 i == Xfake_acid_8 ? 70 :
9868 i == Xball_2B ? j + 8 :
9869 i == Yball_eat ? j + 1 :
9870 i == Ykey_1_eat ? j + 1 :
9871 i == Ykey_2_eat ? j + 1 :
9872 i == Ykey_3_eat ? j + 1 :
9873 i == Ykey_4_eat ? j + 1 :
9874 i == Ykey_5_eat ? j + 1 :
9875 i == Ykey_6_eat ? j + 1 :
9876 i == Ykey_7_eat ? j + 1 :
9877 i == Ykey_8_eat ? j + 1 :
9878 i == Ylenses_eat ? j + 1 :
9879 i == Ymagnify_eat ? j + 1 :
9880 i == Ygrass_eat ? j + 1 :
9881 i == Ydirt_eat ? j + 1 :
9882 i == Xamoeba_1 ? 0 :
9883 i == Xamoeba_2 ? 1 :
9884 i == Xamoeba_3 ? 2 :
9885 i == Xamoeba_4 ? 3 :
9886 i == Xamoeba_5 ? 0 :
9887 i == Xamoeba_6 ? 1 :
9888 i == Xamoeba_7 ? 2 :
9889 i == Xamoeba_8 ? 3 :
9890 i == Xexit_2 ? j + 8 :
9891 i == Xexit_3 ? j + 16 :
9892 i == Xdynamite_1 ? 0 :
9893 i == Xdynamite_2 ? 8 :
9894 i == Xdynamite_3 ? 16 :
9895 i == Xdynamite_4 ? 24 :
9896 i == Xsand_stonein_1 ? j + 1 :
9897 i == Xsand_stonein_2 ? j + 9 :
9898 i == Xsand_stonein_3 ? j + 17 :
9899 i == Xsand_stonein_4 ? j + 25 :
9900 i == Xsand_stoneout_1 && j == 0 ? 0 :
9901 i == Xsand_stoneout_1 && j == 1 ? 0 :
9902 i == Xsand_stoneout_1 && j == 2 ? 1 :
9903 i == Xsand_stoneout_1 && j == 3 ? 2 :
9904 i == Xsand_stoneout_1 && j == 4 ? 2 :
9905 i == Xsand_stoneout_1 && j == 5 ? 3 :
9906 i == Xsand_stoneout_1 && j == 6 ? 4 :
9907 i == Xsand_stoneout_1 && j == 7 ? 4 :
9908 i == Xsand_stoneout_2 && j == 0 ? 5 :
9909 i == Xsand_stoneout_2 && j == 1 ? 6 :
9910 i == Xsand_stoneout_2 && j == 2 ? 7 :
9911 i == Xsand_stoneout_2 && j == 3 ? 8 :
9912 i == Xsand_stoneout_2 && j == 4 ? 9 :
9913 i == Xsand_stoneout_2 && j == 5 ? 11 :
9914 i == Xsand_stoneout_2 && j == 6 ? 13 :
9915 i == Xsand_stoneout_2 && j == 7 ? 15 :
9916 i == Xboom_bug && j == 1 ? 2 :
9917 i == Xboom_bug && j == 2 ? 2 :
9918 i == Xboom_bug && j == 3 ? 4 :
9919 i == Xboom_bug && j == 4 ? 4 :
9920 i == Xboom_bug && j == 5 ? 2 :
9921 i == Xboom_bug && j == 6 ? 2 :
9922 i == Xboom_bug && j == 7 ? 0 :
9923 i == Xboom_bomb && j == 1 ? 2 :
9924 i == Xboom_bomb && j == 2 ? 2 :
9925 i == Xboom_bomb && j == 3 ? 4 :
9926 i == Xboom_bomb && j == 4 ? 4 :
9927 i == Xboom_bomb && j == 5 ? 2 :
9928 i == Xboom_bomb && j == 6 ? 2 :
9929 i == Xboom_bomb && j == 7 ? 0 :
9930 i == Xboom_android && j == 7 ? 6 :
9931 i == Xboom_1 && j == 1 ? 2 :
9932 i == Xboom_1 && j == 2 ? 2 :
9933 i == Xboom_1 && j == 3 ? 4 :
9934 i == Xboom_1 && j == 4 ? 4 :
9935 i == Xboom_1 && j == 5 ? 6 :
9936 i == Xboom_1 && j == 6 ? 6 :
9937 i == Xboom_1 && j == 7 ? 8 :
9938 i == Xboom_2 && j == 0 ? 8 :
9939 i == Xboom_2 && j == 1 ? 8 :
9940 i == Xboom_2 && j == 2 ? 10 :
9941 i == Xboom_2 && j == 3 ? 10 :
9942 i == Xboom_2 && j == 4 ? 10 :
9943 i == Xboom_2 && j == 5 ? 12 :
9944 i == Xboom_2 && j == 6 ? 12 :
9945 i == Xboom_2 && j == 7 ? 12 :
9947 special_animation && j == 4 ? 3 :
9948 effective_action != action ? 0 :
9954 int xxx_effective_action;
9955 int xxx_has_action_graphics;
9958 int element = object_mapping[i].element_rnd;
9959 int action = object_mapping[i].action;
9960 int direction = object_mapping[i].direction;
9961 boolean is_backside = object_mapping[i].is_backside;
9963 boolean action_removing = (action == ACTION_DIGGING ||
9964 action == ACTION_SNAPPING ||
9965 action == ACTION_COLLECTING);
9967 boolean action_exploding = ((action == ACTION_EXPLODING ||
9968 action == ACTION_SMASHED_BY_ROCK ||
9969 action == ACTION_SMASHED_BY_SPRING) &&
9970 element != EL_DIAMOND);
9971 boolean action_active = (action == ACTION_ACTIVE);
9972 boolean action_other = (action == ACTION_OTHER);
9976 int effective_element = get_effective_element_EM(i, j);
9978 int effective_element = (j > 5 && i == Yacid_splash_eB ? EL_EMPTY :
9979 j > 5 && i == Yacid_splash_wB ? EL_EMPTY :
9981 i == Xdrip_stretch ? element :
9982 i == Xdrip_stretchB ? element :
9983 i == Ydrip_s1 ? element :
9984 i == Ydrip_s1B ? element :
9985 i == Xball_1B ? element :
9986 i == Xball_2 ? element :
9987 i == Xball_2B ? element :
9988 i == Yball_eat ? element :
9989 i == Ykey_1_eat ? element :
9990 i == Ykey_2_eat ? element :
9991 i == Ykey_3_eat ? element :
9992 i == Ykey_4_eat ? element :
9993 i == Ykey_5_eat ? element :
9994 i == Ykey_6_eat ? element :
9995 i == Ykey_7_eat ? element :
9996 i == Ykey_8_eat ? element :
9997 i == Ylenses_eat ? element :
9998 i == Ymagnify_eat ? element :
9999 i == Ygrass_eat ? element :
10000 i == Ydirt_eat ? element :
10001 i == Yemerald_stone ? EL_EMERALD :
10002 i == Ydiamond_stone ? EL_ROCK :
10003 i == Xsand_stonein_1 ? element :
10004 i == Xsand_stonein_2 ? element :
10005 i == Xsand_stonein_3 ? element :
10006 i == Xsand_stonein_4 ? element :
10007 is_backside ? EL_EMPTY :
10008 action_removing ? EL_EMPTY :
10011 int effective_action = (j < 7 ? action :
10012 i == Xdrip_stretch ? action :
10013 i == Xdrip_stretchB ? action :
10014 i == Ydrip_s1 ? action :
10015 i == Ydrip_s1B ? action :
10016 i == Xball_1B ? action :
10017 i == Xball_2 ? action :
10018 i == Xball_2B ? action :
10019 i == Yball_eat ? action :
10020 i == Ykey_1_eat ? action :
10021 i == Ykey_2_eat ? action :
10022 i == Ykey_3_eat ? action :
10023 i == Ykey_4_eat ? action :
10024 i == Ykey_5_eat ? action :
10025 i == Ykey_6_eat ? action :
10026 i == Ykey_7_eat ? action :
10027 i == Ykey_8_eat ? action :
10028 i == Ylenses_eat ? action :
10029 i == Ymagnify_eat ? action :
10030 i == Ygrass_eat ? action :
10031 i == Ydirt_eat ? action :
10032 i == Xsand_stonein_1 ? action :
10033 i == Xsand_stonein_2 ? action :
10034 i == Xsand_stonein_3 ? action :
10035 i == Xsand_stonein_4 ? action :
10036 i == Xsand_stoneout_1 ? action :
10037 i == Xsand_stoneout_2 ? action :
10038 i == Xboom_android ? ACTION_EXPLODING :
10039 action_exploding ? ACTION_EXPLODING :
10040 action_active ? action :
10041 action_other ? action :
10043 int graphic = (el_act_dir2img(effective_element, effective_action,
10045 int crumbled = (el_act_dir2crm(effective_element, effective_action,
10047 int base_graphic = el_act2img(effective_element, ACTION_DEFAULT);
10048 int base_crumbled = el_act2crm(effective_element, ACTION_DEFAULT);
10049 boolean has_action_graphics = (graphic != base_graphic);
10050 boolean has_crumbled_graphics = (base_crumbled != base_graphic);
10051 struct GraphicInfo *g = &graphic_info[graphic];
10053 struct GraphicInfo *g_crumbled = &graphic_info[crumbled];
10055 struct GraphicInfo_EM *g_em = &graphic_info_em_object[i][7 - j];
10056 Bitmap *src_bitmap;
10058 /* ensure to get symmetric 3-frame, 2-delay animations as used in EM */
10059 boolean special_animation = (action != ACTION_DEFAULT &&
10060 g->anim_frames == 3 &&
10061 g->anim_delay == 2 &&
10062 g->anim_mode & ANIM_LINEAR);
10063 xxx_sync_frame = (i == Xdrip_stretch ? 7 :
10064 i == Xdrip_stretchB ? 7 :
10065 i == Ydrip_s2 ? j + 8 :
10066 i == Ydrip_s2B ? j + 8 :
10068 i == Xacid_2 ? 10 :
10069 i == Xacid_3 ? 20 :
10070 i == Xacid_4 ? 30 :
10071 i == Xacid_5 ? 40 :
10072 i == Xacid_6 ? 50 :
10073 i == Xacid_7 ? 60 :
10074 i == Xacid_8 ? 70 :
10075 i == Xfake_acid_1 ? 0 :
10076 i == Xfake_acid_2 ? 10 :
10077 i == Xfake_acid_3 ? 20 :
10078 i == Xfake_acid_4 ? 30 :
10079 i == Xfake_acid_5 ? 40 :
10080 i == Xfake_acid_6 ? 50 :
10081 i == Xfake_acid_7 ? 60 :
10082 i == Xfake_acid_8 ? 70 :
10084 i == Xball_2B ? j + 8 :
10085 i == Yball_eat ? j + 1 :
10086 i == Ykey_1_eat ? j + 1 :
10087 i == Ykey_2_eat ? j + 1 :
10088 i == Ykey_3_eat ? j + 1 :
10089 i == Ykey_4_eat ? j + 1 :
10090 i == Ykey_5_eat ? j + 1 :
10091 i == Ykey_6_eat ? j + 1 :
10092 i == Ykey_7_eat ? j + 1 :
10093 i == Ykey_8_eat ? j + 1 :
10094 i == Ylenses_eat ? j + 1 :
10095 i == Ymagnify_eat ? j + 1 :
10096 i == Ygrass_eat ? j + 1 :
10097 i == Ydirt_eat ? j + 1 :
10098 i == Xamoeba_1 ? 0 :
10099 i == Xamoeba_2 ? 1 :
10100 i == Xamoeba_3 ? 2 :
10101 i == Xamoeba_4 ? 3 :
10102 i == Xamoeba_5 ? 0 :
10103 i == Xamoeba_6 ? 1 :
10104 i == Xamoeba_7 ? 2 :
10105 i == Xamoeba_8 ? 3 :
10106 i == Xexit_2 ? j + 8 :
10107 i == Xexit_3 ? j + 16 :
10108 i == Xdynamite_1 ? 0 :
10109 i == Xdynamite_2 ? 8 :
10110 i == Xdynamite_3 ? 16 :
10111 i == Xdynamite_4 ? 24 :
10112 i == Xsand_stonein_1 ? j + 1 :
10113 i == Xsand_stonein_2 ? j + 9 :
10114 i == Xsand_stonein_3 ? j + 17 :
10115 i == Xsand_stonein_4 ? j + 25 :
10116 i == Xsand_stoneout_1 && j == 0 ? 0 :
10117 i == Xsand_stoneout_1 && j == 1 ? 0 :
10118 i == Xsand_stoneout_1 && j == 2 ? 1 :
10119 i == Xsand_stoneout_1 && j == 3 ? 2 :
10120 i == Xsand_stoneout_1 && j == 4 ? 2 :
10121 i == Xsand_stoneout_1 && j == 5 ? 3 :
10122 i == Xsand_stoneout_1 && j == 6 ? 4 :
10123 i == Xsand_stoneout_1 && j == 7 ? 4 :
10124 i == Xsand_stoneout_2 && j == 0 ? 5 :
10125 i == Xsand_stoneout_2 && j == 1 ? 6 :
10126 i == Xsand_stoneout_2 && j == 2 ? 7 :
10127 i == Xsand_stoneout_2 && j == 3 ? 8 :
10128 i == Xsand_stoneout_2 && j == 4 ? 9 :
10129 i == Xsand_stoneout_2 && j == 5 ? 11 :
10130 i == Xsand_stoneout_2 && j == 6 ? 13 :
10131 i == Xsand_stoneout_2 && j == 7 ? 15 :
10132 i == Xboom_bug && j == 1 ? 2 :
10133 i == Xboom_bug && j == 2 ? 2 :
10134 i == Xboom_bug && j == 3 ? 4 :
10135 i == Xboom_bug && j == 4 ? 4 :
10136 i == Xboom_bug && j == 5 ? 2 :
10137 i == Xboom_bug && j == 6 ? 2 :
10138 i == Xboom_bug && j == 7 ? 0 :
10139 i == Xboom_bomb && j == 1 ? 2 :
10140 i == Xboom_bomb && j == 2 ? 2 :
10141 i == Xboom_bomb && j == 3 ? 4 :
10142 i == Xboom_bomb && j == 4 ? 4 :
10143 i == Xboom_bomb && j == 5 ? 2 :
10144 i == Xboom_bomb && j == 6 ? 2 :
10145 i == Xboom_bomb && j == 7 ? 0 :
10146 i == Xboom_android && j == 7 ? 6 :
10147 i == Xboom_1 && j == 1 ? 2 :
10148 i == Xboom_1 && j == 2 ? 2 :
10149 i == Xboom_1 && j == 3 ? 4 :
10150 i == Xboom_1 && j == 4 ? 4 :
10151 i == Xboom_1 && j == 5 ? 6 :
10152 i == Xboom_1 && j == 6 ? 6 :
10153 i == Xboom_1 && j == 7 ? 8 :
10154 i == Xboom_2 && j == 0 ? 8 :
10155 i == Xboom_2 && j == 1 ? 8 :
10156 i == Xboom_2 && j == 2 ? 10 :
10157 i == Xboom_2 && j == 3 ? 10 :
10158 i == Xboom_2 && j == 4 ? 10 :
10159 i == Xboom_2 && j == 5 ? 12 :
10160 i == Xboom_2 && j == 6 ? 12 :
10161 i == Xboom_2 && j == 7 ? 12 :
10162 special_animation && j == 4 ? 3 :
10163 effective_action != action ? 0 :
10166 xxx_effective_action = effective_action;
10167 xxx_has_action_graphics = has_action_graphics;
10172 int frame = getAnimationFrame(g->anim_frames,
10175 g->anim_start_frame,
10189 int old_src_x = g_em->src_x;
10190 int old_src_y = g_em->src_y;
10194 getGraphicSourceExt(graphic, frame, &g_em->bitmap, &g_em->src_x, &g_em->src_y,
10195 g->double_movement && is_backside);
10197 getGraphicSourceExt(graphic, frame, &g_em->bitmap,
10198 &g_em->src_x, &g_em->src_y, FALSE);
10203 if (tile == Ydiamond_stone)
10204 printf("::: stone smashing diamond... %d: %d, %d, %d, %d, %d -> %d [%d, %d, %d, %d, %d, %d] [%d]\n",
10209 g->anim_start_frame,
10212 g_em->src_x, g_em->src_y,
10213 g_em->src_offset_x, g_em->src_offset_y,
10214 g_em->dst_offset_x, g_em->dst_offset_y,
10226 if (graphic == IMG_BUG_MOVING_RIGHT)
10227 printf("::: %d, %d, %d: %d, %d [%d, %d -> %d, %d]\n", graphic, x, y,
10228 g->double_movement, is_backside,
10229 old_src_x, old_src_y, g_em->src_x, g_em->src_y);
10237 g_em->src_offset_x = 0;
10238 g_em->src_offset_y = 0;
10239 g_em->dst_offset_x = 0;
10240 g_em->dst_offset_y = 0;
10241 g_em->width = TILEX;
10242 g_em->height = TILEY;
10244 g_em->preserve_background = FALSE;
10247 /* (updating the "crumbled" graphic definitions is probably not really needed,
10248 as animations for crumbled graphics can't be longer than one EMC cycle) */
10250 set_crumbled_graphics_EM(g_em, has_crumbled_graphics, crumbled,
10255 g_em->crumbled_bitmap = NULL;
10256 g_em->crumbled_src_x = 0;
10257 g_em->crumbled_src_y = 0;
10259 g_em->has_crumbled_graphics = FALSE;
10261 if (has_crumbled_graphics && crumbled != IMG_EMPTY_SPACE)
10263 int frame_crumbled = getAnimationFrame(g_crumbled->anim_frames,
10264 g_crumbled->anim_delay,
10265 g_crumbled->anim_mode,
10266 g_crumbled->anim_start_frame,
10269 getGraphicSource(crumbled, frame_crumbled, &g_em->crumbled_bitmap,
10270 &g_em->crumbled_src_x, &g_em->crumbled_src_y);
10272 g_em->has_crumbled_graphics = TRUE;
10278 int effective_action = xxx_effective_action;
10279 int has_action_graphics = xxx_has_action_graphics;
10281 if ((!g->double_movement && (effective_action == ACTION_FALLING ||
10282 effective_action == ACTION_MOVING ||
10283 effective_action == ACTION_PUSHING ||
10284 effective_action == ACTION_EATING)) ||
10285 (!has_action_graphics && (effective_action == ACTION_FILLING ||
10286 effective_action == ACTION_EMPTYING)))
10289 (effective_action == ACTION_FALLING ||
10290 effective_action == ACTION_FILLING ||
10291 effective_action == ACTION_EMPTYING ? MV_DOWN : direction);
10292 int dx = (move_dir == MV_LEFT ? -1 : move_dir == MV_RIGHT ? 1 : 0);
10293 int dy = (move_dir == MV_UP ? -1 : move_dir == MV_DOWN ? 1 : 0);
10294 int num_steps = (i == Ydrip_s1 ? 16 :
10295 i == Ydrip_s1B ? 16 :
10296 i == Ydrip_s2 ? 16 :
10297 i == Ydrip_s2B ? 16 :
10298 i == Xsand_stonein_1 ? 32 :
10299 i == Xsand_stonein_2 ? 32 :
10300 i == Xsand_stonein_3 ? 32 :
10301 i == Xsand_stonein_4 ? 32 :
10302 i == Xsand_stoneout_1 ? 16 :
10303 i == Xsand_stoneout_2 ? 16 : 8);
10304 int cx = ABS(dx) * (TILEX / num_steps);
10305 int cy = ABS(dy) * (TILEY / num_steps);
10306 int step_frame = (i == Ydrip_s2 ? j + 8 :
10307 i == Ydrip_s2B ? j + 8 :
10308 i == Xsand_stonein_2 ? j + 8 :
10309 i == Xsand_stonein_3 ? j + 16 :
10310 i == Xsand_stonein_4 ? j + 24 :
10311 i == Xsand_stoneout_2 ? j + 8 : j) + 1;
10312 int step = (is_backside ? step_frame : num_steps - step_frame);
10314 if (is_backside) /* tile where movement starts */
10316 if (dx < 0 || dy < 0)
10318 g_em->src_offset_x = cx * step;
10319 g_em->src_offset_y = cy * step;
10323 g_em->dst_offset_x = cx * step;
10324 g_em->dst_offset_y = cy * step;
10327 else /* tile where movement ends */
10329 if (dx < 0 || dy < 0)
10331 g_em->dst_offset_x = cx * step;
10332 g_em->dst_offset_y = cy * step;
10336 g_em->src_offset_x = cx * step;
10337 g_em->src_offset_y = cy * step;
10341 g_em->width = TILEX - cx * step;
10342 g_em->height = TILEY - cy * step;
10345 /* create unique graphic identifier to decide if tile must be redrawn */
10346 /* bit 31 - 16 (16 bit): EM style graphic
10347 bit 15 - 12 ( 4 bit): EM style frame
10348 bit 11 - 6 ( 6 bit): graphic width
10349 bit 5 - 0 ( 6 bit): graphic height */
10350 g_em->unique_identifier =
10351 (graphic << 16) | (frame << 12) | (g_em->width << 6) | g_em->height;
10357 void getGraphicSourcePlayerExt_EM(struct GraphicInfo_EM *g_em,
10358 int player_nr, int anim, int frame_em)
10360 int element = player_mapping[player_nr][anim].element_rnd;
10361 int action = player_mapping[player_nr][anim].action;
10362 int direction = player_mapping[player_nr][anim].direction;
10363 int graphic = (direction == MV_NONE ?
10364 el_act2img(element, action) :
10365 el_act_dir2img(element, action, direction));
10366 struct GraphicInfo *g = &graphic_info[graphic];
10369 InitPlayerGfxAnimation(&stored_player[player_nr], action, direction);
10371 stored_player[player_nr].StepFrame = frame_em;
10373 sync_frame = stored_player[player_nr].Frame;
10375 int frame = getAnimationFrame(g->anim_frames,
10378 g->anim_start_frame,
10381 getGraphicSourceExt(graphic, frame, &g_em->bitmap,
10382 &g_em->src_x, &g_em->src_y, FALSE);
10385 printf("::: %d: %d, %d [%d]\n",
10387 stored_player[player_nr].Frame,
10388 stored_player[player_nr].StepFrame,
10393 void InitGraphicInfo_EM(void)
10396 struct Mapping_EM_to_RND_object object_mapping[TILE_MAX];
10397 struct Mapping_EM_to_RND_player player_mapping[MAX_PLAYERS][SPR_MAX];
10402 int num_em_gfx_errors = 0;
10404 if (graphic_info_em_object[0][0].bitmap == NULL)
10406 /* EM graphics not yet initialized in em_open_all() */
10411 printf("::: [4 errors can be ignored (1 x 'bomb', 3 x 'em_dynamite']\n");
10414 /* always start with reliable default values */
10415 for (i = 0; i < TILE_MAX; i++)
10417 object_mapping[i].element_rnd = EL_UNKNOWN;
10418 object_mapping[i].is_backside = FALSE;
10419 object_mapping[i].action = ACTION_DEFAULT;
10420 object_mapping[i].direction = MV_NONE;
10423 /* always start with reliable default values */
10424 for (p = 0; p < MAX_PLAYERS; p++)
10426 for (i = 0; i < SPR_MAX; i++)
10428 player_mapping[p][i].element_rnd = EL_UNKNOWN;
10429 player_mapping[p][i].action = ACTION_DEFAULT;
10430 player_mapping[p][i].direction = MV_NONE;
10434 for (i = 0; em_object_mapping_list[i].element_em != -1; i++)
10436 int e = em_object_mapping_list[i].element_em;
10438 object_mapping[e].element_rnd = em_object_mapping_list[i].element_rnd;
10439 object_mapping[e].is_backside = em_object_mapping_list[i].is_backside;
10441 if (em_object_mapping_list[i].action != -1)
10442 object_mapping[e].action = em_object_mapping_list[i].action;
10444 if (em_object_mapping_list[i].direction != -1)
10445 object_mapping[e].direction =
10446 MV_DIR_FROM_BIT(em_object_mapping_list[i].direction);
10449 for (i = 0; em_player_mapping_list[i].action_em != -1; i++)
10451 int a = em_player_mapping_list[i].action_em;
10452 int p = em_player_mapping_list[i].player_nr;
10454 player_mapping[p][a].element_rnd = em_player_mapping_list[i].element_rnd;
10456 if (em_player_mapping_list[i].action != -1)
10457 player_mapping[p][a].action = em_player_mapping_list[i].action;
10459 if (em_player_mapping_list[i].direction != -1)
10460 player_mapping[p][a].direction =
10461 MV_DIR_FROM_BIT(em_player_mapping_list[i].direction);
10464 for (i = 0; i < TILE_MAX; i++)
10466 int element = object_mapping[i].element_rnd;
10467 int action = object_mapping[i].action;
10468 int direction = object_mapping[i].direction;
10469 boolean is_backside = object_mapping[i].is_backside;
10471 boolean action_removing = (action == ACTION_DIGGING ||
10472 action == ACTION_SNAPPING ||
10473 action == ACTION_COLLECTING);
10475 boolean action_exploding = ((action == ACTION_EXPLODING ||
10476 action == ACTION_SMASHED_BY_ROCK ||
10477 action == ACTION_SMASHED_BY_SPRING) &&
10478 element != EL_DIAMOND);
10479 boolean action_active = (action == ACTION_ACTIVE);
10480 boolean action_other = (action == ACTION_OTHER);
10482 for (j = 0; j < 8; j++)
10485 int effective_element = get_effective_element_EM(i, j);
10487 int effective_element = (j > 5 && i == Yacid_splash_eB ? EL_EMPTY :
10488 j > 5 && i == Yacid_splash_wB ? EL_EMPTY :
10490 i == Xdrip_stretch ? element :
10491 i == Xdrip_stretchB ? element :
10492 i == Ydrip_s1 ? element :
10493 i == Ydrip_s1B ? element :
10494 i == Xball_1B ? element :
10495 i == Xball_2 ? element :
10496 i == Xball_2B ? element :
10497 i == Yball_eat ? element :
10498 i == Ykey_1_eat ? element :
10499 i == Ykey_2_eat ? element :
10500 i == Ykey_3_eat ? element :
10501 i == Ykey_4_eat ? element :
10502 i == Ykey_5_eat ? element :
10503 i == Ykey_6_eat ? element :
10504 i == Ykey_7_eat ? element :
10505 i == Ykey_8_eat ? element :
10506 i == Ylenses_eat ? element :
10507 i == Ymagnify_eat ? element :
10508 i == Ygrass_eat ? element :
10509 i == Ydirt_eat ? element :
10510 i == Yemerald_stone ? EL_EMERALD :
10511 i == Ydiamond_stone ? EL_ROCK :
10512 i == Xsand_stonein_1 ? element :
10513 i == Xsand_stonein_2 ? element :
10514 i == Xsand_stonein_3 ? element :
10515 i == Xsand_stonein_4 ? element :
10516 is_backside ? EL_EMPTY :
10517 action_removing ? EL_EMPTY :
10520 int effective_action = (j < 7 ? action :
10521 i == Xdrip_stretch ? action :
10522 i == Xdrip_stretchB ? action :
10523 i == Ydrip_s1 ? action :
10524 i == Ydrip_s1B ? action :
10525 i == Xball_1B ? action :
10526 i == Xball_2 ? action :
10527 i == Xball_2B ? action :
10528 i == Yball_eat ? action :
10529 i == Ykey_1_eat ? action :
10530 i == Ykey_2_eat ? action :
10531 i == Ykey_3_eat ? action :
10532 i == Ykey_4_eat ? action :
10533 i == Ykey_5_eat ? action :
10534 i == Ykey_6_eat ? action :
10535 i == Ykey_7_eat ? action :
10536 i == Ykey_8_eat ? action :
10537 i == Ylenses_eat ? action :
10538 i == Ymagnify_eat ? action :
10539 i == Ygrass_eat ? action :
10540 i == Ydirt_eat ? action :
10541 i == Xsand_stonein_1 ? action :
10542 i == Xsand_stonein_2 ? action :
10543 i == Xsand_stonein_3 ? action :
10544 i == Xsand_stonein_4 ? action :
10545 i == Xsand_stoneout_1 ? action :
10546 i == Xsand_stoneout_2 ? action :
10547 i == Xboom_android ? ACTION_EXPLODING :
10548 action_exploding ? ACTION_EXPLODING :
10549 action_active ? action :
10550 action_other ? action :
10552 int graphic = (el_act_dir2img(effective_element, effective_action,
10554 int crumbled = (el_act_dir2crm(effective_element, effective_action,
10556 int base_graphic = el_act2img(effective_element, ACTION_DEFAULT);
10557 int base_crumbled = el_act2crm(effective_element, ACTION_DEFAULT);
10558 boolean has_action_graphics = (graphic != base_graphic);
10559 boolean has_crumbled_graphics = (base_crumbled != base_graphic);
10560 struct GraphicInfo *g = &graphic_info[graphic];
10562 struct GraphicInfo *g_crumbled = &graphic_info[crumbled];
10564 struct GraphicInfo_EM *g_em = &graphic_info_em_object[i][7 - j];
10565 Bitmap *src_bitmap;
10567 /* ensure to get symmetric 3-frame, 2-delay animations as used in EM */
10568 boolean special_animation = (action != ACTION_DEFAULT &&
10569 g->anim_frames == 3 &&
10570 g->anim_delay == 2 &&
10571 g->anim_mode & ANIM_LINEAR);
10572 int sync_frame = (i == Xdrip_stretch ? 7 :
10573 i == Xdrip_stretchB ? 7 :
10574 i == Ydrip_s2 ? j + 8 :
10575 i == Ydrip_s2B ? j + 8 :
10577 i == Xacid_2 ? 10 :
10578 i == Xacid_3 ? 20 :
10579 i == Xacid_4 ? 30 :
10580 i == Xacid_5 ? 40 :
10581 i == Xacid_6 ? 50 :
10582 i == Xacid_7 ? 60 :
10583 i == Xacid_8 ? 70 :
10584 i == Xfake_acid_1 ? 0 :
10585 i == Xfake_acid_2 ? 10 :
10586 i == Xfake_acid_3 ? 20 :
10587 i == Xfake_acid_4 ? 30 :
10588 i == Xfake_acid_5 ? 40 :
10589 i == Xfake_acid_6 ? 50 :
10590 i == Xfake_acid_7 ? 60 :
10591 i == Xfake_acid_8 ? 70 :
10593 i == Xball_2B ? j + 8 :
10594 i == Yball_eat ? j + 1 :
10595 i == Ykey_1_eat ? j + 1 :
10596 i == Ykey_2_eat ? j + 1 :
10597 i == Ykey_3_eat ? j + 1 :
10598 i == Ykey_4_eat ? j + 1 :
10599 i == Ykey_5_eat ? j + 1 :
10600 i == Ykey_6_eat ? j + 1 :
10601 i == Ykey_7_eat ? j + 1 :
10602 i == Ykey_8_eat ? j + 1 :
10603 i == Ylenses_eat ? j + 1 :
10604 i == Ymagnify_eat ? j + 1 :
10605 i == Ygrass_eat ? j + 1 :
10606 i == Ydirt_eat ? j + 1 :
10607 i == Xamoeba_1 ? 0 :
10608 i == Xamoeba_2 ? 1 :
10609 i == Xamoeba_3 ? 2 :
10610 i == Xamoeba_4 ? 3 :
10611 i == Xamoeba_5 ? 0 :
10612 i == Xamoeba_6 ? 1 :
10613 i == Xamoeba_7 ? 2 :
10614 i == Xamoeba_8 ? 3 :
10615 i == Xexit_2 ? j + 8 :
10616 i == Xexit_3 ? j + 16 :
10617 i == Xdynamite_1 ? 0 :
10618 i == Xdynamite_2 ? 8 :
10619 i == Xdynamite_3 ? 16 :
10620 i == Xdynamite_4 ? 24 :
10621 i == Xsand_stonein_1 ? j + 1 :
10622 i == Xsand_stonein_2 ? j + 9 :
10623 i == Xsand_stonein_3 ? j + 17 :
10624 i == Xsand_stonein_4 ? j + 25 :
10625 i == Xsand_stoneout_1 && j == 0 ? 0 :
10626 i == Xsand_stoneout_1 && j == 1 ? 0 :
10627 i == Xsand_stoneout_1 && j == 2 ? 1 :
10628 i == Xsand_stoneout_1 && j == 3 ? 2 :
10629 i == Xsand_stoneout_1 && j == 4 ? 2 :
10630 i == Xsand_stoneout_1 && j == 5 ? 3 :
10631 i == Xsand_stoneout_1 && j == 6 ? 4 :
10632 i == Xsand_stoneout_1 && j == 7 ? 4 :
10633 i == Xsand_stoneout_2 && j == 0 ? 5 :
10634 i == Xsand_stoneout_2 && j == 1 ? 6 :
10635 i == Xsand_stoneout_2 && j == 2 ? 7 :
10636 i == Xsand_stoneout_2 && j == 3 ? 8 :
10637 i == Xsand_stoneout_2 && j == 4 ? 9 :
10638 i == Xsand_stoneout_2 && j == 5 ? 11 :
10639 i == Xsand_stoneout_2 && j == 6 ? 13 :
10640 i == Xsand_stoneout_2 && j == 7 ? 15 :
10641 i == Xboom_bug && j == 1 ? 2 :
10642 i == Xboom_bug && j == 2 ? 2 :
10643 i == Xboom_bug && j == 3 ? 4 :
10644 i == Xboom_bug && j == 4 ? 4 :
10645 i == Xboom_bug && j == 5 ? 2 :
10646 i == Xboom_bug && j == 6 ? 2 :
10647 i == Xboom_bug && j == 7 ? 0 :
10648 i == Xboom_bomb && j == 1 ? 2 :
10649 i == Xboom_bomb && j == 2 ? 2 :
10650 i == Xboom_bomb && j == 3 ? 4 :
10651 i == Xboom_bomb && j == 4 ? 4 :
10652 i == Xboom_bomb && j == 5 ? 2 :
10653 i == Xboom_bomb && j == 6 ? 2 :
10654 i == Xboom_bomb && j == 7 ? 0 :
10655 i == Xboom_android && j == 7 ? 6 :
10656 i == Xboom_1 && j == 1 ? 2 :
10657 i == Xboom_1 && j == 2 ? 2 :
10658 i == Xboom_1 && j == 3 ? 4 :
10659 i == Xboom_1 && j == 4 ? 4 :
10660 i == Xboom_1 && j == 5 ? 6 :
10661 i == Xboom_1 && j == 6 ? 6 :
10662 i == Xboom_1 && j == 7 ? 8 :
10663 i == Xboom_2 && j == 0 ? 8 :
10664 i == Xboom_2 && j == 1 ? 8 :
10665 i == Xboom_2 && j == 2 ? 10 :
10666 i == Xboom_2 && j == 3 ? 10 :
10667 i == Xboom_2 && j == 4 ? 10 :
10668 i == Xboom_2 && j == 5 ? 12 :
10669 i == Xboom_2 && j == 6 ? 12 :
10670 i == Xboom_2 && j == 7 ? 12 :
10671 special_animation && j == 4 ? 3 :
10672 effective_action != action ? 0 :
10676 Bitmap *debug_bitmap = g_em->bitmap;
10677 int debug_src_x = g_em->src_x;
10678 int debug_src_y = g_em->src_y;
10681 int frame = getAnimationFrame(g->anim_frames,
10684 g->anim_start_frame,
10687 getGraphicSourceExt(graphic, frame, &src_bitmap, &src_x, &src_y,
10688 g->double_movement && is_backside);
10690 g_em->bitmap = src_bitmap;
10691 g_em->src_x = src_x;
10692 g_em->src_y = src_y;
10693 g_em->src_offset_x = 0;
10694 g_em->src_offset_y = 0;
10695 g_em->dst_offset_x = 0;
10696 g_em->dst_offset_y = 0;
10697 g_em->width = TILEX;
10698 g_em->height = TILEY;
10700 g_em->preserve_background = FALSE;
10703 set_crumbled_graphics_EM(g_em, has_crumbled_graphics, crumbled,
10708 g_em->crumbled_bitmap = NULL;
10709 g_em->crumbled_src_x = 0;
10710 g_em->crumbled_src_y = 0;
10711 g_em->crumbled_border_size = 0;
10713 g_em->has_crumbled_graphics = FALSE;
10716 if (has_crumbled_graphics && crumbled == IMG_EMPTY_SPACE)
10717 printf("::: empty crumbled: %d [%s], %d, %d\n",
10718 effective_element, element_info[effective_element].token_name,
10719 effective_action, direction);
10722 /* if element can be crumbled, but certain action graphics are just empty
10723 space (like instantly snapping sand to empty space in 1 frame), do not
10724 treat these empty space graphics as crumbled graphics in EMC engine */
10725 if (has_crumbled_graphics && crumbled != IMG_EMPTY_SPACE)
10727 int frame_crumbled = getAnimationFrame(g_crumbled->anim_frames,
10728 g_crumbled->anim_delay,
10729 g_crumbled->anim_mode,
10730 g_crumbled->anim_start_frame,
10733 getGraphicSource(crumbled, frame_crumbled, &src_bitmap, &src_x, &src_y);
10735 g_em->has_crumbled_graphics = TRUE;
10736 g_em->crumbled_bitmap = src_bitmap;
10737 g_em->crumbled_src_x = src_x;
10738 g_em->crumbled_src_y = src_y;
10739 g_em->crumbled_border_size = graphic_info[crumbled].border_size;
10743 if (g_em == &graphic_info_em_object[207][0])
10744 printf("... %d, %d [%d, %d, %d, %d] [%d, %d, %d, %d, %d, %d => %d]\n",
10745 graphic_info_em_object[207][0].crumbled_src_x,
10746 graphic_info_em_object[207][0].crumbled_src_y,
10748 crumbled, frame, src_x, src_y,
10753 g->anim_start_frame,
10755 gfx.anim_random_frame,
10760 printf("::: EMC tile %d is crumbled\n", i);
10766 if (element == EL_ROCK &&
10767 effective_action == ACTION_FILLING)
10768 printf("::: has_action_graphics == %d\n", has_action_graphics);
10771 if ((!g->double_movement && (effective_action == ACTION_FALLING ||
10772 effective_action == ACTION_MOVING ||
10773 effective_action == ACTION_PUSHING ||
10774 effective_action == ACTION_EATING)) ||
10775 (!has_action_graphics && (effective_action == ACTION_FILLING ||
10776 effective_action == ACTION_EMPTYING)))
10779 (effective_action == ACTION_FALLING ||
10780 effective_action == ACTION_FILLING ||
10781 effective_action == ACTION_EMPTYING ? MV_DOWN : direction);
10782 int dx = (move_dir == MV_LEFT ? -1 : move_dir == MV_RIGHT ? 1 : 0);
10783 int dy = (move_dir == MV_UP ? -1 : move_dir == MV_DOWN ? 1 : 0);
10784 int num_steps = (i == Ydrip_s1 ? 16 :
10785 i == Ydrip_s1B ? 16 :
10786 i == Ydrip_s2 ? 16 :
10787 i == Ydrip_s2B ? 16 :
10788 i == Xsand_stonein_1 ? 32 :
10789 i == Xsand_stonein_2 ? 32 :
10790 i == Xsand_stonein_3 ? 32 :
10791 i == Xsand_stonein_4 ? 32 :
10792 i == Xsand_stoneout_1 ? 16 :
10793 i == Xsand_stoneout_2 ? 16 : 8);
10794 int cx = ABS(dx) * (TILEX / num_steps);
10795 int cy = ABS(dy) * (TILEY / num_steps);
10796 int step_frame = (i == Ydrip_s2 ? j + 8 :
10797 i == Ydrip_s2B ? j + 8 :
10798 i == Xsand_stonein_2 ? j + 8 :
10799 i == Xsand_stonein_3 ? j + 16 :
10800 i == Xsand_stonein_4 ? j + 24 :
10801 i == Xsand_stoneout_2 ? j + 8 : j) + 1;
10802 int step = (is_backside ? step_frame : num_steps - step_frame);
10804 if (is_backside) /* tile where movement starts */
10806 if (dx < 0 || dy < 0)
10808 g_em->src_offset_x = cx * step;
10809 g_em->src_offset_y = cy * step;
10813 g_em->dst_offset_x = cx * step;
10814 g_em->dst_offset_y = cy * step;
10817 else /* tile where movement ends */
10819 if (dx < 0 || dy < 0)
10821 g_em->dst_offset_x = cx * step;
10822 g_em->dst_offset_y = cy * step;
10826 g_em->src_offset_x = cx * step;
10827 g_em->src_offset_y = cy * step;
10831 g_em->width = TILEX - cx * step;
10832 g_em->height = TILEY - cy * step;
10835 /* create unique graphic identifier to decide if tile must be redrawn */
10836 /* bit 31 - 16 (16 bit): EM style graphic
10837 bit 15 - 12 ( 4 bit): EM style frame
10838 bit 11 - 6 ( 6 bit): graphic width
10839 bit 5 - 0 ( 6 bit): graphic height */
10840 g_em->unique_identifier =
10841 (graphic << 16) | (frame << 12) | (g_em->width << 6) | g_em->height;
10845 /* skip check for EMC elements not contained in original EMC artwork */
10846 if (element == EL_EMC_FAKE_ACID)
10849 if (g_em->bitmap != debug_bitmap ||
10850 g_em->src_x != debug_src_x ||
10851 g_em->src_y != debug_src_y ||
10852 g_em->src_offset_x != 0 ||
10853 g_em->src_offset_y != 0 ||
10854 g_em->dst_offset_x != 0 ||
10855 g_em->dst_offset_y != 0 ||
10856 g_em->width != TILEX ||
10857 g_em->height != TILEY)
10859 static int last_i = -1;
10867 printf("::: EMC GFX ERROR for element %d -> %d ('%s', '%s', %d)",
10868 i, element, element_info[element].token_name,
10869 element_action_info[effective_action].suffix, direction);
10871 if (element != effective_element)
10872 printf(" [%d ('%s')]",
10874 element_info[effective_element].token_name);
10878 if (g_em->bitmap != debug_bitmap)
10879 printf(" %d (%d): different bitmap! (0x%08x != 0x%08x)\n",
10880 j, is_backside, (int)(g_em->bitmap), (int)(debug_bitmap));
10882 if (g_em->src_x != debug_src_x ||
10883 g_em->src_y != debug_src_y)
10884 printf(" frame %d (%c): %d,%d (%d,%d) should be %d,%d (%d,%d)\n",
10885 j, (is_backside ? 'B' : 'F'),
10886 g_em->src_x, g_em->src_y,
10887 g_em->src_x / 32, g_em->src_y / 32,
10888 debug_src_x, debug_src_y,
10889 debug_src_x / 32, debug_src_y / 32);
10891 if (g_em->src_offset_x != 0 ||
10892 g_em->src_offset_y != 0 ||
10893 g_em->dst_offset_x != 0 ||
10894 g_em->dst_offset_y != 0)
10895 printf(" %d (%d): offsets %d,%d and %d,%d should be all 0\n",
10897 g_em->src_offset_x, g_em->src_offset_y,
10898 g_em->dst_offset_x, g_em->dst_offset_y);
10900 if (g_em->width != TILEX ||
10901 g_em->height != TILEY)
10902 printf(" %d (%d): size %d,%d should be %d,%d\n",
10904 g_em->width, g_em->height, TILEX, TILEY);
10906 num_em_gfx_errors++;
10913 for (i = 0; i < TILE_MAX; i++)
10915 for (j = 0; j < 8; j++)
10917 int element = object_mapping[i].element_rnd;
10918 int action = object_mapping[i].action;
10919 int direction = object_mapping[i].direction;
10920 boolean is_backside = object_mapping[i].is_backside;
10921 int graphic_action = el_act_dir2img(element, action, direction);
10922 int graphic_default = el_act_dir2img(element, ACTION_DEFAULT, direction);
10924 if ((action == ACTION_SMASHED_BY_ROCK ||
10925 action == ACTION_SMASHED_BY_SPRING ||
10926 action == ACTION_EATING) &&
10927 graphic_action == graphic_default)
10929 int e = (action == ACTION_SMASHED_BY_ROCK ? Ystone_s :
10930 action == ACTION_SMASHED_BY_SPRING ? Yspring_s :
10931 direction == MV_LEFT ? (is_backside? Yspring_wB: Yspring_w) :
10932 direction == MV_RIGHT ? (is_backside? Yspring_eB: Yspring_e) :
10935 /* no separate animation for "smashed by rock" -- use rock instead */
10936 struct GraphicInfo_EM *g_em = &graphic_info_em_object[i][7 - j];
10937 struct GraphicInfo_EM *g_xx = &graphic_info_em_object[e][7 - j];
10939 g_em->bitmap = g_xx->bitmap;
10940 g_em->src_x = g_xx->src_x;
10941 g_em->src_y = g_xx->src_y;
10942 g_em->src_offset_x = g_xx->src_offset_x;
10943 g_em->src_offset_y = g_xx->src_offset_y;
10944 g_em->dst_offset_x = g_xx->dst_offset_x;
10945 g_em->dst_offset_y = g_xx->dst_offset_y;
10946 g_em->width = g_xx->width;
10947 g_em->height = g_xx->height;
10948 g_em->unique_identifier = g_xx->unique_identifier;
10951 g_em->preserve_background = TRUE;
10956 for (p = 0; p < MAX_PLAYERS; p++)
10958 for (i = 0; i < SPR_MAX; i++)
10960 int element = player_mapping[p][i].element_rnd;
10961 int action = player_mapping[p][i].action;
10962 int direction = player_mapping[p][i].direction;
10964 for (j = 0; j < 8; j++)
10966 int effective_element = element;
10967 int effective_action = action;
10968 int graphic = (direction == MV_NONE ?
10969 el_act2img(effective_element, effective_action) :
10970 el_act_dir2img(effective_element, effective_action,
10972 struct GraphicInfo *g = &graphic_info[graphic];
10973 struct GraphicInfo_EM *g_em = &graphic_info_em_player[p][i][7 - j];
10974 Bitmap *src_bitmap;
10976 int sync_frame = j;
10979 Bitmap *debug_bitmap = g_em->bitmap;
10980 int debug_src_x = g_em->src_x;
10981 int debug_src_y = g_em->src_y;
10984 int frame = getAnimationFrame(g->anim_frames,
10987 g->anim_start_frame,
10990 getGraphicSourceExt(graphic, frame, &src_bitmap, &src_x, &src_y, FALSE);
10992 g_em->bitmap = src_bitmap;
10993 g_em->src_x = src_x;
10994 g_em->src_y = src_y;
10995 g_em->src_offset_x = 0;
10996 g_em->src_offset_y = 0;
10997 g_em->dst_offset_x = 0;
10998 g_em->dst_offset_y = 0;
10999 g_em->width = TILEX;
11000 g_em->height = TILEY;
11004 /* skip check for EMC elements not contained in original EMC artwork */
11005 if (element == EL_PLAYER_3 ||
11006 element == EL_PLAYER_4)
11009 if (g_em->bitmap != debug_bitmap ||
11010 g_em->src_x != debug_src_x ||
11011 g_em->src_y != debug_src_y)
11013 static int last_i = -1;
11021 printf("::: EMC GFX ERROR for p/a %d/%d -> %d ('%s', '%s', %d)",
11022 p, i, element, element_info[element].token_name,
11023 element_action_info[effective_action].suffix, direction);
11025 if (element != effective_element)
11026 printf(" [%d ('%s')]",
11028 element_info[effective_element].token_name);
11032 if (g_em->bitmap != debug_bitmap)
11033 printf(" %d: different bitmap! (0x%08x != 0x%08x)\n",
11034 j, (int)(g_em->bitmap), (int)(debug_bitmap));
11036 if (g_em->src_x != debug_src_x ||
11037 g_em->src_y != debug_src_y)
11038 printf(" frame %d: %d,%d (%d,%d) should be %d,%d (%d,%d)\n",
11040 g_em->src_x, g_em->src_y,
11041 g_em->src_x / 32, g_em->src_y / 32,
11042 debug_src_x, debug_src_y,
11043 debug_src_x / 32, debug_src_y / 32);
11045 num_em_gfx_errors++;
11055 printf("::: [%d errors found]\n", num_em_gfx_errors);
11061 void CheckSingleStepMode_EM(byte action[MAX_PLAYERS], int frame,
11062 boolean any_player_moving,
11063 boolean player_is_dropping)
11065 if (tape.single_step && tape.recording && !tape.pausing)
11068 boolean active_players = FALSE;
11071 for (i = 0; i < MAX_PLAYERS; i++)
11072 if (action[i] != JOY_NO_ACTION)
11073 active_players = TRUE;
11077 if (frame == 0 && !player_is_dropping)
11078 TapeTogglePause(TAPE_TOGGLE_AUTOMATIC);
11082 void CheckSingleStepMode_SP(boolean murphy_is_waiting,
11083 boolean murphy_is_dropping)
11086 printf("::: waiting: %d, dropping: %d\n",
11087 murphy_is_waiting, murphy_is_dropping);
11090 if (tape.single_step && tape.recording && !tape.pausing)
11092 // if (murphy_is_waiting || murphy_is_dropping)
11093 if (murphy_is_waiting)
11096 printf("::: murphy is waiting -> pause mode\n");
11099 TapeTogglePause(TAPE_TOGGLE_AUTOMATIC);
11104 void getGraphicSource_SP(struct GraphicInfo_SP *g_sp,
11105 int graphic, int sync_frame, int x, int y)
11107 int frame = getGraphicAnimationFrame(graphic, sync_frame);
11109 getGraphicSource(graphic, frame, &g_sp->bitmap, &g_sp->src_x, &g_sp->src_y);
11112 boolean isNextAnimationFrame_SP(int graphic, int sync_frame)
11114 return (IS_NEXT_FRAME(sync_frame, graphic));
11117 int getGraphicInfo_Delay(int graphic)
11119 return graphic_info[graphic].anim_delay;
11122 void PlayMenuSoundExt(int sound)
11124 if (sound == SND_UNDEFINED)
11127 if ((!setup.sound_simple && !IS_LOOP_SOUND(sound)) ||
11128 (!setup.sound_loops && IS_LOOP_SOUND(sound)))
11131 if (IS_LOOP_SOUND(sound))
11132 PlaySoundLoop(sound);
11137 void PlayMenuSound()
11139 PlayMenuSoundExt(menu.sound[game_status]);
11142 void PlayMenuSoundStereo(int sound, int stereo_position)
11144 if (sound == SND_UNDEFINED)
11147 if ((!setup.sound_simple && !IS_LOOP_SOUND(sound)) ||
11148 (!setup.sound_loops && IS_LOOP_SOUND(sound)))
11151 if (IS_LOOP_SOUND(sound))
11152 PlaySoundExt(sound, SOUND_MAX_VOLUME, stereo_position, SND_CTRL_PLAY_LOOP);
11154 PlaySoundStereo(sound, stereo_position);
11157 void PlayMenuSoundIfLoopExt(int sound)
11159 if (sound == SND_UNDEFINED)
11162 if ((!setup.sound_simple && !IS_LOOP_SOUND(sound)) ||
11163 (!setup.sound_loops && IS_LOOP_SOUND(sound)))
11166 if (IS_LOOP_SOUND(sound))
11167 PlaySoundLoop(sound);
11170 void PlayMenuSoundIfLoop()
11172 PlayMenuSoundIfLoopExt(menu.sound[game_status]);
11175 void PlayMenuMusicExt(int music)
11177 if (music == MUS_UNDEFINED)
11180 if (!setup.sound_music)
11186 void PlayMenuMusic()
11188 PlayMenuMusicExt(menu.music[game_status]);
11191 void PlaySoundActivating()
11194 PlaySound(SND_MENU_ITEM_ACTIVATING);
11198 void PlaySoundSelecting()
11201 PlaySound(SND_MENU_ITEM_SELECTING);
11205 void ToggleFullscreenOrChangeWindowScalingIfNeeded()
11207 boolean change_fullscreen = (setup.fullscreen !=
11208 video.fullscreen_enabled);
11209 boolean change_fullscreen_mode = (video.fullscreen_enabled &&
11210 !strEqual(setup.fullscreen_mode,
11211 video.fullscreen_mode_current));
11212 boolean change_window_scaling_percent = (!video.fullscreen_enabled &&
11213 setup.window_scaling_percent !=
11214 video.window_scaling_percent);
11216 if (change_window_scaling_percent && video.fullscreen_enabled)
11219 if (!change_window_scaling_percent && !video.fullscreen_available)
11222 #if defined(TARGET_SDL2)
11223 if (change_window_scaling_percent)
11225 SDLSetWindowScaling(setup.window_scaling_percent);
11229 else if (change_fullscreen)
11231 SDLSetWindowFullscreen(setup.fullscreen);
11233 /* set setup value according to successfully changed fullscreen mode */
11234 setup.fullscreen = video.fullscreen_enabled;
11240 if (change_fullscreen ||
11241 change_fullscreen_mode ||
11242 change_window_scaling_percent)
11244 Bitmap *tmp_backbuffer = CreateBitmap(WIN_XSIZE, WIN_YSIZE, DEFAULT_DEPTH);
11246 /* save backbuffer content which gets lost when toggling fullscreen mode */
11247 BlitBitmap(backbuffer, tmp_backbuffer, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
11249 if (change_fullscreen_mode)
11251 /* keep fullscreen, but change fullscreen mode (screen resolution) */
11252 video.fullscreen_enabled = FALSE; /* force new fullscreen mode */
11255 if (change_window_scaling_percent)
11257 /* keep window mode, but change window scaling */
11258 video.fullscreen_enabled = TRUE; /* force new window scaling */
11261 /* toggle fullscreen */
11262 ChangeVideoModeIfNeeded(setup.fullscreen);
11264 /* set setup value according to successfully changed fullscreen mode */
11265 setup.fullscreen = video.fullscreen_enabled;
11267 /* restore backbuffer content from temporary backbuffer backup bitmap */
11268 BlitBitmap(tmp_backbuffer, backbuffer, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
11270 FreeBitmap(tmp_backbuffer);
11273 /* update visible window/screen */
11274 BlitBitmap(backbuffer, window, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
11276 redraw_mask = REDRAW_ALL;
11281 void ChangeViewportPropertiesIfNeeded()
11284 int *door_1_x = &DX;
11285 int *door_1_y = &DY;
11286 int *door_2_x = (game_status == GAME_MODE_EDITOR ? &EX : &VX);
11287 int *door_2_y = (game_status == GAME_MODE_EDITOR ? &EY : &VY);
11290 int gfx_game_mode = game_status;
11292 int gfx_game_mode = (game_status == GAME_MODE_PLAYING ||
11293 game_status == GAME_MODE_EDITOR ? game_status :
11296 int gfx_game_mode2 = (game_status == GAME_MODE_EDITOR ? GAME_MODE_DEFAULT :
11298 struct RectWithBorder *vp_playfield = &viewport.playfield[gfx_game_mode];
11299 struct RectWithBorder *vp_door_1 = &viewport.door_1[gfx_game_mode];
11300 struct RectWithBorder *vp_door_2 = &viewport.door_2[gfx_game_mode2];
11301 struct RectWithBorder *vp_door_3 = &viewport.door_2[GAME_MODE_EDITOR];
11302 int border_size = vp_playfield->border_size;
11303 int new_sx = vp_playfield->x + border_size;
11304 int new_sy = vp_playfield->y + border_size;
11305 int new_sxsize = vp_playfield->width - 2 * border_size;
11306 int new_sysize = vp_playfield->height - 2 * border_size;
11307 int new_real_sx = vp_playfield->x;
11308 int new_real_sy = vp_playfield->y;
11309 int new_full_sxsize = vp_playfield->width;
11310 int new_full_sysize = vp_playfield->height;
11311 int new_dx = vp_door_1->x;
11312 int new_dy = vp_door_1->y;
11313 int new_dxsize = vp_door_1->width;
11314 int new_dysize = vp_door_1->height;
11315 int new_vx = vp_door_2->x;
11316 int new_vy = vp_door_2->y;
11317 int new_vxsize = vp_door_2->width;
11318 int new_vysize = vp_door_2->height;
11319 int new_ex = vp_door_3->x;
11320 int new_ey = vp_door_3->y;
11321 int new_exsize = vp_door_3->width;
11322 int new_eysize = vp_door_3->height;
11324 int new_tilesize_var = TILESIZE / (setup.small_game_graphics ? 2 : 1);
11325 int tilesize = (gfx_game_mode == GAME_MODE_PLAYING ? new_tilesize_var :
11326 gfx_game_mode == GAME_MODE_EDITOR ? MINI_TILESIZE : TILESIZE);
11327 int new_scr_fieldx = new_sxsize / tilesize;
11328 int new_scr_fieldy = new_sysize / tilesize;
11329 int new_scr_fieldx_buffers = new_sxsize / new_tilesize_var;
11330 int new_scr_fieldy_buffers = new_sysize / new_tilesize_var;
11332 int new_scr_fieldx = (vp_playfield->width - 2 * border_size) / TILESIZE;
11333 int new_scr_fieldy = (vp_playfield->height - 2 * border_size) / TILESIZE;
11335 boolean init_gfx_buffers = FALSE;
11336 boolean init_video_buffer = FALSE;
11337 boolean init_gadgets_and_toons = FALSE;
11340 /* !!! TEST ONLY !!! */
11341 // InitGfxBuffers();
11345 if (viewport.window.width != WIN_XSIZE ||
11346 viewport.window.height != WIN_YSIZE)
11348 WIN_XSIZE = viewport.window.width;
11349 WIN_YSIZE = viewport.window.height;
11352 init_video_buffer = TRUE;
11353 init_gfx_buffers = TRUE;
11355 InitVideoBuffer(WIN_XSIZE, WIN_YSIZE, DEFAULT_DEPTH, setup.fullscreen);
11359 SetDrawDeactivationMask(REDRAW_NONE);
11360 SetDrawBackgroundMask(REDRAW_FIELD);
11362 // RedrawBackground();
11366 // printf("::: video: init_video_buffer, init_gfx_buffers\n");
11369 if (new_scr_fieldx != SCR_FIELDX ||
11370 new_scr_fieldy != SCR_FIELDY)
11372 /* this always toggles between MAIN and GAME when using small tile size */
11374 SCR_FIELDX = new_scr_fieldx;
11375 SCR_FIELDY = new_scr_fieldy;
11377 // printf("::: new_scr_fieldx != SCR_FIELDX ...\n");
11381 if (new_tilesize_var != TILESIZE_VAR &&
11382 gfx_game_mode == GAME_MODE_PLAYING)
11384 /* doing this outside GAME_MODE_PLAYING would give wrong playfield size */
11386 TILESIZE_VAR = new_tilesize_var;
11388 init_gfx_buffers = TRUE;
11390 // printf("::: tilesize: init_gfx_buffers\n");
11394 if (new_sx != SX ||
11402 new_sxsize != SXSIZE ||
11403 new_sysize != SYSIZE ||
11404 new_dxsize != DXSIZE ||
11405 new_dysize != DYSIZE ||
11406 new_vxsize != VXSIZE ||
11407 new_vysize != VYSIZE ||
11408 new_exsize != EXSIZE ||
11409 new_eysize != EYSIZE ||
11410 new_real_sx != REAL_SX ||
11411 new_real_sy != REAL_SY ||
11412 new_full_sxsize != FULL_SXSIZE ||
11413 new_full_sysize != FULL_SYSIZE ||
11414 new_tilesize_var != TILESIZE_VAR
11417 vp_door_1->x != *door_1_x ||
11418 vp_door_1->y != *door_1_y ||
11419 vp_door_2->x != *door_2_x ||
11420 vp_door_2->y != *door_2_y
11432 SXSIZE = new_sxsize;
11433 SYSIZE = new_sysize;
11434 DXSIZE = new_dxsize;
11435 DYSIZE = new_dysize;
11436 VXSIZE = new_vxsize;
11437 VYSIZE = new_vysize;
11438 EXSIZE = new_exsize;
11439 EYSIZE = new_eysize;
11440 REAL_SX = new_real_sx;
11441 REAL_SY = new_real_sy;
11442 FULL_SXSIZE = new_full_sxsize;
11443 FULL_SYSIZE = new_full_sysize;
11444 TILESIZE_VAR = new_tilesize_var;
11447 printf("::: %d, %d, %d [%d]\n",
11448 SCR_FIELDX, SCR_FIELDY, TILESIZE_VAR,
11449 setup.small_game_graphics);
11453 *door_1_x = vp_door_1->x;
11454 *door_1_y = vp_door_1->y;
11455 *door_2_x = vp_door_2->x;
11456 *door_2_y = vp_door_2->y;
11460 init_gfx_buffers = TRUE;
11462 // printf("::: viewports: init_gfx_buffers\n");
11468 if (gfx_game_mode == GAME_MODE_MAIN)
11472 init_gadgets_and_toons = TRUE;
11474 // printf("::: viewports: init_gadgets_and_toons\n");
11482 if (init_gfx_buffers)
11484 // printf("::: init_gfx_buffers\n");
11486 SCR_FIELDX = new_scr_fieldx_buffers;
11487 SCR_FIELDY = new_scr_fieldy_buffers;
11491 SCR_FIELDX = new_scr_fieldx;
11492 SCR_FIELDY = new_scr_fieldy;
11495 if (init_video_buffer)
11497 // printf("::: init_video_buffer\n");
11499 InitVideoBuffer(WIN_XSIZE, WIN_YSIZE, DEFAULT_DEPTH, setup.fullscreen);
11501 SetDrawDeactivationMask(REDRAW_NONE);
11502 SetDrawBackgroundMask(REDRAW_FIELD);
11505 if (init_gadgets_and_toons)
11507 // printf("::: init_gadgets_and_toons\n");
11514 printf("::: %d, %d / %d, %d [%d]\n", VX, VY, EX, EY, game_status);