1 /***********************************************************
2 * Rocks'n'Diamonds -- McDuffin Strikes Back! *
3 *----------------------------------------------------------*
4 * (c) 1995-2002 Artsoft Entertainment *
6 * Detmolder Strasse 189 *
9 * e-mail: info@artsoft.org *
10 *----------------------------------------------------------*
12 ***********************************************************/
14 #include "libgame/libgame.h"
23 /* tool button identifiers */
24 #define TOOL_CTRL_ID_YES 0
25 #define TOOL_CTRL_ID_NO 1
26 #define TOOL_CTRL_ID_CONFIRM 2
27 #define TOOL_CTRL_ID_PLAYER_1 3
28 #define TOOL_CTRL_ID_PLAYER_2 4
29 #define TOOL_CTRL_ID_PLAYER_3 5
30 #define TOOL_CTRL_ID_PLAYER_4 6
32 #define NUM_TOOL_BUTTONS 7
34 /* forward declaration for internal use */
35 static void UnmapToolButtons();
36 static void HandleToolButtons(struct GadgetInfo *);
37 static int el_act_dir2crm(int, int, int);
38 static int el_act2crm(int, int);
40 static struct GadgetInfo *tool_gadget[NUM_TOOL_BUTTONS];
41 static int request_gadget_id = -1;
43 static char *print_if_not_empty(int element)
45 static char *s = NULL;
46 char *token_name = element_info[element].token_name;
51 s = checked_malloc(strlen(token_name) + 10 + 1);
53 if (element != EL_EMPTY)
54 sprintf(s, "%d\t['%s']", element, token_name);
56 sprintf(s, "%d", element);
61 void DumpTile(int x, int y)
67 printf("Field Info: SCREEN(%d, %d), LEVEL(%d, %d)\n", sx, sy, x, y);
70 if (!IN_LEV_FIELD(x, y))
72 printf("(not in level field)\n");
78 printf(" Feld: %d\t['%s']\n", Feld[x][y],
79 element_info[Feld[x][y]].token_name);
80 printf(" Back: %s\n", print_if_not_empty(Back[x][y]));
81 printf(" Store: %s\n", print_if_not_empty(Store[x][y]));
82 printf(" Store2: %s\n", print_if_not_empty(Store2[x][y]));
83 printf(" StorePlayer: %s\n", print_if_not_empty(StorePlayer[x][y]));
84 printf(" MovPos: %d\n", MovPos[x][y]);
85 printf(" MovDir: %d\n", MovDir[x][y]);
86 printf(" MovDelay: %d\n", MovDelay[x][y]);
87 printf(" ChangeDelay: %d\n", ChangeDelay[x][y]);
88 printf(" GfxElement: %d\n", GfxElement[x][y]);
89 printf(" GfxAction: %d\n", GfxAction[x][y]);
90 printf(" GfxFrame: %d\n", GfxFrame[x][y]);
94 void SetDrawtoField(int mode)
96 if (mode == DRAW_BUFFERED && setup.soft_scrolling)
107 drawto_field = fieldbuffer;
109 else /* DRAW_DIRECT, DRAW_BACKBUFFER */
115 BX2 = SCR_FIELDX - 1;
116 BY2 = SCR_FIELDY - 1;
120 drawto_field = (mode == DRAW_DIRECT ? window : backbuffer);
124 void RedrawPlayfield(boolean force_redraw, int x, int y, int width, int height)
126 if (game_status == GAME_MODE_PLAYING && !game.envelope_active)
132 width = gfx.sxsize + 2 * TILEX;
133 height = gfx.sysize + 2 * TILEY;
136 if (force_redraw || setup.direct_draw)
139 int x1 = (x - SX) / TILEX, y1 = (y - SY) / TILEY;
140 int x2 = (x - SX + width) / TILEX, y2 = (y - SY + height) / TILEY;
142 if (setup.direct_draw)
143 SetDrawtoField(DRAW_BACKBUFFER);
145 for (xx = BX1; xx <= BX2; xx++)
146 for (yy = BY1; yy <= BY2; yy++)
147 if (xx >= x1 && xx <= x2 && yy >= y1 && yy <= y2)
148 DrawScreenField(xx, yy);
151 if (setup.direct_draw)
152 SetDrawtoField(DRAW_DIRECT);
155 if (setup.soft_scrolling)
157 int fx = FX, fy = FY;
159 fx += (ScreenMovDir & (MV_LEFT|MV_RIGHT) ? ScreenGfxPos : 0);
160 fy += (ScreenMovDir & (MV_UP|MV_DOWN) ? ScreenGfxPos : 0);
162 BlitBitmap(fieldbuffer, backbuffer, fx,fy, SXSIZE,SYSIZE, SX,SY);
166 BlitBitmap(drawto, window, x, y, width, height, x, y);
172 DrawBuffer *buffer = (drawto_field == window ? backbuffer : drawto_field);
174 if (setup.direct_draw && game_status == GAME_MODE_PLAYING)
175 redraw_mask &= ~REDRAW_MAIN;
177 if (redraw_mask & REDRAW_TILES && redraw_tiles > REDRAWTILES_THRESHOLD)
178 redraw_mask |= REDRAW_FIELD;
180 if (redraw_mask & REDRAW_FIELD)
181 redraw_mask &= ~REDRAW_TILES;
183 if (redraw_mask == REDRAW_NONE)
186 if (global.fps_slowdown && game_status == GAME_MODE_PLAYING)
188 static boolean last_frame_skipped = FALSE;
189 boolean skip_even_when_not_scrolling = TRUE;
190 boolean just_scrolling = (ScreenMovDir != 0);
191 boolean verbose = FALSE;
193 if (global.fps_slowdown_factor > 1 &&
194 (FrameCounter % global.fps_slowdown_factor) &&
195 (just_scrolling || skip_even_when_not_scrolling))
197 redraw_mask &= ~REDRAW_MAIN;
199 last_frame_skipped = TRUE;
202 printf("FRAME SKIPPED\n");
206 if (last_frame_skipped)
207 redraw_mask |= REDRAW_FIELD;
209 last_frame_skipped = FALSE;
212 printf("frame not skipped\n");
216 /* synchronize X11 graphics at this point; if we would synchronize the
217 display immediately after the buffer switching (after the XFlush),
218 this could mean that we have to wait for the graphics to complete,
219 although we could go on doing calculations for the next frame */
223 if (redraw_mask & REDRAW_ALL)
225 BlitBitmap(backbuffer, window, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
229 if (redraw_mask & REDRAW_FIELD)
231 if (game_status != GAME_MODE_PLAYING ||
232 redraw_mask & REDRAW_FROM_BACKBUFFER)
234 BlitBitmap(backbuffer, window,
235 REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE, REAL_SX, REAL_SY);
239 int fx = FX, fy = FY;
241 if (setup.soft_scrolling)
243 fx += (ScreenMovDir & (MV_LEFT | MV_RIGHT) ? ScreenGfxPos : 0);
244 fy += (ScreenMovDir & (MV_UP | MV_DOWN) ? ScreenGfxPos : 0);
247 if (setup.soft_scrolling ||
248 ABS(ScreenMovPos) + ScrollStepSize == TILEX ||
249 ABS(ScreenMovPos) == ScrollStepSize ||
250 redraw_tiles > REDRAWTILES_THRESHOLD)
252 BlitBitmap(buffer, window, fx, fy, SXSIZE, SYSIZE, SX, SY);
256 printf("redrawing all (ScreenGfxPos == %d) because %s\n",
258 (setup.soft_scrolling ?
259 "setup.soft_scrolling" :
260 ABS(ScreenGfxPos) + ScrollStepSize == TILEX ?
261 "ABS(ScreenGfxPos) + ScrollStepSize == TILEX" :
262 ABS(ScreenGfxPos) == ScrollStepSize ?
263 "ABS(ScreenGfxPos) == ScrollStepSize" :
264 "redraw_tiles > REDRAWTILES_THRESHOLD"));
270 redraw_mask &= ~REDRAW_MAIN;
273 if (redraw_mask & REDRAW_DOORS)
275 if (redraw_mask & REDRAW_DOOR_1)
276 BlitBitmap(backbuffer, window, DX, DY, DXSIZE, DYSIZE, DX, DY);
278 if (redraw_mask & REDRAW_DOOR_2)
281 if ((redraw_mask & REDRAW_DOOR_2) == REDRAW_DOOR_2)
283 BlitBitmap(backbuffer, window, VX, VY, VXSIZE, VYSIZE, VX, VY);
287 if (redraw_mask & REDRAW_VIDEO_1)
288 BlitBitmap(backbuffer, window,
289 VX + VIDEO_DISPLAY1_XPOS, VY + VIDEO_DISPLAY1_YPOS,
290 VIDEO_DISPLAY_XSIZE, VIDEO_DISPLAY_YSIZE,
291 VX + VIDEO_DISPLAY1_XPOS, VY + VIDEO_DISPLAY1_YPOS);
292 if (redraw_mask & REDRAW_VIDEO_2)
293 BlitBitmap(backbuffer, window,
294 VX + VIDEO_DISPLAY2_XPOS, VY + VIDEO_DISPLAY2_YPOS,
295 VIDEO_DISPLAY_XSIZE, VIDEO_DISPLAY_YSIZE,
296 VX + VIDEO_DISPLAY2_XPOS, VY + VIDEO_DISPLAY2_YPOS);
297 if (redraw_mask & REDRAW_VIDEO_3)
298 BlitBitmap(backbuffer, window,
299 VX + VIDEO_CONTROL_XPOS, VY + VIDEO_CONTROL_YPOS,
300 VIDEO_CONTROL_XSIZE, VIDEO_CONTROL_YSIZE,
301 VX + VIDEO_CONTROL_XPOS, VY + VIDEO_CONTROL_YPOS);
306 if (redraw_mask & REDRAW_DOOR_3)
307 BlitBitmap(backbuffer, window, EX, EY, EXSIZE, EYSIZE, EX, EY);
309 redraw_mask &= ~REDRAW_DOORS;
312 if (redraw_mask & REDRAW_MICROLEVEL)
314 BlitBitmap(backbuffer, window, SX, SY + 10 * TILEY, SXSIZE, 7 * TILEY,
315 SX, SY + 10 * TILEY);
317 redraw_mask &= ~REDRAW_MICROLEVEL;
320 if (redraw_mask & REDRAW_TILES)
322 for (x = 0; x < SCR_FIELDX; x++)
323 for (y = 0 ; y < SCR_FIELDY; y++)
324 if (redraw[redraw_x1 + x][redraw_y1 + y])
325 BlitBitmap(buffer, window,
326 FX + x * TILEX, FY + y * TILEY, TILEX, TILEY,
327 SX + x * TILEX, SY + y * TILEY);
330 if (redraw_mask & REDRAW_FPS) /* display frames per second */
335 sprintf(info1, " (only every %d. frame)", global.fps_slowdown_factor);
336 if (!global.fps_slowdown)
339 sprintf(text, "%.1f fps%s", global.frames_per_second, info1);
340 DrawTextExt(window, SX, SY, text, FONT_TEXT_2, BLIT_OPAQUE);
345 for (x = 0; x < MAX_BUF_XSIZE; x++)
346 for (y = 0; y < MAX_BUF_YSIZE; y++)
349 redraw_mask = REDRAW_NONE;
355 long fading_delay = 300;
357 if (setup.fading && (redraw_mask & REDRAW_FIELD))
364 ClearRectangle(window, REAL_SX,REAL_SY,FULL_SXSIZE,FULL_SYSIZE);
367 for (i = 0; i < 2 * FULL_SYSIZE; i++)
369 for (y = 0; y < FULL_SYSIZE; y++)
371 BlitBitmap(backbuffer, window,
372 REAL_SX,REAL_SY+i, FULL_SXSIZE,1, REAL_SX,REAL_SY+i);
380 for (i = 1; i < FULL_SYSIZE; i+=2)
381 BlitBitmap(backbuffer, window,
382 REAL_SX,REAL_SY+i, FULL_SXSIZE,1, REAL_SX,REAL_SY+i);
388 SetClipOrigin(clip_gc[PIX_FADEMASK], 0, 0);
389 BlitBitmapMasked(backbuffer, window,
390 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE,
395 SetClipOrigin(clip_gc[PIX_FADEMASK], -1, -1);
396 BlitBitmapMasked(backbuffer, window,
397 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE,
402 SetClipOrigin(clip_gc[PIX_FADEMASK], 0, -1);
403 BlitBitmapMasked(backbuffer, window,
404 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE,
409 SetClipOrigin(clip_gc[PIX_FADEMASK], -1, 0);
410 BlitBitmapMasked(backbuffer, window,
411 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE,
416 redraw_mask &= ~REDRAW_MAIN;
423 void SetMainBackgroundImage(int graphic)
425 SetMainBackgroundBitmap(graphic == IMG_UNDEFINED ? NULL :
426 graphic_info[graphic].bitmap ?
427 graphic_info[graphic].bitmap :
428 graphic_info[IMG_BACKGROUND].bitmap);
431 void SetDoorBackgroundImage(int graphic)
433 SetDoorBackgroundBitmap(graphic == IMG_UNDEFINED ? NULL :
434 graphic_info[graphic].bitmap ?
435 graphic_info[graphic].bitmap :
436 graphic_info[IMG_BACKGROUND].bitmap);
439 void DrawBackground(int dest_x, int dest_y, int width, int height)
441 ClearRectangleOnBackground(backbuffer, dest_x, dest_y, width, height);
443 redraw_mask |= REDRAW_FIELD;
448 DrawBackground(REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE);
450 if (setup.soft_scrolling && game_status == GAME_MODE_PLAYING)
452 ClearRectangle(fieldbuffer, 0, 0, FXSIZE, FYSIZE);
453 SetDrawtoField(DRAW_BUFFERED);
456 SetDrawtoField(DRAW_BACKBUFFER);
458 if (setup.direct_draw && game_status == GAME_MODE_PLAYING)
460 ClearRectangle(window, REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE);
461 SetDrawtoField(DRAW_DIRECT);
465 void MarkTileDirty(int x, int y)
467 int xx = redraw_x1 + x;
468 int yy = redraw_y1 + y;
473 redraw[xx][yy] = TRUE;
474 redraw_mask |= REDRAW_TILES;
477 void SetBorderElement()
481 BorderElement = EL_EMPTY;
483 for (y = 0; y < lev_fieldy && BorderElement == EL_EMPTY; y++)
485 for (x = 0; x < lev_fieldx; x++)
487 if (!IS_INDESTRUCTIBLE(Feld[x][y]))
488 BorderElement = EL_STEELWALL;
490 if (y != 0 && y != lev_fieldy - 1 && x != lev_fieldx - 1)
496 void SetRandomAnimationValue(int x, int y)
498 gfx.anim_random_frame = GfxRandom[x][y];
501 inline int getGraphicAnimationFrame(int graphic, int sync_frame)
503 /* animation synchronized with global frame counter, not move position */
504 if (graphic_info[graphic].anim_global_sync || sync_frame < 0)
505 sync_frame = FrameCounter;
507 return getAnimationFrame(graphic_info[graphic].anim_frames,
508 graphic_info[graphic].anim_delay,
509 graphic_info[graphic].anim_mode,
510 graphic_info[graphic].anim_start_frame,
514 inline void DrawGraphicAnimationExt(DrawBuffer *dst_bitmap, int x, int y,
515 int graphic, int sync_frame, int mask_mode)
517 int frame = getGraphicAnimationFrame(graphic, sync_frame);
519 if (mask_mode == USE_MASKING)
520 DrawGraphicThruMaskExt(dst_bitmap, x, y, graphic, frame);
522 DrawGraphicExt(dst_bitmap, x, y, graphic, frame);
525 inline void DrawGraphicAnimation(int x, int y, int graphic)
527 int lx = LEVELX(x), ly = LEVELY(y);
529 if (!IN_SCR_FIELD(x, y))
532 DrawGraphicAnimationExt(drawto_field, FX + x * TILEX, FY + y * TILEY,
533 graphic, GfxFrame[lx][ly], NO_MASKING);
537 void DrawLevelGraphicAnimation(int x, int y, int graphic)
539 DrawGraphicAnimation(SCREENX(x), SCREENY(y), graphic);
542 void DrawLevelElementAnimation(int x, int y, int element)
545 int graphic = el_act_dir2img(element, GfxAction[x][y], GfxDir[x][y]);
547 DrawGraphicAnimation(SCREENX(x), SCREENY(y), graphic);
549 DrawGraphicAnimation(SCREENX(x), SCREENY(y), el2img(element));
553 inline void DrawLevelGraphicAnimationIfNeeded(int x, int y, int graphic)
555 int sx = SCREENX(x), sy = SCREENY(y);
557 if (!IN_LEV_FIELD(x, y) || !IN_SCR_FIELD(sx, sy))
560 if (!IS_NEW_FRAME(GfxFrame[x][y], graphic))
563 DrawGraphicAnimation(sx, sy, graphic);
565 if (GFX_CRUMBLED(Feld[x][y]))
566 DrawLevelFieldCrumbledSand(x, y);
569 void DrawLevelElementAnimationIfNeeded(int x, int y, int element)
571 int sx = SCREENX(x), sy = SCREENY(y);
574 if (!IN_LEV_FIELD(x, y) || !IN_SCR_FIELD(sx, sy))
577 graphic = el_act_dir2img(element, GfxAction[x][y], GfxDir[x][y]);
579 if (!IS_NEW_FRAME(GfxFrame[x][y], graphic))
582 DrawGraphicAnimation(sx, sy, graphic);
584 if (GFX_CRUMBLED(element))
585 DrawLevelFieldCrumbledSand(x, y);
588 static int getPlayerGraphic(struct PlayerInfo *player, int move_dir)
590 if (player->use_murphy_graphic)
592 /* this works only because currently only one player can be "murphy" ... */
593 static int last_horizontal_dir = MV_LEFT;
594 int graphic = el_act_dir2img(EL_SP_MURPHY, player->GfxAction, move_dir);
596 if (move_dir == MV_LEFT || move_dir == MV_RIGHT)
597 last_horizontal_dir = move_dir;
599 if (graphic == IMG_SP_MURPHY) /* undefined => use special graphic */
601 int direction = (player->is_snapping ? move_dir : last_horizontal_dir);
603 graphic = el_act_dir2img(EL_SP_MURPHY, player->GfxAction, direction);
609 return el_act_dir2img(player->element_nr, player->GfxAction, move_dir);
612 static boolean equalGraphics(int graphic1, int graphic2)
614 struct GraphicInfo *g1 = &graphic_info[graphic1];
615 struct GraphicInfo *g2 = &graphic_info[graphic2];
617 return (g1->bitmap == g2->bitmap &&
618 g1->src_x == g2->src_x &&
619 g1->src_y == g2->src_y &&
620 g1->anim_frames == g2->anim_frames &&
621 g1->anim_delay == g2->anim_delay &&
622 g1->anim_mode == g2->anim_mode);
625 void DrawAllPlayers()
629 for (i = 0; i < MAX_PLAYERS; i++)
630 if (stored_player[i].active)
631 DrawPlayer(&stored_player[i]);
634 void DrawPlayerField(int x, int y)
636 if (!IS_PLAYER(x, y))
639 DrawPlayer(PLAYERINFO(x, y));
642 void DrawPlayer(struct PlayerInfo *player)
646 int move_dir = player->MovDir;
648 int last_jx = player->last_jx;
649 int last_jy = player->last_jy;
650 int next_jx = jx + (jx - last_jx);
651 int next_jy = jy + (jy - last_jy);
652 boolean player_is_moving = (last_jx != jx || last_jy != jy ? TRUE : FALSE);
654 int dx = (move_dir == MV_LEFT ? -1 : move_dir == MV_RIGHT ? +1 : 0);
655 int dy = (move_dir == MV_UP ? -1 : move_dir == MV_DOWN ? +1 : 0);
656 int last_jx = (player->is_moving ? jx - dx : jx);
657 int last_jy = (player->is_moving ? jy - dy : jy);
658 int next_jx = jx + dx;
659 int next_jy = jy + dy;
660 boolean player_is_moving = (player->MovPos ? TRUE : FALSE);
662 int sx = SCREENX(jx), sy = SCREENY(jy);
663 int sxx = 0, syy = 0;
664 int element = Feld[jx][jy], last_element = Feld[last_jx][last_jy];
666 int action = ACTION_DEFAULT;
667 int last_player_graphic = getPlayerGraphic(player, move_dir);
668 int last_player_frame = player->Frame;
671 if (!player->active || !IN_SCR_FIELD(SCREENX(last_jx), SCREENY(last_jy)))
675 if (!IN_LEV_FIELD(jx, jy))
677 printf("DrawPlayerField(): x = %d, y = %d\n",jx,jy);
678 printf("DrawPlayerField(): sx = %d, sy = %d\n",sx,sy);
679 printf("DrawPlayerField(): This should never happen!\n");
684 if (element == EL_EXPLOSION)
687 action = (player->is_pushing ? ACTION_PUSHING :
688 player->is_digging ? ACTION_DIGGING :
689 player->is_collecting ? ACTION_COLLECTING :
690 player->is_moving ? ACTION_MOVING :
691 player->is_snapping ? ACTION_SNAPPING :
692 player->is_dropping ? ACTION_DROPPING :
693 player->is_waiting ? player->action_waiting : ACTION_DEFAULT);
695 InitPlayerGfxAnimation(player, action, move_dir);
697 /* ----------------------------------------------------------------------- */
698 /* draw things in the field the player is leaving, if needed */
699 /* ----------------------------------------------------------------------- */
702 if (player->is_moving)
704 if (player_is_moving)
707 if (Back[last_jx][last_jy] && IS_DRAWABLE(last_element))
709 DrawLevelElement(last_jx, last_jy, Back[last_jx][last_jy]);
711 if (last_element == EL_DYNAMITE_ACTIVE ||
712 last_element == EL_SP_DISK_RED_ACTIVE)
713 DrawDynamite(last_jx, last_jy);
715 DrawLevelFieldThruMask(last_jx, last_jy);
717 else if (last_element == EL_DYNAMITE_ACTIVE ||
718 last_element == EL_SP_DISK_RED_ACTIVE)
719 DrawDynamite(last_jx, last_jy);
721 DrawLevelField(last_jx, last_jy);
723 if (player->is_pushing && IN_SCR_FIELD(SCREENX(next_jx), SCREENY(next_jy)))
724 DrawLevelElement(next_jx, next_jy, EL_EMPTY);
727 if (!IN_SCR_FIELD(sx, sy))
730 if (setup.direct_draw)
731 SetDrawtoField(DRAW_BUFFERED);
733 /* ----------------------------------------------------------------------- */
734 /* draw things behind the player, if needed */
735 /* ----------------------------------------------------------------------- */
738 DrawLevelElement(jx, jy, Back[jx][jy]);
739 else if (IS_ACTIVE_BOMB(element))
740 DrawLevelElement(jx, jy, EL_EMPTY);
743 if (player_is_moving && GfxElement[jx][jy] != EL_UNDEFINED)
745 if (GFX_CRUMBLED(GfxElement[jx][jy]))
746 DrawLevelFieldCrumbledSandDigging(jx, jy, move_dir, player->StepFrame);
749 int old_element = GfxElement[jx][jy];
750 int old_graphic = el_act_dir2img(old_element, action, move_dir);
751 int frame = getGraphicAnimationFrame(old_graphic, player->StepFrame);
753 DrawGraphic(sx, sy, old_graphic, frame);
758 GfxElement[jx][jy] = EL_UNDEFINED;
760 DrawLevelField(jx, jy);
764 /* ----------------------------------------------------------------------- */
765 /* draw player himself */
766 /* ----------------------------------------------------------------------- */
770 graphic = getPlayerGraphic(player, move_dir);
772 /* in the case of changed player action or direction, prevent the current
773 animation frame from being restarted for identical animations */
774 if (player->Frame == 0 && equalGraphics(graphic, last_player_graphic))
775 player->Frame = last_player_frame;
779 if (player->use_murphy_graphic)
781 static int last_horizontal_dir = MV_LEFT;
783 if (move_dir == MV_LEFT || move_dir == MV_RIGHT)
784 last_horizontal_dir = move_dir;
786 graphic = el_act_dir2img(EL_SP_MURPHY, player->GfxAction, move_dir);
788 if (graphic == IMG_SP_MURPHY) /* undefined => use special graphic */
790 int direction = (player->is_snapping ? move_dir : last_horizontal_dir);
792 graphic = el_act_dir2img(EL_SP_MURPHY, player->GfxAction, direction);
796 graphic = el_act_dir2img(player->element_nr, player->GfxAction, move_dir);
800 frame = getGraphicAnimationFrame(graphic, player->Frame);
804 if (move_dir == MV_LEFT || move_dir == MV_RIGHT)
805 sxx = player->GfxPos;
807 syy = player->GfxPos;
810 if (!setup.soft_scrolling && ScreenMovPos)
813 DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, frame, NO_CUTTING);
815 if (SHIELD_ON(player))
817 int graphic = (player->shield_deadly_time_left ? IMG_SHIELD_DEADLY_ACTIVE :
818 IMG_SHIELD_NORMAL_ACTIVE);
819 int frame = getGraphicAnimationFrame(graphic, -1);
821 DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, frame, NO_CUTTING);
824 /* ----------------------------------------------------------------------- */
825 /* draw things the player is pushing, if needed */
826 /* ----------------------------------------------------------------------- */
829 printf("::: %d, %d [%d, %d] [%d]\n",
830 player->is_pushing, player_is_moving, player->GfxAction,
831 player->is_moving, player_is_moving);
835 if (player->is_pushing && player->is_moving)
837 if (player->is_pushing && player_is_moving)
840 int px = SCREENX(next_jx), py = SCREENY(next_jy);
842 if (Back[next_jx][next_jy])
843 DrawLevelElement(next_jx, next_jy, Back[next_jx][next_jy]);
845 if ((sxx || syy) && element == EL_SOKOBAN_OBJECT)
846 DrawGraphicShiftedThruMask(px, py, sxx, syy, IMG_SOKOBAN_OBJECT, 0,
850 int element = MovingOrBlocked2Element(next_jx, next_jy);
851 int graphic = el_act_dir2img(element, ACTION_PUSHING, move_dir);
853 int frame = getGraphicAnimationFrame(graphic, player->StepFrame);
855 int frame = getGraphicAnimationFrame(graphic, player->Frame);
858 DrawGraphicShifted(px, py, sxx, syy, graphic, frame,
859 NO_CUTTING, NO_MASKING);
863 /* ----------------------------------------------------------------------- */
864 /* draw things in front of player (active dynamite or dynabombs) */
865 /* ----------------------------------------------------------------------- */
867 if (IS_ACTIVE_BOMB(element))
869 graphic = el2img(element);
870 frame = getGraphicAnimationFrame(graphic, GfxFrame[jx][jy]);
872 if (game.emulation == EMU_SUPAPLEX)
873 DrawGraphic(sx, sy, IMG_SP_DISK_RED, frame);
875 DrawGraphicThruMask(sx, sy, graphic, frame);
878 if (player_is_moving && last_element == EL_EXPLOSION)
880 int graphic = el_act2img(GfxElement[last_jx][last_jy], ACTION_EXPLODING);
881 int delay = (game.emulation == EMU_SUPAPLEX ? 3 : 2);
882 int phase = ExplodePhase[last_jx][last_jy] - 1;
883 int frame = getGraphicAnimationFrame(graphic, phase - delay);
886 DrawGraphicThruMask(SCREENX(last_jx), SCREENY(last_jy), graphic, frame);
889 /* ----------------------------------------------------------------------- */
890 /* draw elements the player is just walking/passing through/under */
891 /* ----------------------------------------------------------------------- */
893 if (player_is_moving)
895 /* handle the field the player is leaving ... */
896 if (IS_ACCESSIBLE_INSIDE(last_element))
897 DrawLevelField(last_jx, last_jy);
898 else if (IS_ACCESSIBLE_UNDER(last_element))
899 DrawLevelFieldThruMask(last_jx, last_jy);
903 /* do not redraw accessible elements if the player is just pushing them */
904 if (!player_is_moving || !player->is_pushing)
906 /* ... and the field the player is entering */
907 if (IS_ACCESSIBLE_INSIDE(element))
908 DrawLevelField(jx, jy);
909 else if (IS_ACCESSIBLE_UNDER(element))
910 DrawLevelFieldThruMask(jx, jy);
916 /* !!! I have forgotton what this should be good for !!! */
917 /* !!! causes player being visible when pushing from within tubes !!! */
918 if (!player->is_pushing)
921 /* ... and the field the player is entering */
922 if (IS_ACCESSIBLE_INSIDE(element))
923 DrawLevelField(jx, jy);
924 else if (IS_ACCESSIBLE_UNDER(element))
925 DrawLevelFieldThruMask(jx, jy);
929 if (setup.direct_draw)
931 int dest_x = SX + SCREENX(MIN(jx, last_jx)) * TILEX;
932 int dest_y = SY + SCREENY(MIN(jy, last_jy)) * TILEY;
933 int x_size = TILEX * (1 + ABS(jx - last_jx));
934 int y_size = TILEY * (1 + ABS(jy - last_jy));
936 BlitBitmap(drawto_field, window,
937 dest_x, dest_y, x_size, y_size, dest_x, dest_y);
938 SetDrawtoField(DRAW_DIRECT);
941 MarkTileDirty(sx, sy);
944 void getGraphicSource(int graphic, int frame, Bitmap **bitmap, int *x, int *y)
946 struct GraphicInfo *g = &graphic_info[graphic];
950 if (g->offset_y == 0) /* frames are ordered horizontally */
952 int max_width = g->anim_frames_per_line * g->width;
954 *x = (g->src_x + frame * g->offset_x) % max_width;
955 *y = g->src_y + (g->src_x + frame * g->offset_x) / max_width * g->height;
957 else if (g->offset_x == 0) /* frames are ordered vertically */
959 int max_height = g->anim_frames_per_line * g->height;
961 *x = g->src_x + (g->src_y + frame * g->offset_y) / max_height * g->width;
962 *y = (g->src_y + frame * g->offset_y) % max_height;
964 else /* frames are ordered diagonally */
966 *x = g->src_x + frame * g->offset_x;
967 *y = g->src_y + frame * g->offset_y;
971 void DrawGraphic(int x, int y, int graphic, int frame)
974 if (!IN_SCR_FIELD(x, y))
976 printf("DrawGraphic(): x = %d, y = %d, graphic = %d\n", x, y, graphic);
977 printf("DrawGraphic(): This should never happen!\n");
982 DrawGraphicExt(drawto_field, FX + x * TILEX, FY + y * TILEY, graphic, frame);
986 void DrawGraphicExt(DrawBuffer *dst_bitmap, int x, int y, int graphic,
992 getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
993 BlitBitmap(src_bitmap, dst_bitmap, src_x, src_y, TILEX, TILEY, x, y);
996 void DrawGraphicThruMask(int x, int y, int graphic, int frame)
999 if (!IN_SCR_FIELD(x, y))
1001 printf("DrawGraphicThruMask(): x = %d,y = %d, graphic = %d\n",x,y,graphic);
1002 printf("DrawGraphicThruMask(): This should never happen!\n");
1007 DrawGraphicThruMaskExt(drawto_field, FX + x * TILEX, FY + y *TILEY, graphic,
1009 MarkTileDirty(x, y);
1012 void DrawGraphicThruMaskExt(DrawBuffer *d, int dest_x, int dest_y, int graphic,
1020 getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
1021 drawing_gc = src_bitmap->stored_clip_gc;
1023 GC drawing_gc = src_bitmap->stored_clip_gc;
1024 Bitmap *src_bitmap = graphic_info[graphic].bitmap;
1025 int src_x = graphic_info[graphic].src_x;
1026 int src_y = graphic_info[graphic].src_y;
1027 int offset_x = graphic_info[graphic].offset_x;
1028 int offset_y = graphic_info[graphic].offset_y;
1030 src_x += frame * offset_x;
1031 src_y += frame * offset_y;
1035 SetClipOrigin(src_bitmap, drawing_gc, dest_x - src_x, dest_y - src_y);
1036 BlitBitmapMasked(src_bitmap, d, src_x, src_y, TILEX, TILEY, dest_x, dest_y);
1039 void DrawMiniGraphic(int x, int y, int graphic)
1041 DrawMiniGraphicExt(drawto, SX + x * MINI_TILEX,SY + y * MINI_TILEY, graphic);
1042 MarkTileDirty(x / 2, y / 2);
1045 void getMiniGraphicSource(int graphic, Bitmap **bitmap, int *x, int *y)
1047 struct GraphicInfo *g = &graphic_info[graphic];
1048 int mini_startx = 0;
1049 int mini_starty = g->bitmap->height * 2 / 3;
1051 *bitmap = g->bitmap;
1052 *x = mini_startx + g->src_x / 2;
1053 *y = mini_starty + g->src_y / 2;
1056 void DrawMiniGraphicExt(DrawBuffer *d, int x, int y, int graphic)
1061 getMiniGraphicSource(graphic, &src_bitmap, &src_x, &src_y);
1062 BlitBitmap(src_bitmap, d, src_x, src_y, MINI_TILEX, MINI_TILEY, x, y);
1065 void DrawGraphicShifted(int x, int y, int dx, int dy, int graphic, int frame,
1066 int cut_mode, int mask_mode)
1071 int width = TILEX, height = TILEY;
1077 DrawGraphic(x, y, graphic, frame);
1081 if (dx || dy) /* shifted graphic */
1083 if (x < BX1) /* object enters playfield from the left */
1090 else if (x > BX2) /* object enters playfield from the right */
1096 else if (x==BX1 && dx < 0) /* object leaves playfield to the left */
1102 else if (x==BX2 && dx > 0) /* object leaves playfield to the right */
1104 else if (dx) /* general horizontal movement */
1105 MarkTileDirty(x + SIGN(dx), y);
1107 if (y < BY1) /* object enters playfield from the top */
1109 if (cut_mode==CUT_BELOW) /* object completely above top border */
1117 else if (y > BY2) /* object enters playfield from the bottom */
1123 else if (y==BY1 && dy < 0) /* object leaves playfield to the top */
1129 else if (dy > 0 && cut_mode == CUT_ABOVE)
1131 if (y == BY2) /* object completely above bottom border */
1137 MarkTileDirty(x, y + 1);
1138 } /* object leaves playfield to the bottom */
1139 else if (dy > 0 && (y == BY2 || cut_mode == CUT_BELOW))
1141 else if (dy) /* general vertical movement */
1142 MarkTileDirty(x, y + SIGN(dy));
1146 getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
1148 src_bitmap = graphic_info[graphic].bitmap;
1149 src_x = graphic_info[graphic].src_x;
1150 src_y = graphic_info[graphic].src_y;
1151 offset_x = graphic_info[graphic].offset_x;
1152 offset_y = graphic_info[graphic].offset_y;
1154 src_x += frame * offset_x;
1155 src_y += frame * offset_y;
1158 drawing_gc = src_bitmap->stored_clip_gc;
1163 dest_x = FX + x * TILEX + dx;
1164 dest_y = FY + y * TILEY + dy;
1167 if (!IN_SCR_FIELD(x,y))
1169 printf("DrawGraphicShifted(): x = %d, y = %d, graphic = %d\n",x,y,graphic);
1170 printf("DrawGraphicShifted(): This should never happen!\n");
1175 if (mask_mode == USE_MASKING)
1177 SetClipOrigin(src_bitmap, drawing_gc, dest_x - src_x, dest_y - src_y);
1178 BlitBitmapMasked(src_bitmap, drawto_field, src_x, src_y, width, height,
1182 BlitBitmap(src_bitmap, drawto_field, src_x, src_y, width, height,
1185 MarkTileDirty(x, y);
1188 void DrawGraphicShiftedThruMask(int x, int y, int dx, int dy, int graphic,
1189 int frame, int cut_mode)
1191 DrawGraphicShifted(x, y, dx, dy, graphic, frame, cut_mode, USE_MASKING);
1194 void DrawScreenElementExt(int x, int y, int dx, int dy, int element,
1195 int cut_mode, int mask_mode)
1197 int lx = LEVELX(x), ly = LEVELY(y);
1201 if (IN_LEV_FIELD(lx, ly))
1203 SetRandomAnimationValue(lx, ly);
1205 graphic = el_act_dir2img(element, GfxAction[lx][ly], GfxDir[lx][ly]);
1206 frame = getGraphicAnimationFrame(graphic, GfxFrame[lx][ly]);
1208 else /* border element */
1210 graphic = el2img(element);
1211 frame = getGraphicAnimationFrame(graphic, -1);
1214 if (element == EL_EXPANDABLE_WALL)
1216 boolean left_stopped = FALSE, right_stopped = FALSE;
1218 if (!IN_LEV_FIELD(lx - 1, ly) || IS_WALL(Feld[lx - 1][ly]))
1219 left_stopped = TRUE;
1220 if (!IN_LEV_FIELD(lx + 1, ly) || IS_WALL(Feld[lx + 1][ly]))
1221 right_stopped = TRUE;
1223 if (left_stopped && right_stopped)
1225 else if (left_stopped)
1227 graphic = IMG_EXPANDABLE_WALL_GROWING_RIGHT;
1228 frame = graphic_info[graphic].anim_frames - 1;
1230 else if (right_stopped)
1232 graphic = IMG_EXPANDABLE_WALL_GROWING_LEFT;
1233 frame = graphic_info[graphic].anim_frames - 1;
1238 DrawGraphicShifted(x, y, dx, dy, graphic, frame, cut_mode, mask_mode);
1239 else if (mask_mode == USE_MASKING)
1240 DrawGraphicThruMask(x, y, graphic, frame);
1242 DrawGraphic(x, y, graphic, frame);
1245 void DrawLevelElementExt(int x, int y, int dx, int dy, int element,
1246 int cut_mode, int mask_mode)
1248 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1249 DrawScreenElementExt(SCREENX(x), SCREENY(y), dx, dy, element,
1250 cut_mode, mask_mode);
1253 void DrawScreenElementShifted(int x, int y, int dx, int dy, int element,
1256 DrawScreenElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
1259 void DrawLevelElementShifted(int x, int y, int dx, int dy, int element,
1262 DrawLevelElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
1265 void DrawLevelElementThruMask(int x, int y, int element)
1267 DrawLevelElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
1270 void DrawLevelFieldThruMask(int x, int y)
1272 DrawLevelElementExt(x, y, 0, 0, Feld[x][y], NO_CUTTING, USE_MASKING);
1275 #define TILE_GFX_ELEMENT(x, y) \
1276 (GfxElement[x][y] != EL_UNDEFINED && Feld[x][y] != EL_EXPLOSION ? \
1277 GfxElement[x][y] : Feld[x][y])
1279 static void DrawLevelFieldCrumbledSandExt(int x, int y, int graphic, int frame)
1283 int sx = SCREENX(x), sy = SCREENY(y);
1285 int width, height, cx, cy, i;
1287 int crumbled_border_size = graphic_info[graphic].border_size;
1289 int snip = TILEX / 8; /* number of border pixels from "crumbled graphic" */
1291 static int xy[4][2] =
1300 if (x == 0 && y == 7)
1301 printf("::: %d, %d [%d]\n", GfxElement[x][y], Feld[x][y],
1302 crumbled_border_size);
1305 if (!IN_LEV_FIELD(x, y))
1308 element = TILE_GFX_ELEMENT(x, y);
1310 /* crumble field itself */
1311 if (GFX_CRUMBLED(element) && !IS_MOVING(x, y))
1313 if (!IN_SCR_FIELD(sx, sy))
1316 getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
1318 for (i = 0; i < 4; i++)
1320 int xx = x + xy[i][0];
1321 int yy = y + xy[i][1];
1324 element = (IN_LEV_FIELD(xx, yy) ? TILE_GFX_ELEMENT(xx, yy) :
1327 element = (IN_LEV_FIELD(xx, yy) ? Feld[xx][yy] : BorderElement);
1330 /* check if neighbour field is of same type */
1331 if (GFX_CRUMBLED(element) && !IS_MOVING(xx, yy))
1335 if (Feld[x][y] == EL_CUSTOM_START + 123)
1336 printf("::: crumble [%d] THE CHAOS ENGINE (%d, %d): %d, %d\n",
1337 i, Feld[x][y], element,
1338 GFX_CRUMBLED(element), IS_MOVING(x, y));
1341 if (i == 1 || i == 2)
1343 width = crumbled_border_size;
1345 cx = (i == 2 ? TILEX - crumbled_border_size : 0);
1351 height = crumbled_border_size;
1353 cy = (i == 3 ? TILEY - crumbled_border_size : 0);
1356 BlitBitmap(src_bitmap, drawto_field, src_x + cx, src_y + cy,
1357 width, height, FX + sx * TILEX + cx, FY + sy * TILEY + cy);
1360 MarkTileDirty(sx, sy);
1362 else /* crumble neighbour fields */
1365 getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
1368 for (i = 0; i < 4; i++)
1370 int xx = x + xy[i][0];
1371 int yy = y + xy[i][1];
1372 int sxx = sx + xy[i][0];
1373 int syy = sy + xy[i][1];
1376 if (!IN_LEV_FIELD(xx, yy) ||
1377 !IN_SCR_FIELD(sxx, syy) ||
1381 element = TILE_GFX_ELEMENT(xx, yy);
1383 if (!GFX_CRUMBLED(element))
1386 if (!IN_LEV_FIELD(xx, yy) ||
1387 !IN_SCR_FIELD(sxx, syy) ||
1388 !GFX_CRUMBLED(Feld[xx][yy]) ||
1394 graphic = el_act2crm(Feld[xx][yy], ACTION_DEFAULT);
1395 crumbled_border_size = graphic_info[graphic].border_size;
1397 getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
1400 if (i == 1 || i == 2)
1402 width = crumbled_border_size;
1404 cx = (i == 1 ? TILEX - crumbled_border_size : 0);
1410 height = crumbled_border_size;
1412 cy = (i == 0 ? TILEY - crumbled_border_size : 0);
1415 BlitBitmap(src_bitmap, drawto_field, src_x + cx, src_y + cy,
1416 width, height, FX + sxx * TILEX + cx, FY + syy * TILEY + cy);
1418 MarkTileDirty(sxx, syy);
1423 void DrawLevelFieldCrumbledSand(int x, int y)
1428 if (!IN_LEV_FIELD(x, y))
1431 graphic = el_act2crm(Feld[x][y], ACTION_DEFAULT);
1433 DrawLevelFieldCrumbledSandExt(x, y, graphic, 0);
1435 DrawLevelFieldCrumbledSandExt(x, y, IMG_SAND_CRUMBLED, 0);
1439 void DrawLevelFieldCrumbledSandDigging(int x, int y, int direction,
1443 int graphic1 = el_act_dir2img(GfxElement[x][y], ACTION_DIGGING, direction);
1444 int graphic2 = el_act_dir2crm(GfxElement[x][y], ACTION_DIGGING, direction);
1446 int graphic1 = el_act_dir2img(EL_SAND, ACTION_DIGGING, direction);
1447 int graphic2 = el_act_dir2img(EL_SAND_CRUMBLED, ACTION_DIGGING, direction);
1449 int frame1 = getGraphicAnimationFrame(graphic1, step_frame);
1450 int frame2 = getGraphicAnimationFrame(graphic2, step_frame);
1451 int sx = SCREENX(x), sy = SCREENY(y);
1453 DrawGraphic(sx, sy, graphic1, frame1);
1454 DrawLevelFieldCrumbledSandExt(x, y, graphic2, frame2);
1457 void DrawLevelFieldCrumbledSandNeighbours(int x, int y)
1459 int sx = SCREENX(x), sy = SCREENY(y);
1460 static int xy[4][2] =
1469 for (i = 0; i < 4; i++)
1471 int xx = x + xy[i][0];
1472 int yy = y + xy[i][1];
1473 int sxx = sx + xy[i][0];
1474 int syy = sy + xy[i][1];
1476 if (!IN_LEV_FIELD(xx, yy) ||
1477 !IN_SCR_FIELD(sxx, syy) ||
1478 !GFX_CRUMBLED(Feld[xx][yy]) ||
1482 DrawLevelField(xx, yy);
1486 static int getBorderElement(int x, int y)
1490 { EL_STEELWALL_TOPLEFT, EL_INVISIBLE_STEELWALL_TOPLEFT },
1491 { EL_STEELWALL_TOPRIGHT, EL_INVISIBLE_STEELWALL_TOPRIGHT },
1492 { EL_STEELWALL_BOTTOMLEFT, EL_INVISIBLE_STEELWALL_BOTTOMLEFT },
1493 { EL_STEELWALL_BOTTOMRIGHT, EL_INVISIBLE_STEELWALL_BOTTOMRIGHT },
1494 { EL_STEELWALL_VERTICAL, EL_INVISIBLE_STEELWALL_VERTICAL },
1495 { EL_STEELWALL_HORIZONTAL, EL_INVISIBLE_STEELWALL_HORIZONTAL },
1496 { EL_STEELWALL, EL_INVISIBLE_STEELWALL }
1498 int steel_type = (BorderElement == EL_STEELWALL ? 0 : 1);
1499 int steel_position = (x == -1 && y == -1 ? 0 :
1500 x == lev_fieldx && y == -1 ? 1 :
1501 x == -1 && y == lev_fieldy ? 2 :
1502 x == lev_fieldx && y == lev_fieldy ? 3 :
1503 x == -1 || x == lev_fieldx ? 4 :
1504 y == -1 || y == lev_fieldy ? 5 : 6);
1506 return border[steel_position][steel_type];
1509 void DrawScreenElement(int x, int y, int element)
1511 DrawScreenElementExt(x, y, 0, 0, element, NO_CUTTING, NO_MASKING);
1512 DrawLevelFieldCrumbledSand(LEVELX(x), LEVELY(y));
1515 void DrawLevelElement(int x, int y, int element)
1517 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1518 DrawScreenElement(SCREENX(x), SCREENY(y), element);
1521 void DrawScreenField(int x, int y)
1523 int lx = LEVELX(x), ly = LEVELY(y);
1524 int element, content;
1526 if (!IN_LEV_FIELD(lx, ly))
1528 if (lx < -1 || lx > lev_fieldx || ly < -1 || ly > lev_fieldy)
1531 element = getBorderElement(lx, ly);
1533 DrawScreenElement(x, y, element);
1537 element = Feld[lx][ly];
1538 content = Store[lx][ly];
1540 if (IS_MOVING(lx, ly))
1542 int horiz_move = (MovDir[lx][ly] == MV_LEFT || MovDir[lx][ly] == MV_RIGHT);
1543 boolean cut_mode = NO_CUTTING;
1545 if (element == EL_QUICKSAND_EMPTYING ||
1546 element == EL_MAGIC_WALL_EMPTYING ||
1547 element == EL_BD_MAGIC_WALL_EMPTYING ||
1548 element == EL_AMOEBA_DROPPING)
1549 cut_mode = CUT_ABOVE;
1550 else if (element == EL_QUICKSAND_FILLING ||
1551 element == EL_MAGIC_WALL_FILLING ||
1552 element == EL_BD_MAGIC_WALL_FILLING)
1553 cut_mode = CUT_BELOW;
1555 if (cut_mode == CUT_ABOVE)
1556 DrawScreenElementShifted(x, y, 0, 0, element, NO_CUTTING);
1558 DrawScreenElement(x, y, EL_EMPTY);
1561 DrawScreenElementShifted(x, y, MovPos[lx][ly], 0, element, NO_CUTTING);
1562 else if (cut_mode == NO_CUTTING)
1563 DrawScreenElementShifted(x, y, 0, MovPos[lx][ly], element, cut_mode);
1565 DrawScreenElementShifted(x, y, 0, MovPos[lx][ly], content, cut_mode);
1567 if (content == EL_ACID)
1569 int dir = MovDir[lx][ly];
1570 int newlx = lx + (dir == MV_LEFT ? -1 : dir == MV_RIGHT ? +1 : 0);
1571 int newly = ly + (dir == MV_UP ? -1 : dir == MV_DOWN ? +1 : 0);
1573 DrawLevelElementThruMask(newlx, newly, EL_ACID);
1576 else if (IS_BLOCKED(lx, ly))
1581 boolean cut_mode = NO_CUTTING;
1582 int element_old, content_old;
1584 Blocked2Moving(lx, ly, &oldx, &oldy);
1587 horiz_move = (MovDir[oldx][oldy] == MV_LEFT ||
1588 MovDir[oldx][oldy] == MV_RIGHT);
1590 element_old = Feld[oldx][oldy];
1591 content_old = Store[oldx][oldy];
1593 if (element_old == EL_QUICKSAND_EMPTYING ||
1594 element_old == EL_MAGIC_WALL_EMPTYING ||
1595 element_old == EL_BD_MAGIC_WALL_EMPTYING ||
1596 element_old == EL_AMOEBA_DROPPING)
1597 cut_mode = CUT_ABOVE;
1599 DrawScreenElement(x, y, EL_EMPTY);
1602 DrawScreenElementShifted(sx, sy, MovPos[oldx][oldy], 0, element_old,
1604 else if (cut_mode == NO_CUTTING)
1605 DrawScreenElementShifted(sx, sy, 0, MovPos[oldx][oldy], element_old,
1608 DrawScreenElementShifted(sx, sy, 0, MovPos[oldx][oldy], content_old,
1611 else if (IS_DRAWABLE(element))
1612 DrawScreenElement(x, y, element);
1614 DrawScreenElement(x, y, EL_EMPTY);
1617 void DrawLevelField(int x, int y)
1619 if (IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1620 DrawScreenField(SCREENX(x), SCREENY(y));
1621 else if (IS_MOVING(x, y))
1625 Moving2Blocked(x, y, &newx, &newy);
1626 if (IN_SCR_FIELD(SCREENX(newx), SCREENY(newy)))
1627 DrawScreenField(SCREENX(newx), SCREENY(newy));
1629 else if (IS_BLOCKED(x, y))
1633 Blocked2Moving(x, y, &oldx, &oldy);
1634 if (IN_SCR_FIELD(SCREENX(oldx), SCREENY(oldy)))
1635 DrawScreenField(SCREENX(oldx), SCREENY(oldy));
1639 void DrawMiniElement(int x, int y, int element)
1643 graphic = el2edimg(element);
1644 DrawMiniGraphic(x, y, graphic);
1647 void DrawMiniElementOrWall(int sx, int sy, int scroll_x, int scroll_y)
1649 int x = sx + scroll_x, y = sy + scroll_y;
1651 if (x < -1 || x > lev_fieldx || y < -1 || y > lev_fieldy)
1652 DrawMiniElement(sx, sy, EL_EMPTY);
1653 else if (x > -1 && x < lev_fieldx && y > -1 && y < lev_fieldy)
1654 DrawMiniElement(sx, sy, Feld[x][y]);
1656 DrawMiniGraphic(sx, sy, el2edimg(getBorderElement(x, y)));
1659 void DrawEnvelopeBackground(int envelope_nr, int startx, int starty,
1660 int x, int y, int xsize, int ysize, int font_nr)
1662 int font_width = getFontWidth(font_nr);
1663 int font_height = getFontHeight(font_nr);
1664 int graphic = IMG_BACKGROUND_ENVELOPE_1 + envelope_nr;
1667 int dst_x = SX + startx + x * font_width;
1668 int dst_y = SY + starty + y * font_height;
1669 int width = graphic_info[graphic].width;
1670 int height = graphic_info[graphic].height;
1671 int inner_width = MAX(width - 2 * font_width, font_width);
1672 int inner_height = MAX(height - 2 * font_height, font_height);
1673 int inner_sx = (width >= 3 * font_width ? font_width : 0);
1674 int inner_sy = (height >= 3 * font_height ? font_height : 0);
1675 boolean draw_masked = graphic_info[graphic].draw_masked;
1677 getGraphicSource(graphic, 0, &src_bitmap, &src_x, &src_y);
1679 if (src_bitmap == NULL || width < font_width || height < font_height)
1681 ClearRectangle(drawto, dst_x, dst_y, font_width, font_height);
1685 src_x += (x == 0 ? 0 : x == xsize - 1 ? width - font_width :
1686 inner_sx + (x - 1) * font_width % inner_width);
1687 src_y += (y == 0 ? 0 : y == ysize - 1 ? height - font_height :
1688 inner_sy + (y - 1) * font_height % inner_height);
1692 SetClipOrigin(src_bitmap, src_bitmap->stored_clip_gc,
1693 dst_x - src_x, dst_y - src_y);
1694 BlitBitmapMasked(src_bitmap, drawto, src_x, src_y, font_width, font_height,
1698 BlitBitmap(src_bitmap, drawto, src_x, src_y, font_width, font_height,
1702 void AnimateEnvelope(int envelope_nr, int anim_mode, int action)
1704 int graphic = IMG_BACKGROUND_ENVELOPE_1 + envelope_nr;
1706 Bitmap *src_bitmap = graphic_info[graphic].bitmap;
1707 int mask_mode = (src_bitmap != NULL ? BLIT_MASKED : BLIT_ON_BACKGROUND);
1709 boolean draw_masked = graphic_info[graphic].draw_masked;
1710 int mask_mode = (draw_masked ? BLIT_MASKED : BLIT_ON_BACKGROUND);
1712 boolean ffwd_delay = (tape.playing && tape.fast_forward);
1713 boolean no_delay = (tape.warp_forward);
1714 unsigned long anim_delay = 0;
1715 int frame_delay_value = (ffwd_delay ? FfwdFrameDelay : GameFrameDelay);
1716 int anim_delay_value = (no_delay ? 0 : frame_delay_value);
1717 int font_nr = FONT_ENVELOPE_1 + envelope_nr;
1718 int font_width = getFontWidth(font_nr);
1719 int font_height = getFontHeight(font_nr);
1720 int max_xsize = level.envelope_xsize[envelope_nr];
1721 int max_ysize = level.envelope_ysize[envelope_nr];
1722 int xstart = (anim_mode & ANIM_VERTICAL ? max_xsize : 0);
1723 int ystart = (anim_mode & ANIM_HORIZONTAL ? max_ysize : 0);
1724 int xend = max_xsize;
1725 int yend = (anim_mode != ANIM_DEFAULT ? max_ysize : 0);
1726 int xstep = (xstart < xend ? 1 : 0);
1727 int ystep = (ystart < yend || xstep == 0 ? 1 : 0);
1730 for (x = xstart, y = ystart; x <= xend && y <= yend; x += xstep, y += ystep)
1732 int xsize = (action == ACTION_CLOSING ? xend - (x - xstart) : x) + 2;
1733 int ysize = (action == ACTION_CLOSING ? yend - (y - ystart) : y) + 2;
1734 int sx = (SXSIZE - xsize * font_width) / 2;
1735 int sy = (SYSIZE - ysize * font_height) / 2;
1738 SetDrawtoField(DRAW_BUFFERED);
1740 BlitBitmap(fieldbuffer, backbuffer, FX, FY, SXSIZE, SYSIZE, SX, SY);
1742 SetDrawtoField(DRAW_BACKBUFFER);
1744 for (yy = 0; yy < ysize; yy++) for (xx = 0; xx < xsize; xx++)
1745 DrawEnvelopeBackground(envelope_nr, sx,sy, xx,yy, xsize, ysize, font_nr);
1747 DrawTextToTextArea(SX + sx + font_width, SY + sy + font_height,
1748 level.envelope_text[envelope_nr], font_nr, max_xsize,
1749 xsize - 2, ysize - 2, mask_mode);
1751 redraw_mask |= REDRAW_FIELD | REDRAW_FROM_BACKBUFFER;
1754 WaitUntilDelayReached(&anim_delay, anim_delay_value / 2);
1758 void ShowEnvelope(int envelope_nr)
1760 int element = EL_ENVELOPE_1 + envelope_nr;
1761 int graphic = IMG_BACKGROUND_ENVELOPE_1 + envelope_nr;
1762 int sound_opening = element_info[element].sound[ACTION_OPENING];
1763 int sound_closing = element_info[element].sound[ACTION_CLOSING];
1764 boolean ffwd_delay = (tape.playing && tape.fast_forward);
1765 boolean no_delay = (tape.warp_forward);
1766 int normal_delay_value = ONE_SECOND_DELAY / (ffwd_delay ? 2 : 1);
1767 int wait_delay_value = (no_delay ? 0 : normal_delay_value);
1768 int anim_mode = graphic_info[graphic].anim_mode;
1769 int main_anim_mode = (anim_mode == ANIM_NONE ? ANIM_VERTICAL|ANIM_HORIZONTAL:
1770 anim_mode == ANIM_DEFAULT ? ANIM_VERTICAL : anim_mode);
1772 game.envelope_active = TRUE; /* needed for RedrawPlayfield() events */
1774 PlaySoundStereo(sound_opening, SOUND_MIDDLE);
1776 if (anim_mode == ANIM_DEFAULT)
1777 AnimateEnvelope(envelope_nr, ANIM_DEFAULT, ACTION_OPENING);
1779 AnimateEnvelope(envelope_nr, main_anim_mode, ACTION_OPENING);
1782 Delay(wait_delay_value);
1784 WaitForEventToContinue();
1786 PlaySoundStereo(sound_closing, SOUND_MIDDLE);
1788 if (anim_mode != ANIM_NONE)
1789 AnimateEnvelope(envelope_nr, main_anim_mode, ACTION_CLOSING);
1791 if (anim_mode == ANIM_DEFAULT)
1792 AnimateEnvelope(envelope_nr, ANIM_DEFAULT, ACTION_CLOSING);
1794 game.envelope_active = FALSE;
1796 SetDrawtoField(DRAW_BUFFERED);
1798 redraw_mask |= REDRAW_FIELD;
1802 void getMicroGraphicSource(int graphic, Bitmap **bitmap, int *x, int *y)
1804 Bitmap *src_bitmap = graphic_info[graphic].bitmap;
1805 int mini_startx = src_bitmap->width * 3 / 4;
1806 int mini_starty = src_bitmap->height * 2 / 3;
1807 int src_x = mini_startx + graphic_info[graphic].src_x / 8;
1808 int src_y = mini_starty + graphic_info[graphic].src_y / 8;
1810 *bitmap = src_bitmap;
1815 void DrawMicroElement(int xpos, int ypos, int element)
1819 int graphic = el2preimg(element);
1821 getMicroGraphicSource(graphic, &src_bitmap, &src_x, &src_y);
1822 BlitBitmap(src_bitmap, drawto, src_x, src_y, MICRO_TILEX, MICRO_TILEY,
1830 SetDrawBackgroundMask(REDRAW_NONE);
1833 for (x = BX1; x <= BX2; x++)
1834 for (y = BY1; y <= BY2; y++)
1835 DrawScreenField(x, y);
1837 redraw_mask |= REDRAW_FIELD;
1840 void DrawMiniLevel(int size_x, int size_y, int scroll_x, int scroll_y)
1844 for (x = 0; x < size_x; x++)
1845 for (y = 0; y < size_y; y++)
1846 DrawMiniElementOrWall(x, y, scroll_x, scroll_y);
1848 redraw_mask |= REDRAW_FIELD;
1851 static void DrawMicroLevelExt(int xpos, int ypos, int from_x, int from_y)
1855 DrawBackground(xpos, ypos, MICROLEV_XSIZE, MICROLEV_YSIZE);
1857 if (lev_fieldx < STD_LEV_FIELDX)
1858 xpos += (STD_LEV_FIELDX - lev_fieldx) / 2 * MICRO_TILEX;
1859 if (lev_fieldy < STD_LEV_FIELDY)
1860 ypos += (STD_LEV_FIELDY - lev_fieldy) / 2 * MICRO_TILEY;
1862 xpos += MICRO_TILEX;
1863 ypos += MICRO_TILEY;
1865 for (x = -1; x <= STD_LEV_FIELDX; x++)
1867 for (y = -1; y <= STD_LEV_FIELDY; y++)
1869 int lx = from_x + x, ly = from_y + y;
1871 if (lx >= 0 && lx < lev_fieldx && ly >= 0 && ly < lev_fieldy)
1872 DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
1873 level.field[lx][ly]);
1874 else if (lx >= -1 && lx < lev_fieldx+1 && ly >= -1 && ly < lev_fieldy+1
1875 && BorderElement != EL_EMPTY)
1876 DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
1877 getBorderElement(lx, ly));
1881 redraw_mask |= REDRAW_MICROLEVEL;
1884 #define MICROLABEL_EMPTY 0
1885 #define MICROLABEL_LEVEL_NAME 1
1886 #define MICROLABEL_CREATED_BY 2
1887 #define MICROLABEL_LEVEL_AUTHOR 3
1888 #define MICROLABEL_IMPORTED_FROM 4
1889 #define MICROLABEL_LEVEL_IMPORT_INFO 5
1891 static void DrawMicroLevelLabelExt(int mode)
1893 char label_text[MAX_OUTPUT_LINESIZE + 1];
1894 int max_len_label_text;
1895 int font_nr = FONT_TEXT_2;
1897 if (mode == MICROLABEL_CREATED_BY || mode == MICROLABEL_IMPORTED_FROM)
1898 font_nr = FONT_TEXT_3;
1900 max_len_label_text = SXSIZE / getFontWidth(font_nr);
1902 DrawBackground(SX, MICROLABEL_YPOS, SXSIZE, getFontHeight(font_nr));
1904 strncpy(label_text, (mode == MICROLABEL_LEVEL_NAME ? level.name :
1905 mode == MICROLABEL_CREATED_BY ? "created by" :
1906 mode == MICROLABEL_LEVEL_AUTHOR ? level.author :
1907 mode == MICROLABEL_IMPORTED_FROM ? "imported from" :
1908 mode == MICROLABEL_LEVEL_IMPORT_INFO ?
1909 leveldir_current->imported_from : ""),
1910 max_len_label_text);
1911 label_text[max_len_label_text] = '\0';
1913 if (strlen(label_text) > 0)
1915 int lxpos = SX + (SXSIZE - getTextWidth(label_text, font_nr)) / 2;
1916 int lypos = MICROLABEL_YPOS;
1918 DrawText(lxpos, lypos, label_text, font_nr);
1921 redraw_mask |= REDRAW_MICROLEVEL;
1924 void DrawMicroLevel(int xpos, int ypos, boolean restart)
1926 static unsigned long scroll_delay = 0;
1927 static unsigned long label_delay = 0;
1928 static int from_x, from_y, scroll_direction;
1929 static int label_state, label_counter;
1930 int last_game_status = game_status; /* save current game status */
1932 /* force PREVIEW font on preview level */
1933 game_status = GAME_MODE_PSEUDO_PREVIEW;
1937 from_x = from_y = 0;
1938 scroll_direction = MV_RIGHT;
1942 DrawMicroLevelExt(xpos, ypos, from_x, from_y);
1943 DrawMicroLevelLabelExt(label_state);
1945 /* initialize delay counters */
1946 DelayReached(&scroll_delay, 0);
1947 DelayReached(&label_delay, 0);
1949 if (leveldir_current->name)
1951 int text_width = getTextWidth(leveldir_current->name, FONT_TEXT_1);
1952 int lxpos = SX + (SXSIZE - text_width) / 2;
1953 int lypos = SY + 352;
1955 DrawText(lxpos, lypos, leveldir_current->name, FONT_TEXT_1);
1958 game_status = last_game_status; /* restore current game status */
1963 /* scroll micro level, if needed */
1964 if ((lev_fieldx > STD_LEV_FIELDX || lev_fieldy > STD_LEV_FIELDY) &&
1965 DelayReached(&scroll_delay, MICROLEVEL_SCROLL_DELAY))
1967 switch (scroll_direction)
1973 scroll_direction = MV_UP;
1977 if (from_x < lev_fieldx - STD_LEV_FIELDX)
1980 scroll_direction = MV_DOWN;
1987 scroll_direction = MV_RIGHT;
1991 if (from_y < lev_fieldy - STD_LEV_FIELDY)
1994 scroll_direction = MV_LEFT;
2001 DrawMicroLevelExt(xpos, ypos, from_x, from_y);
2004 /* redraw micro level label, if needed */
2005 if (strcmp(level.name, NAMELESS_LEVEL_NAME) != 0 &&
2006 strcmp(level.author, ANONYMOUS_NAME) != 0 &&
2007 strcmp(level.author, leveldir_current->name) != 0 &&
2008 DelayReached(&label_delay, MICROLEVEL_LABEL_DELAY))
2010 int max_label_counter = 23;
2012 if (leveldir_current->imported_from != NULL)
2013 max_label_counter += 14;
2015 label_counter = (label_counter + 1) % max_label_counter;
2016 label_state = (label_counter >= 0 && label_counter <= 7 ?
2017 MICROLABEL_LEVEL_NAME :
2018 label_counter >= 9 && label_counter <= 12 ?
2019 MICROLABEL_CREATED_BY :
2020 label_counter >= 14 && label_counter <= 21 ?
2021 MICROLABEL_LEVEL_AUTHOR :
2022 label_counter >= 23 && label_counter <= 26 ?
2023 MICROLABEL_IMPORTED_FROM :
2024 label_counter >= 28 && label_counter <= 35 ?
2025 MICROLABEL_LEVEL_IMPORT_INFO : MICROLABEL_EMPTY);
2026 DrawMicroLevelLabelExt(label_state);
2029 game_status = last_game_status; /* restore current game status */
2032 void WaitForEventToContinue()
2034 boolean still_wait = TRUE;
2036 /* simulate releasing mouse button over last gadget, if still pressed */
2038 HandleGadgets(-1, -1, 0);
2040 button_status = MB_RELEASED;
2052 case EVENT_BUTTONPRESS:
2053 case EVENT_KEYPRESS:
2057 case EVENT_KEYRELEASE:
2058 ClearPlayerAction();
2062 HandleOtherEvents(&event);
2066 else if (AnyJoystickButton() == JOY_BUTTON_NEW_PRESSED)
2073 /* don't eat all CPU time */
2078 #define MAX_REQUEST_LINES 13
2079 #define MAX_REQUEST_LINE_FONT1_LEN 7
2080 #define MAX_REQUEST_LINE_FONT2_LEN 10
2082 boolean Request(char *text, unsigned int req_state)
2084 int mx, my, ty, result = -1;
2085 unsigned int old_door_state;
2086 int last_game_status = game_status; /* save current game status */
2087 int max_request_line_len = MAX_REQUEST_LINE_FONT1_LEN;
2088 int font_nr = FONT_TEXT_2;
2089 int max_word_len = 0;
2092 for (text_ptr = text; *text_ptr; text_ptr++)
2094 max_word_len = (*text_ptr != ' ' ? max_word_len + 1 : 0);
2096 if (max_word_len > MAX_REQUEST_LINE_FONT1_LEN)
2098 max_request_line_len = MAX_REQUEST_LINE_FONT2_LEN;
2099 font_nr = FONT_LEVEL_NUMBER;
2106 /* disable deactivated drawing when quick-loading level tape recording */
2107 if (tape.playing && tape.deactivate_display)
2108 TapeDeactivateDisplayOff(TRUE);
2112 SetMouseCursor(CURSOR_DEFAULT);
2115 #if defined(NETWORK_AVALIABLE)
2116 /* pause network game while waiting for request to answer */
2117 if (options.network &&
2118 game_status == GAME_MODE_PLAYING &&
2119 req_state & REQUEST_WAIT_FOR_INPUT)
2120 SendToServer_PausePlaying();
2123 old_door_state = GetDoorState();
2125 /* simulate releasing mouse button over last gadget, if still pressed */
2127 HandleGadgets(-1, -1, 0);
2131 if (old_door_state & DOOR_OPEN_1)
2133 CloseDoor(DOOR_CLOSE_1);
2135 /* save old door content */
2136 BlitBitmap(bitmap_db_door, bitmap_db_door,
2137 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE,
2138 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1);
2141 SetDrawBackgroundMask(REDRAW_FIELD | REDRAW_DOOR_1);
2143 /* clear door drawing field */
2144 DrawBackground(DX, DY, DXSIZE, DYSIZE);
2146 /* force DOOR font on preview level */
2147 game_status = GAME_MODE_PSEUDO_DOOR;
2149 /* write text for request */
2150 for (ty = 0; ty < MAX_REQUEST_LINES; ty++)
2152 char text_line[max_request_line_len + 1];
2158 for (tl = 0, tx = 0; tx < max_request_line_len; tl++, tx++)
2161 if (!tc || tc == ' ')
2172 strncpy(text_line, text, tl);
2175 DrawText(DX + (DXSIZE - tl * getFontWidth(font_nr)) / 2,
2176 DY + 8 + ty * (getFontHeight(font_nr) + 2),
2177 text_line, font_nr);
2179 text += tl + (tc == ' ' ? 1 : 0);
2182 game_status = last_game_status; /* restore current game status */
2184 if (req_state & REQ_ASK)
2186 MapGadget(tool_gadget[TOOL_CTRL_ID_YES]);
2187 MapGadget(tool_gadget[TOOL_CTRL_ID_NO]);
2189 else if (req_state & REQ_CONFIRM)
2191 MapGadget(tool_gadget[TOOL_CTRL_ID_CONFIRM]);
2193 else if (req_state & REQ_PLAYER)
2195 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_1]);
2196 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_2]);
2197 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_3]);
2198 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_4]);
2201 /* copy request gadgets to door backbuffer */
2202 BlitBitmap(drawto, bitmap_db_door,
2203 DX, DY, DXSIZE, DYSIZE,
2204 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
2206 OpenDoor(DOOR_OPEN_1);
2212 if (!(req_state & REQUEST_WAIT_FOR_INPUT))
2214 SetDrawBackgroundMask(REDRAW_FIELD);
2219 if (game_status != GAME_MODE_MAIN)
2222 button_status = MB_RELEASED;
2224 request_gadget_id = -1;
2226 SetDrawBackgroundMask(REDRAW_FIELD | REDRAW_DOOR_1);
2229 SetMouseCursor(CURSOR_DEFAULT);
2242 case EVENT_BUTTONPRESS:
2243 case EVENT_BUTTONRELEASE:
2244 case EVENT_MOTIONNOTIFY:
2246 if (event.type == EVENT_MOTIONNOTIFY)
2248 if (!PointerInWindow(window))
2249 continue; /* window and pointer are on different screens */
2254 motion_status = TRUE;
2255 mx = ((MotionEvent *) &event)->x;
2256 my = ((MotionEvent *) &event)->y;
2260 motion_status = FALSE;
2261 mx = ((ButtonEvent *) &event)->x;
2262 my = ((ButtonEvent *) &event)->y;
2263 if (event.type == EVENT_BUTTONPRESS)
2264 button_status = ((ButtonEvent *) &event)->button;
2266 button_status = MB_RELEASED;
2269 /* this sets 'request_gadget_id' */
2270 HandleGadgets(mx, my, button_status);
2272 switch(request_gadget_id)
2274 case TOOL_CTRL_ID_YES:
2277 case TOOL_CTRL_ID_NO:
2280 case TOOL_CTRL_ID_CONFIRM:
2281 result = TRUE | FALSE;
2284 case TOOL_CTRL_ID_PLAYER_1:
2287 case TOOL_CTRL_ID_PLAYER_2:
2290 case TOOL_CTRL_ID_PLAYER_3:
2293 case TOOL_CTRL_ID_PLAYER_4:
2304 case EVENT_KEYPRESS:
2305 switch(GetEventKey((KeyEvent *)&event, TRUE))
2318 if (req_state & REQ_PLAYER)
2322 case EVENT_KEYRELEASE:
2323 ClearPlayerAction();
2327 HandleOtherEvents(&event);
2331 else if (AnyJoystickButton() == JOY_BUTTON_NEW_PRESSED)
2333 int joy = AnyJoystick();
2335 if (joy & JOY_BUTTON_1)
2337 else if (joy & JOY_BUTTON_2)
2343 /* don't eat all CPU time */
2347 if (game_status != GAME_MODE_MAIN)
2352 if (!(req_state & REQ_STAY_OPEN))
2354 CloseDoor(DOOR_CLOSE_1);
2356 if (((old_door_state & DOOR_OPEN_1) && !(req_state & REQ_STAY_CLOSED)) ||
2357 (req_state & REQ_REOPEN))
2358 OpenDoor(DOOR_OPEN_1 | DOOR_COPY_BACK);
2363 SetDrawBackgroundMask(REDRAW_FIELD);
2365 #if defined(NETWORK_AVALIABLE)
2366 /* continue network game after request */
2367 if (options.network &&
2368 game_status == GAME_MODE_PLAYING &&
2369 req_state & REQUEST_WAIT_FOR_INPUT)
2370 SendToServer_ContinuePlaying();
2374 /* restore deactivated drawing when quick-loading level tape recording */
2375 if (tape.playing && tape.deactivate_display)
2376 TapeDeactivateDisplayOn();
2382 unsigned int OpenDoor(unsigned int door_state)
2384 if (door_state & DOOR_COPY_BACK)
2386 if (door_state & DOOR_OPEN_1)
2387 BlitBitmap(bitmap_db_door, bitmap_db_door,
2388 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE,
2389 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
2391 if (door_state & DOOR_OPEN_2)
2392 BlitBitmap(bitmap_db_door, bitmap_db_door,
2393 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY2, VXSIZE, VYSIZE,
2394 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2);
2396 door_state &= ~DOOR_COPY_BACK;
2399 return MoveDoor(door_state);
2402 unsigned int CloseDoor(unsigned int door_state)
2404 unsigned int old_door_state = GetDoorState();
2406 if (!(door_state & DOOR_NO_COPY_BACK))
2408 if (old_door_state & DOOR_OPEN_1)
2409 BlitBitmap(backbuffer, bitmap_db_door,
2410 DX, DY, DXSIZE, DYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
2412 if (old_door_state & DOOR_OPEN_2)
2413 BlitBitmap(backbuffer, bitmap_db_door,
2414 VX, VY, VXSIZE, VYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2);
2416 door_state &= ~DOOR_NO_COPY_BACK;
2419 return MoveDoor(door_state);
2422 unsigned int GetDoorState()
2424 return MoveDoor(DOOR_GET_STATE);
2427 unsigned int SetDoorState(unsigned int door_state)
2429 return MoveDoor(door_state | DOOR_SET_STATE);
2432 unsigned int MoveDoor(unsigned int door_state)
2434 static int door1 = DOOR_OPEN_1;
2435 static int door2 = DOOR_CLOSE_2;
2436 unsigned long door_delay = 0;
2437 unsigned long door_delay_value;
2440 if (door_state == DOOR_GET_STATE)
2441 return(door1 | door2);
2443 if (door_state & DOOR_SET_STATE)
2445 if (door_state & DOOR_ACTION_1)
2446 door1 = door_state & DOOR_ACTION_1;
2447 if (door_state & DOOR_ACTION_2)
2448 door2 = door_state & DOOR_ACTION_2;
2450 return(door1 | door2);
2453 if (door1 == DOOR_OPEN_1 && door_state & DOOR_OPEN_1)
2454 door_state &= ~DOOR_OPEN_1;
2455 else if (door1 == DOOR_CLOSE_1 && door_state & DOOR_CLOSE_1)
2456 door_state &= ~DOOR_CLOSE_1;
2457 if (door2 == DOOR_OPEN_2 && door_state & DOOR_OPEN_2)
2458 door_state &= ~DOOR_OPEN_2;
2459 else if (door2 == DOOR_CLOSE_2 && door_state & DOOR_CLOSE_2)
2460 door_state &= ~DOOR_CLOSE_2;
2462 door_delay_value = (door_state & DOOR_ACTION_1 ? door_1.step_delay :
2465 if (setup.quick_doors)
2467 stepsize = 20; /* must be choosen to always draw last frame */
2468 door_delay_value = 0;
2471 StopSound(SND_DOOR_OPENING);
2472 StopSound(SND_DOOR_CLOSING);
2476 if (global.autoplay_leveldir)
2478 door_state |= DOOR_NO_DELAY;
2479 door_state &= ~DOOR_CLOSE_ALL;
2482 if (door_state & DOOR_ACTION)
2484 boolean door_1_done = !(door_state & DOOR_ACTION_1);
2485 boolean door_2_done = !(door_state & DOOR_ACTION_2);
2486 int start = ((door_state & DOOR_NO_DELAY) ? DXSIZE : 0);
2487 int end = (door_state & DOOR_ACTION_1 &&
2488 door_1.anim_mode == ANIM_VERTICAL ? DYSIZE : DXSIZE);
2491 if (!(door_state & DOOR_NO_DELAY) && !setup.quick_doors)
2493 /* opening door sound has priority over simultaneously closing door */
2494 if (door_state & (DOOR_OPEN_1 | DOOR_OPEN_2))
2495 PlaySoundStereo(SND_DOOR_OPENING, SOUND_MIDDLE);
2496 else if (door_state & (DOOR_CLOSE_1 | DOOR_CLOSE_2))
2497 PlaySoundStereo(SND_DOOR_CLOSING, SOUND_MIDDLE);
2500 for (x = start; x <= end && !(door_1_done && door_2_done); x += stepsize)
2502 Bitmap *bitmap = graphic_info[IMG_GLOBAL_DOOR].bitmap;
2503 GC gc = bitmap->stored_clip_gc;
2505 if (door_state & DOOR_ACTION_1)
2507 int a = MIN(x * door_1.step_offset, end);
2508 int i = (door_state & DOOR_OPEN_1 ? end - a : a);
2512 BlitBitmap(bitmap_db_door, drawto,
2513 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1 + i / 2,
2514 DXSIZE, DYSIZE - i / 2, DX, DY);
2516 ClearRectangle(drawto, DX, DY + DYSIZE - i / 2, DXSIZE, i / 2);
2519 if (door_1.anim_mode == ANIM_HORIZONTAL && x <= DXSIZE)
2521 int src1_x = DXSIZE, src1_y = DOOR_GFX_PAGEY1;
2522 int dst1_x = DX + DXSIZE - i, dst1_y = DY;
2523 int src2_x = DXSIZE - i, src2_y = DOOR_GFX_PAGEY1;
2524 int dst2_x = DX, dst2_y = DY;
2525 int width = i, height = DYSIZE;
2527 SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y);
2528 BlitBitmapMasked(bitmap, drawto, src1_x, src1_y, width, height,
2531 SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y);
2532 BlitBitmapMasked(bitmap, drawto, src2_x, src2_y, width, height,
2535 else if (door_1.anim_mode == ANIM_VERTICAL && x <= DYSIZE)
2537 int src1_x = DXSIZE, src1_y = DOOR_GFX_PAGEY1;
2538 int dst1_x = DX, dst1_y = DY + DYSIZE - i;
2539 int src2_x = 0, src2_y = DOOR_GFX_PAGEY1 + DYSIZE - i;
2540 int dst2_x = DX, dst2_y = DY;
2541 int width = DXSIZE, height = i;
2543 SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y);
2544 BlitBitmapMasked(bitmap, drawto, src1_x, src1_y, width, height,
2547 SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y);
2548 BlitBitmapMasked(bitmap, drawto, src2_x, src2_y, width, height,
2551 else if (x <= DXSIZE) /* ANIM_DEFAULT */
2553 int j = (door_1.anim_mode == ANIM_DEFAULT ? (DXSIZE - i) / 3 : 0);
2555 SetClipOrigin(bitmap, gc, DX - i, (DY + j) - DOOR_GFX_PAGEY1);
2556 BlitBitmapMasked(bitmap, drawto,
2557 DXSIZE, DOOR_GFX_PAGEY1, i, 77,
2558 DX + DXSIZE - i, DY + j);
2559 BlitBitmapMasked(bitmap, drawto,
2560 DXSIZE, DOOR_GFX_PAGEY1 + 140, i, 63,
2561 DX + DXSIZE - i, DY + 140 + j);
2562 SetClipOrigin(bitmap, gc, DX - DXSIZE + i,
2563 DY - (DOOR_GFX_PAGEY1 + j));
2564 BlitBitmapMasked(bitmap, drawto,
2565 DXSIZE - i, DOOR_GFX_PAGEY1 + j, i, 77 - j,
2567 BlitBitmapMasked(bitmap, drawto,
2568 DXSIZE-i, DOOR_GFX_PAGEY1 + 140, i, 63,
2571 BlitBitmapMasked(bitmap, drawto,
2572 DXSIZE - i, DOOR_GFX_PAGEY1 + 77, i, 63,
2574 BlitBitmapMasked(bitmap, drawto,
2575 DXSIZE - i, DOOR_GFX_PAGEY1 + 203, i, 77,
2577 SetClipOrigin(bitmap, gc, DX - i, (DY + j) - DOOR_GFX_PAGEY1);
2578 BlitBitmapMasked(bitmap, drawto,
2579 DXSIZE, DOOR_GFX_PAGEY1 + 77, i, 63,
2580 DX + DXSIZE - i, DY + 77 + j);
2581 BlitBitmapMasked(bitmap, drawto,
2582 DXSIZE, DOOR_GFX_PAGEY1 + 203, i, 77 - j,
2583 DX + DXSIZE - i, DY + 203 + j);
2586 redraw_mask |= REDRAW_DOOR_1;
2587 door_1_done = (a == end);
2590 if (door_state & DOOR_ACTION_2)
2592 int a = MIN(x * door_2.step_offset, VXSIZE);
2593 int i = (door_state & DOOR_OPEN_2 ? VXSIZE - a : a);
2597 BlitBitmap(bitmap_db_door, drawto,
2598 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2 + i / 2,
2599 VXSIZE, VYSIZE - i / 2, VX, VY);
2601 ClearRectangle(drawto, VX, VY + VYSIZE - i / 2, VXSIZE, i / 2);
2604 if (door_2.anim_mode == ANIM_HORIZONTAL && x <= VXSIZE)
2606 int src1_x = VXSIZE, src1_y = DOOR_GFX_PAGEY2;
2607 int dst1_x = VX + VXSIZE - i, dst1_y = VY;
2608 int src2_x = VXSIZE - i, src2_y = DOOR_GFX_PAGEY2;
2609 int dst2_x = VX, dst2_y = VY;
2610 int width = i, height = VYSIZE;
2612 SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y);
2613 BlitBitmapMasked(bitmap, drawto, src1_x, src1_y, width, height,
2616 SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y);
2617 BlitBitmapMasked(bitmap, drawto, src2_x, src2_y, width, height,
2620 else if (door_2.anim_mode == ANIM_VERTICAL && x <= VYSIZE)
2622 int src1_x = VXSIZE, src1_y = DOOR_GFX_PAGEY2;
2623 int dst1_x = VX, dst1_y = VY + VYSIZE - i;
2624 int src2_x = 0, src2_y = DOOR_GFX_PAGEY2 + VYSIZE - i;
2625 int dst2_x = VX, dst2_y = VY;
2626 int width = VXSIZE, height = i;
2628 SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y);
2629 BlitBitmapMasked(bitmap, drawto, src1_x, src1_y, width, height,
2632 SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y);
2633 BlitBitmapMasked(bitmap, drawto, src2_x, src2_y, width, height,
2636 else if (x <= VXSIZE) /* ANIM_DEFAULT */
2638 int j = (door_2.anim_mode == ANIM_DEFAULT ? (VXSIZE - i) / 3 : 0);
2640 SetClipOrigin(bitmap, gc, VX - i, (VY + j) - DOOR_GFX_PAGEY2);
2641 BlitBitmapMasked(bitmap, drawto,
2642 VXSIZE, DOOR_GFX_PAGEY2, i, VYSIZE / 2,
2643 VX + VXSIZE - i, VY + j);
2644 SetClipOrigin(bitmap, gc,
2645 VX - VXSIZE + i, VY - (DOOR_GFX_PAGEY2 + j));
2646 BlitBitmapMasked(bitmap, drawto,
2647 VXSIZE - i, DOOR_GFX_PAGEY2 + j, i, VYSIZE / 2 - j,
2650 BlitBitmapMasked(bitmap, drawto,
2651 VXSIZE - i, DOOR_GFX_PAGEY2 + VYSIZE / 2,
2652 i, VYSIZE / 2, VX, VY + VYSIZE / 2 - j);
2653 SetClipOrigin(bitmap, gc, VX - i, (VY + j) - DOOR_GFX_PAGEY2);
2654 BlitBitmapMasked(bitmap, drawto,
2655 VXSIZE, DOOR_GFX_PAGEY2 + VYSIZE / 2,
2657 VX + VXSIZE - i, VY + VYSIZE / 2 + j);
2660 redraw_mask |= REDRAW_DOOR_2;
2661 door_2_done = (a == VXSIZE);
2666 if (game_status == GAME_MODE_MAIN)
2669 if (!(door_state & DOOR_NO_DELAY))
2670 WaitUntilDelayReached(&door_delay, door_delay_value);
2675 if (setup.quick_doors)
2677 StopSound(SND_DOOR_OPENING);
2678 StopSound(SND_DOOR_CLOSING);
2682 if (door_state & DOOR_ACTION_1)
2683 door1 = door_state & DOOR_ACTION_1;
2684 if (door_state & DOOR_ACTION_2)
2685 door2 = door_state & DOOR_ACTION_2;
2687 return (door1 | door2);
2690 void DrawSpecialEditorDoor()
2692 /* draw bigger toolbox window */
2693 BlitBitmap(graphic_info[IMG_GLOBAL_DOOR].bitmap, drawto,
2694 DOOR_GFX_PAGEX7, 0, EXSIZE + 8, 8,
2696 BlitBitmap(graphic_info[IMG_GLOBAL_BORDER].bitmap, drawto,
2697 EX - 4, VY - 4, EXSIZE + 8, EYSIZE - VYSIZE + 4,
2700 redraw_mask |= REDRAW_ALL;
2703 void UndrawSpecialEditorDoor()
2705 /* draw normal tape recorder window */
2706 BlitBitmap(graphic_info[IMG_GLOBAL_BORDER].bitmap, drawto,
2707 EX - 4, EY - 12, EXSIZE + 8, EYSIZE - VYSIZE + 12,
2710 redraw_mask |= REDRAW_ALL;
2714 /* ---------- new tool button stuff ---------------------------------------- */
2716 /* graphic position values for tool buttons */
2717 #define TOOL_BUTTON_YES_XPOS 2
2718 #define TOOL_BUTTON_YES_YPOS 250
2719 #define TOOL_BUTTON_YES_GFX_YPOS 0
2720 #define TOOL_BUTTON_YES_XSIZE 46
2721 #define TOOL_BUTTON_YES_YSIZE 28
2722 #define TOOL_BUTTON_NO_XPOS 52
2723 #define TOOL_BUTTON_NO_YPOS TOOL_BUTTON_YES_YPOS
2724 #define TOOL_BUTTON_NO_GFX_YPOS TOOL_BUTTON_YES_GFX_YPOS
2725 #define TOOL_BUTTON_NO_XSIZE TOOL_BUTTON_YES_XSIZE
2726 #define TOOL_BUTTON_NO_YSIZE TOOL_BUTTON_YES_YSIZE
2727 #define TOOL_BUTTON_CONFIRM_XPOS TOOL_BUTTON_YES_XPOS
2728 #define TOOL_BUTTON_CONFIRM_YPOS TOOL_BUTTON_YES_YPOS
2729 #define TOOL_BUTTON_CONFIRM_GFX_YPOS 30
2730 #define TOOL_BUTTON_CONFIRM_XSIZE 96
2731 #define TOOL_BUTTON_CONFIRM_YSIZE TOOL_BUTTON_YES_YSIZE
2732 #define TOOL_BUTTON_PLAYER_XSIZE 30
2733 #define TOOL_BUTTON_PLAYER_YSIZE 30
2734 #define TOOL_BUTTON_PLAYER_GFX_XPOS 5
2735 #define TOOL_BUTTON_PLAYER_GFX_YPOS 185
2736 #define TOOL_BUTTON_PLAYER_XPOS (5 + TOOL_BUTTON_PLAYER_XSIZE / 2)
2737 #define TOOL_BUTTON_PLAYER_YPOS (215 - TOOL_BUTTON_PLAYER_YSIZE / 2)
2738 #define TOOL_BUTTON_PLAYER1_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2739 + 0 * TOOL_BUTTON_PLAYER_XSIZE)
2740 #define TOOL_BUTTON_PLAYER2_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2741 + 1 * TOOL_BUTTON_PLAYER_XSIZE)
2742 #define TOOL_BUTTON_PLAYER3_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2743 + 0 * TOOL_BUTTON_PLAYER_XSIZE)
2744 #define TOOL_BUTTON_PLAYER4_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2745 + 1 * TOOL_BUTTON_PLAYER_XSIZE)
2746 #define TOOL_BUTTON_PLAYER1_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2747 + 0 * TOOL_BUTTON_PLAYER_YSIZE)
2748 #define TOOL_BUTTON_PLAYER2_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2749 + 0 * TOOL_BUTTON_PLAYER_YSIZE)
2750 #define TOOL_BUTTON_PLAYER3_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2751 + 1 * TOOL_BUTTON_PLAYER_YSIZE)
2752 #define TOOL_BUTTON_PLAYER4_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2753 + 1 * TOOL_BUTTON_PLAYER_YSIZE)
2762 } toolbutton_info[NUM_TOOL_BUTTONS] =
2765 TOOL_BUTTON_YES_XPOS, TOOL_BUTTON_YES_GFX_YPOS,
2766 TOOL_BUTTON_YES_XPOS, TOOL_BUTTON_YES_YPOS,
2767 TOOL_BUTTON_YES_XSIZE, TOOL_BUTTON_YES_YSIZE,
2772 TOOL_BUTTON_NO_XPOS, TOOL_BUTTON_NO_GFX_YPOS,
2773 TOOL_BUTTON_NO_XPOS, TOOL_BUTTON_NO_YPOS,
2774 TOOL_BUTTON_NO_XSIZE, TOOL_BUTTON_NO_YSIZE,
2779 TOOL_BUTTON_CONFIRM_XPOS, TOOL_BUTTON_CONFIRM_GFX_YPOS,
2780 TOOL_BUTTON_CONFIRM_XPOS, TOOL_BUTTON_CONFIRM_YPOS,
2781 TOOL_BUTTON_CONFIRM_XSIZE, TOOL_BUTTON_CONFIRM_YSIZE,
2782 TOOL_CTRL_ID_CONFIRM,
2786 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2787 TOOL_BUTTON_PLAYER1_XPOS, TOOL_BUTTON_PLAYER1_YPOS,
2788 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2789 TOOL_CTRL_ID_PLAYER_1,
2793 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2794 TOOL_BUTTON_PLAYER2_XPOS, TOOL_BUTTON_PLAYER2_YPOS,
2795 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2796 TOOL_CTRL_ID_PLAYER_2,
2800 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2801 TOOL_BUTTON_PLAYER3_XPOS, TOOL_BUTTON_PLAYER3_YPOS,
2802 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2803 TOOL_CTRL_ID_PLAYER_3,
2807 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2808 TOOL_BUTTON_PLAYER4_XPOS, TOOL_BUTTON_PLAYER4_YPOS,
2809 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2810 TOOL_CTRL_ID_PLAYER_4,
2815 void CreateToolButtons()
2819 for (i = 0; i < NUM_TOOL_BUTTONS; i++)
2821 Bitmap *gd_bitmap = graphic_info[IMG_GLOBAL_DOOR].bitmap;
2822 Bitmap *deco_bitmap = None;
2823 int deco_x = 0, deco_y = 0, deco_xpos = 0, deco_ypos = 0;
2824 struct GadgetInfo *gi;
2825 unsigned long event_mask;
2826 int gd_xoffset, gd_yoffset;
2827 int gd_x1, gd_x2, gd_y;
2830 event_mask = GD_EVENT_RELEASED;
2832 gd_xoffset = toolbutton_info[i].xpos;
2833 gd_yoffset = toolbutton_info[i].ypos;
2834 gd_x1 = DOOR_GFX_PAGEX4 + gd_xoffset;
2835 gd_x2 = DOOR_GFX_PAGEX3 + gd_xoffset;
2836 gd_y = DOOR_GFX_PAGEY1 + gd_yoffset;
2838 if (id >= TOOL_CTRL_ID_PLAYER_1 && id <= TOOL_CTRL_ID_PLAYER_4)
2840 int player_nr = id - TOOL_CTRL_ID_PLAYER_1;
2842 getMiniGraphicSource(PLAYER_NR_GFX(IMG_PLAYER_1, player_nr),
2843 &deco_bitmap, &deco_x, &deco_y);
2844 deco_xpos = (toolbutton_info[i].width - MINI_TILEX) / 2;
2845 deco_ypos = (toolbutton_info[i].height - MINI_TILEY) / 2;
2848 gi = CreateGadget(GDI_CUSTOM_ID, id,
2849 GDI_INFO_TEXT, toolbutton_info[i].infotext,
2850 GDI_X, DX + toolbutton_info[i].x,
2851 GDI_Y, DY + toolbutton_info[i].y,
2852 GDI_WIDTH, toolbutton_info[i].width,
2853 GDI_HEIGHT, toolbutton_info[i].height,
2854 GDI_TYPE, GD_TYPE_NORMAL_BUTTON,
2855 GDI_STATE, GD_BUTTON_UNPRESSED,
2856 GDI_DESIGN_UNPRESSED, gd_bitmap, gd_x1, gd_y,
2857 GDI_DESIGN_PRESSED, gd_bitmap, gd_x2, gd_y,
2858 GDI_DECORATION_DESIGN, deco_bitmap, deco_x, deco_y,
2859 GDI_DECORATION_POSITION, deco_xpos, deco_ypos,
2860 GDI_DECORATION_SIZE, MINI_TILEX, MINI_TILEY,
2861 GDI_DECORATION_SHIFTING, 1, 1,
2862 GDI_EVENT_MASK, event_mask,
2863 GDI_CALLBACK_ACTION, HandleToolButtons,
2867 Error(ERR_EXIT, "cannot create gadget");
2869 tool_gadget[id] = gi;
2873 void FreeToolButtons()
2877 for (i = 0; i < NUM_TOOL_BUTTONS; i++)
2878 FreeGadget(tool_gadget[i]);
2881 static void UnmapToolButtons()
2885 for (i = 0; i < NUM_TOOL_BUTTONS; i++)
2886 UnmapGadget(tool_gadget[i]);
2889 static void HandleToolButtons(struct GadgetInfo *gi)
2891 request_gadget_id = gi->custom_id;
2894 int get_next_element(int element)
2898 case EL_QUICKSAND_FILLING: return EL_QUICKSAND_FULL;
2899 case EL_QUICKSAND_EMPTYING: return EL_QUICKSAND_EMPTY;
2900 case EL_MAGIC_WALL_FILLING: return EL_MAGIC_WALL_FULL;
2901 case EL_MAGIC_WALL_EMPTYING: return EL_MAGIC_WALL_ACTIVE;
2902 case EL_BD_MAGIC_WALL_FILLING: return EL_BD_MAGIC_WALL_FULL;
2903 case EL_BD_MAGIC_WALL_EMPTYING: return EL_BD_MAGIC_WALL_ACTIVE;
2904 case EL_AMOEBA_DROPPING: return EL_AMOEBA_WET;
2906 default: return element;
2910 int el_act_dir2img(int element, int action, int direction)
2912 element = GFX_ELEMENT(element);
2913 direction = MV_DIR_BIT(direction); /* default: MV_NO_MOVING => MV_DOWN */
2915 return element_info[element].direction_graphic[action][direction];
2918 static int el_act_dir2crm(int element, int action, int direction)
2920 element = GFX_ELEMENT(element);
2921 direction = MV_DIR_BIT(direction); /* default: MV_NO_MOVING => MV_DOWN */
2923 return element_info[element].direction_crumbled[action][direction];
2926 int el_act2img(int element, int action)
2928 element = GFX_ELEMENT(element);
2930 return element_info[element].graphic[action];
2933 int el_act2crm(int element, int action)
2935 element = GFX_ELEMENT(element);
2937 return element_info[element].crumbled[action];
2940 int el_dir2img(int element, int direction)
2942 element = GFX_ELEMENT(element);
2944 return el_act_dir2img(element, ACTION_DEFAULT, direction);
2947 int el2baseimg(int element)
2949 return element_info[element].graphic[ACTION_DEFAULT];
2952 int el2img(int element)
2954 element = GFX_ELEMENT(element);
2956 return element_info[element].graphic[ACTION_DEFAULT];
2959 int el2edimg(int element)
2961 element = GFX_ELEMENT(element);
2963 return element_info[element].special_graphic[GFX_SPECIAL_ARG_EDITOR];
2966 int el2preimg(int element)
2968 element = GFX_ELEMENT(element);
2970 return element_info[element].special_graphic[GFX_SPECIAL_ARG_PREVIEW];