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 /* handle the field the player is leaving ... */
894 if (player_is_moving && IS_ACCESSIBLE_INSIDE(last_element))
895 DrawLevelField(last_jx, last_jy);
896 else if (player_is_moving && IS_ACCESSIBLE_UNDER(last_element))
897 DrawLevelFieldThruMask(last_jx, last_jy);
900 /* !!! I have forgotton what this should be good for !!! */
901 /* !!! causes player being visible when pushing from within tubes !!! */
902 if (!player->is_pushing)
905 /* ... and the field the player is entering */
906 if (IS_ACCESSIBLE_INSIDE(element))
907 DrawLevelField(jx, jy);
908 else if (IS_ACCESSIBLE_UNDER(element))
909 DrawLevelFieldThruMask(jx, jy);
912 if (setup.direct_draw)
914 int dest_x = SX + SCREENX(MIN(jx, last_jx)) * TILEX;
915 int dest_y = SY + SCREENY(MIN(jy, last_jy)) * TILEY;
916 int x_size = TILEX * (1 + ABS(jx - last_jx));
917 int y_size = TILEY * (1 + ABS(jy - last_jy));
919 BlitBitmap(drawto_field, window,
920 dest_x, dest_y, x_size, y_size, dest_x, dest_y);
921 SetDrawtoField(DRAW_DIRECT);
924 MarkTileDirty(sx, sy);
927 void getGraphicSource(int graphic, int frame, Bitmap **bitmap, int *x, int *y)
929 struct GraphicInfo *g = &graphic_info[graphic];
933 if (g->offset_y == 0) /* frames are ordered horizontally */
935 int max_width = g->anim_frames_per_line * g->width;
937 *x = (g->src_x + frame * g->offset_x) % max_width;
938 *y = g->src_y + (g->src_x + frame * g->offset_x) / max_width * g->height;
940 else if (g->offset_x == 0) /* frames are ordered vertically */
942 int max_height = g->anim_frames_per_line * g->height;
944 *x = g->src_x + (g->src_y + frame * g->offset_y) / max_height * g->width;
945 *y = (g->src_y + frame * g->offset_y) % max_height;
947 else /* frames are ordered diagonally */
949 *x = g->src_x + frame * g->offset_x;
950 *y = g->src_y + frame * g->offset_y;
954 void DrawGraphic(int x, int y, int graphic, int frame)
957 if (!IN_SCR_FIELD(x, y))
959 printf("DrawGraphic(): x = %d, y = %d, graphic = %d\n", x, y, graphic);
960 printf("DrawGraphic(): This should never happen!\n");
965 DrawGraphicExt(drawto_field, FX + x * TILEX, FY + y * TILEY, graphic, frame);
969 void DrawGraphicExt(DrawBuffer *dst_bitmap, int x, int y, int graphic,
975 getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
976 BlitBitmap(src_bitmap, dst_bitmap, src_x, src_y, TILEX, TILEY, x, y);
979 void DrawGraphicThruMask(int x, int y, int graphic, int frame)
982 if (!IN_SCR_FIELD(x, y))
984 printf("DrawGraphicThruMask(): x = %d,y = %d, graphic = %d\n",x,y,graphic);
985 printf("DrawGraphicThruMask(): This should never happen!\n");
990 DrawGraphicThruMaskExt(drawto_field, FX + x * TILEX, FY + y *TILEY, graphic,
995 void DrawGraphicThruMaskExt(DrawBuffer *d, int dest_x, int dest_y, int graphic,
1003 getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
1004 drawing_gc = src_bitmap->stored_clip_gc;
1006 GC drawing_gc = src_bitmap->stored_clip_gc;
1007 Bitmap *src_bitmap = graphic_info[graphic].bitmap;
1008 int src_x = graphic_info[graphic].src_x;
1009 int src_y = graphic_info[graphic].src_y;
1010 int offset_x = graphic_info[graphic].offset_x;
1011 int offset_y = graphic_info[graphic].offset_y;
1013 src_x += frame * offset_x;
1014 src_y += frame * offset_y;
1018 SetClipOrigin(src_bitmap, drawing_gc, dest_x - src_x, dest_y - src_y);
1019 BlitBitmapMasked(src_bitmap, d, src_x, src_y, TILEX, TILEY, dest_x, dest_y);
1022 void DrawMiniGraphic(int x, int y, int graphic)
1024 DrawMiniGraphicExt(drawto, SX + x * MINI_TILEX,SY + y * MINI_TILEY, graphic);
1025 MarkTileDirty(x / 2, y / 2);
1028 void getMiniGraphicSource(int graphic, Bitmap **bitmap, int *x, int *y)
1030 struct GraphicInfo *g = &graphic_info[graphic];
1031 int mini_startx = 0;
1032 int mini_starty = g->bitmap->height * 2 / 3;
1034 *bitmap = g->bitmap;
1035 *x = mini_startx + g->src_x / 2;
1036 *y = mini_starty + g->src_y / 2;
1039 void DrawMiniGraphicExt(DrawBuffer *d, int x, int y, int graphic)
1044 getMiniGraphicSource(graphic, &src_bitmap, &src_x, &src_y);
1045 BlitBitmap(src_bitmap, d, src_x, src_y, MINI_TILEX, MINI_TILEY, x, y);
1048 void DrawGraphicShifted(int x, int y, int dx, int dy, int graphic, int frame,
1049 int cut_mode, int mask_mode)
1054 int width = TILEX, height = TILEY;
1060 DrawGraphic(x, y, graphic, frame);
1064 if (dx || dy) /* shifted graphic */
1066 if (x < BX1) /* object enters playfield from the left */
1073 else if (x > BX2) /* object enters playfield from the right */
1079 else if (x==BX1 && dx < 0) /* object leaves playfield to the left */
1085 else if (x==BX2 && dx > 0) /* object leaves playfield to the right */
1087 else if (dx) /* general horizontal movement */
1088 MarkTileDirty(x + SIGN(dx), y);
1090 if (y < BY1) /* object enters playfield from the top */
1092 if (cut_mode==CUT_BELOW) /* object completely above top border */
1100 else if (y > BY2) /* object enters playfield from the bottom */
1106 else if (y==BY1 && dy < 0) /* object leaves playfield to the top */
1112 else if (dy > 0 && cut_mode == CUT_ABOVE)
1114 if (y == BY2) /* object completely above bottom border */
1120 MarkTileDirty(x, y + 1);
1121 } /* object leaves playfield to the bottom */
1122 else if (dy > 0 && (y == BY2 || cut_mode == CUT_BELOW))
1124 else if (dy) /* general vertical movement */
1125 MarkTileDirty(x, y + SIGN(dy));
1129 getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
1131 src_bitmap = graphic_info[graphic].bitmap;
1132 src_x = graphic_info[graphic].src_x;
1133 src_y = graphic_info[graphic].src_y;
1134 offset_x = graphic_info[graphic].offset_x;
1135 offset_y = graphic_info[graphic].offset_y;
1137 src_x += frame * offset_x;
1138 src_y += frame * offset_y;
1141 drawing_gc = src_bitmap->stored_clip_gc;
1146 dest_x = FX + x * TILEX + dx;
1147 dest_y = FY + y * TILEY + dy;
1150 if (!IN_SCR_FIELD(x,y))
1152 printf("DrawGraphicShifted(): x = %d, y = %d, graphic = %d\n",x,y,graphic);
1153 printf("DrawGraphicShifted(): This should never happen!\n");
1158 if (mask_mode == USE_MASKING)
1160 SetClipOrigin(src_bitmap, drawing_gc, dest_x - src_x, dest_y - src_y);
1161 BlitBitmapMasked(src_bitmap, drawto_field, src_x, src_y, width, height,
1165 BlitBitmap(src_bitmap, drawto_field, src_x, src_y, width, height,
1168 MarkTileDirty(x, y);
1171 void DrawGraphicShiftedThruMask(int x, int y, int dx, int dy, int graphic,
1172 int frame, int cut_mode)
1174 DrawGraphicShifted(x, y, dx, dy, graphic, frame, cut_mode, USE_MASKING);
1177 void DrawScreenElementExt(int x, int y, int dx, int dy, int element,
1178 int cut_mode, int mask_mode)
1180 int lx = LEVELX(x), ly = LEVELY(y);
1184 if (IN_LEV_FIELD(lx, ly))
1186 SetRandomAnimationValue(lx, ly);
1188 graphic = el_act_dir2img(element, GfxAction[lx][ly], GfxDir[lx][ly]);
1189 frame = getGraphicAnimationFrame(graphic, GfxFrame[lx][ly]);
1191 else /* border element */
1193 graphic = el2img(element);
1194 frame = getGraphicAnimationFrame(graphic, -1);
1197 if (element == EL_EXPANDABLE_WALL)
1199 boolean left_stopped = FALSE, right_stopped = FALSE;
1201 if (!IN_LEV_FIELD(lx - 1, ly) || IS_WALL(Feld[lx - 1][ly]))
1202 left_stopped = TRUE;
1203 if (!IN_LEV_FIELD(lx + 1, ly) || IS_WALL(Feld[lx + 1][ly]))
1204 right_stopped = TRUE;
1206 if (left_stopped && right_stopped)
1208 else if (left_stopped)
1210 graphic = IMG_EXPANDABLE_WALL_GROWING_RIGHT;
1211 frame = graphic_info[graphic].anim_frames - 1;
1213 else if (right_stopped)
1215 graphic = IMG_EXPANDABLE_WALL_GROWING_LEFT;
1216 frame = graphic_info[graphic].anim_frames - 1;
1221 DrawGraphicShifted(x, y, dx, dy, graphic, frame, cut_mode, mask_mode);
1222 else if (mask_mode == USE_MASKING)
1223 DrawGraphicThruMask(x, y, graphic, frame);
1225 DrawGraphic(x, y, graphic, frame);
1228 void DrawLevelElementExt(int x, int y, int dx, int dy, int element,
1229 int cut_mode, int mask_mode)
1231 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1232 DrawScreenElementExt(SCREENX(x), SCREENY(y), dx, dy, element,
1233 cut_mode, mask_mode);
1236 void DrawScreenElementShifted(int x, int y, int dx, int dy, int element,
1239 DrawScreenElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
1242 void DrawLevelElementShifted(int x, int y, int dx, int dy, int element,
1245 DrawLevelElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
1248 void DrawLevelElementThruMask(int x, int y, int element)
1250 DrawLevelElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
1253 void DrawLevelFieldThruMask(int x, int y)
1255 DrawLevelElementExt(x, y, 0, 0, Feld[x][y], NO_CUTTING, USE_MASKING);
1258 #define TILE_GFX_ELEMENT(x, y) \
1259 (GfxElement[x][y] != EL_UNDEFINED && Feld[x][y] != EL_EXPLOSION ? \
1260 GfxElement[x][y] : Feld[x][y])
1262 static void DrawLevelFieldCrumbledSandExt(int x, int y, int graphic, int frame)
1266 int sx = SCREENX(x), sy = SCREENY(y);
1268 int width, height, cx, cy, i;
1270 int crumbled_border_size = graphic_info[graphic].border_size;
1272 int snip = TILEX / 8; /* number of border pixels from "crumbled graphic" */
1274 static int xy[4][2] =
1283 if (x == 0 && y == 7)
1284 printf("::: %d, %d [%d]\n", GfxElement[x][y], Feld[x][y],
1285 crumbled_border_size);
1288 if (!IN_LEV_FIELD(x, y))
1291 element = TILE_GFX_ELEMENT(x, y);
1293 /* crumble field itself */
1294 if (GFX_CRUMBLED(element) && !IS_MOVING(x, y))
1296 if (!IN_SCR_FIELD(sx, sy))
1299 getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
1301 for (i = 0; i < 4; i++)
1303 int xx = x + xy[i][0];
1304 int yy = y + xy[i][1];
1307 element = (IN_LEV_FIELD(xx, yy) ? TILE_GFX_ELEMENT(xx, yy) :
1310 element = (IN_LEV_FIELD(xx, yy) ? Feld[xx][yy] : BorderElement);
1313 /* check if neighbour field is of same type */
1314 if (GFX_CRUMBLED(element) && !IS_MOVING(xx, yy))
1318 if (Feld[x][y] == EL_CUSTOM_START + 123)
1319 printf("::: crumble [%d] THE CHAOS ENGINE (%d, %d): %d, %d\n",
1320 i, Feld[x][y], element,
1321 GFX_CRUMBLED(element), IS_MOVING(x, y));
1324 if (i == 1 || i == 2)
1326 width = crumbled_border_size;
1328 cx = (i == 2 ? TILEX - crumbled_border_size : 0);
1334 height = crumbled_border_size;
1336 cy = (i == 3 ? TILEY - crumbled_border_size : 0);
1339 BlitBitmap(src_bitmap, drawto_field, src_x + cx, src_y + cy,
1340 width, height, FX + sx * TILEX + cx, FY + sy * TILEY + cy);
1343 MarkTileDirty(sx, sy);
1345 else /* crumble neighbour fields */
1348 getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
1351 for (i = 0; i < 4; i++)
1353 int xx = x + xy[i][0];
1354 int yy = y + xy[i][1];
1355 int sxx = sx + xy[i][0];
1356 int syy = sy + xy[i][1];
1359 if (!IN_LEV_FIELD(xx, yy) ||
1360 !IN_SCR_FIELD(sxx, syy) ||
1364 element = TILE_GFX_ELEMENT(xx, yy);
1366 if (!GFX_CRUMBLED(element))
1369 if (!IN_LEV_FIELD(xx, yy) ||
1370 !IN_SCR_FIELD(sxx, syy) ||
1371 !GFX_CRUMBLED(Feld[xx][yy]) ||
1377 graphic = el_act2crm(Feld[xx][yy], ACTION_DEFAULT);
1378 crumbled_border_size = graphic_info[graphic].border_size;
1380 getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
1383 if (i == 1 || i == 2)
1385 width = crumbled_border_size;
1387 cx = (i == 1 ? TILEX - crumbled_border_size : 0);
1393 height = crumbled_border_size;
1395 cy = (i == 0 ? TILEY - crumbled_border_size : 0);
1398 BlitBitmap(src_bitmap, drawto_field, src_x + cx, src_y + cy,
1399 width, height, FX + sxx * TILEX + cx, FY + syy * TILEY + cy);
1401 MarkTileDirty(sxx, syy);
1406 void DrawLevelFieldCrumbledSand(int x, int y)
1411 if (!IN_LEV_FIELD(x, y))
1414 graphic = el_act2crm(Feld[x][y], ACTION_DEFAULT);
1416 DrawLevelFieldCrumbledSandExt(x, y, graphic, 0);
1418 DrawLevelFieldCrumbledSandExt(x, y, IMG_SAND_CRUMBLED, 0);
1422 void DrawLevelFieldCrumbledSandDigging(int x, int y, int direction,
1426 int graphic1 = el_act_dir2img(GfxElement[x][y], ACTION_DIGGING, direction);
1427 int graphic2 = el_act_dir2crm(GfxElement[x][y], ACTION_DIGGING, direction);
1429 int graphic1 = el_act_dir2img(EL_SAND, ACTION_DIGGING, direction);
1430 int graphic2 = el_act_dir2img(EL_SAND_CRUMBLED, ACTION_DIGGING, direction);
1432 int frame1 = getGraphicAnimationFrame(graphic1, step_frame);
1433 int frame2 = getGraphicAnimationFrame(graphic2, step_frame);
1434 int sx = SCREENX(x), sy = SCREENY(y);
1436 DrawGraphic(sx, sy, graphic1, frame1);
1437 DrawLevelFieldCrumbledSandExt(x, y, graphic2, frame2);
1440 void DrawLevelFieldCrumbledSandNeighbours(int x, int y)
1442 int sx = SCREENX(x), sy = SCREENY(y);
1443 static int xy[4][2] =
1452 for (i = 0; i < 4; i++)
1454 int xx = x + xy[i][0];
1455 int yy = y + xy[i][1];
1456 int sxx = sx + xy[i][0];
1457 int syy = sy + xy[i][1];
1459 if (!IN_LEV_FIELD(xx, yy) ||
1460 !IN_SCR_FIELD(sxx, syy) ||
1461 !GFX_CRUMBLED(Feld[xx][yy]) ||
1465 DrawLevelField(xx, yy);
1469 static int getBorderElement(int x, int y)
1473 { EL_STEELWALL_TOPLEFT, EL_INVISIBLE_STEELWALL_TOPLEFT },
1474 { EL_STEELWALL_TOPRIGHT, EL_INVISIBLE_STEELWALL_TOPRIGHT },
1475 { EL_STEELWALL_BOTTOMLEFT, EL_INVISIBLE_STEELWALL_BOTTOMLEFT },
1476 { EL_STEELWALL_BOTTOMRIGHT, EL_INVISIBLE_STEELWALL_BOTTOMRIGHT },
1477 { EL_STEELWALL_VERTICAL, EL_INVISIBLE_STEELWALL_VERTICAL },
1478 { EL_STEELWALL_HORIZONTAL, EL_INVISIBLE_STEELWALL_HORIZONTAL },
1479 { EL_STEELWALL, EL_INVISIBLE_STEELWALL }
1481 int steel_type = (BorderElement == EL_STEELWALL ? 0 : 1);
1482 int steel_position = (x == -1 && y == -1 ? 0 :
1483 x == lev_fieldx && y == -1 ? 1 :
1484 x == -1 && y == lev_fieldy ? 2 :
1485 x == lev_fieldx && y == lev_fieldy ? 3 :
1486 x == -1 || x == lev_fieldx ? 4 :
1487 y == -1 || y == lev_fieldy ? 5 : 6);
1489 return border[steel_position][steel_type];
1492 void DrawScreenElement(int x, int y, int element)
1494 DrawScreenElementExt(x, y, 0, 0, element, NO_CUTTING, NO_MASKING);
1495 DrawLevelFieldCrumbledSand(LEVELX(x), LEVELY(y));
1498 void DrawLevelElement(int x, int y, int element)
1500 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1501 DrawScreenElement(SCREENX(x), SCREENY(y), element);
1504 void DrawScreenField(int x, int y)
1506 int lx = LEVELX(x), ly = LEVELY(y);
1507 int element, content;
1509 if (!IN_LEV_FIELD(lx, ly))
1511 if (lx < -1 || lx > lev_fieldx || ly < -1 || ly > lev_fieldy)
1514 element = getBorderElement(lx, ly);
1516 DrawScreenElement(x, y, element);
1520 element = Feld[lx][ly];
1521 content = Store[lx][ly];
1523 if (IS_MOVING(lx, ly))
1525 int horiz_move = (MovDir[lx][ly] == MV_LEFT || MovDir[lx][ly] == MV_RIGHT);
1526 boolean cut_mode = NO_CUTTING;
1528 if (element == EL_QUICKSAND_EMPTYING ||
1529 element == EL_MAGIC_WALL_EMPTYING ||
1530 element == EL_BD_MAGIC_WALL_EMPTYING ||
1531 element == EL_AMOEBA_DROPPING)
1532 cut_mode = CUT_ABOVE;
1533 else if (element == EL_QUICKSAND_FILLING ||
1534 element == EL_MAGIC_WALL_FILLING ||
1535 element == EL_BD_MAGIC_WALL_FILLING)
1536 cut_mode = CUT_BELOW;
1538 if (cut_mode == CUT_ABOVE)
1539 DrawScreenElementShifted(x, y, 0, 0, element, NO_CUTTING);
1541 DrawScreenElement(x, y, EL_EMPTY);
1544 DrawScreenElementShifted(x, y, MovPos[lx][ly], 0, element, NO_CUTTING);
1545 else if (cut_mode == NO_CUTTING)
1546 DrawScreenElementShifted(x, y, 0, MovPos[lx][ly], element, cut_mode);
1548 DrawScreenElementShifted(x, y, 0, MovPos[lx][ly], content, cut_mode);
1550 if (content == EL_ACID)
1552 int dir = MovDir[lx][ly];
1553 int newlx = lx + (dir == MV_LEFT ? -1 : dir == MV_RIGHT ? +1 : 0);
1554 int newly = ly + (dir == MV_UP ? -1 : dir == MV_DOWN ? +1 : 0);
1556 DrawLevelElementThruMask(newlx, newly, EL_ACID);
1559 else if (IS_BLOCKED(lx, ly))
1564 boolean cut_mode = NO_CUTTING;
1565 int element_old, content_old;
1567 Blocked2Moving(lx, ly, &oldx, &oldy);
1570 horiz_move = (MovDir[oldx][oldy] == MV_LEFT ||
1571 MovDir[oldx][oldy] == MV_RIGHT);
1573 element_old = Feld[oldx][oldy];
1574 content_old = Store[oldx][oldy];
1576 if (element_old == EL_QUICKSAND_EMPTYING ||
1577 element_old == EL_MAGIC_WALL_EMPTYING ||
1578 element_old == EL_BD_MAGIC_WALL_EMPTYING ||
1579 element_old == EL_AMOEBA_DROPPING)
1580 cut_mode = CUT_ABOVE;
1582 DrawScreenElement(x, y, EL_EMPTY);
1585 DrawScreenElementShifted(sx, sy, MovPos[oldx][oldy], 0, element_old,
1587 else if (cut_mode == NO_CUTTING)
1588 DrawScreenElementShifted(sx, sy, 0, MovPos[oldx][oldy], element_old,
1591 DrawScreenElementShifted(sx, sy, 0, MovPos[oldx][oldy], content_old,
1594 else if (IS_DRAWABLE(element))
1595 DrawScreenElement(x, y, element);
1597 DrawScreenElement(x, y, EL_EMPTY);
1600 void DrawLevelField(int x, int y)
1602 if (IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1603 DrawScreenField(SCREENX(x), SCREENY(y));
1604 else if (IS_MOVING(x, y))
1608 Moving2Blocked(x, y, &newx, &newy);
1609 if (IN_SCR_FIELD(SCREENX(newx), SCREENY(newy)))
1610 DrawScreenField(SCREENX(newx), SCREENY(newy));
1612 else if (IS_BLOCKED(x, y))
1616 Blocked2Moving(x, y, &oldx, &oldy);
1617 if (IN_SCR_FIELD(SCREENX(oldx), SCREENY(oldy)))
1618 DrawScreenField(SCREENX(oldx), SCREENY(oldy));
1622 void DrawMiniElement(int x, int y, int element)
1626 graphic = el2edimg(element);
1627 DrawMiniGraphic(x, y, graphic);
1630 void DrawMiniElementOrWall(int sx, int sy, int scroll_x, int scroll_y)
1632 int x = sx + scroll_x, y = sy + scroll_y;
1634 if (x < -1 || x > lev_fieldx || y < -1 || y > lev_fieldy)
1635 DrawMiniElement(sx, sy, EL_EMPTY);
1636 else if (x > -1 && x < lev_fieldx && y > -1 && y < lev_fieldy)
1637 DrawMiniElement(sx, sy, Feld[x][y]);
1639 DrawMiniGraphic(sx, sy, el2edimg(getBorderElement(x, y)));
1642 void DrawEnvelopeBackground(int envelope_nr, int startx, int starty,
1643 int x, int y, int xsize, int ysize, int font_nr)
1645 int font_width = getFontWidth(font_nr);
1646 int font_height = getFontHeight(font_nr);
1647 int graphic = IMG_BACKGROUND_ENVELOPE_1 + envelope_nr;
1650 int dst_x = SX + startx + x * font_width;
1651 int dst_y = SY + starty + y * font_height;
1652 int width = graphic_info[graphic].width;
1653 int height = graphic_info[graphic].height;
1654 int inner_width = MAX(width - 2 * font_width, font_width);
1655 int inner_height = MAX(height - 2 * font_height, font_height);
1656 int inner_sx = (width >= 3 * font_width ? font_width : 0);
1657 int inner_sy = (height >= 3 * font_height ? font_height : 0);
1658 boolean draw_masked = graphic_info[graphic].draw_masked;
1660 getGraphicSource(graphic, 0, &src_bitmap, &src_x, &src_y);
1662 if (src_bitmap == NULL || width < font_width || height < font_height)
1664 ClearRectangle(drawto, dst_x, dst_y, font_width, font_height);
1668 src_x += (x == 0 ? 0 : x == xsize - 1 ? width - font_width :
1669 inner_sx + (x - 1) * font_width % inner_width);
1670 src_y += (y == 0 ? 0 : y == ysize - 1 ? height - font_height :
1671 inner_sy + (y - 1) * font_height % inner_height);
1675 SetClipOrigin(src_bitmap, src_bitmap->stored_clip_gc,
1676 dst_x - src_x, dst_y - src_y);
1677 BlitBitmapMasked(src_bitmap, drawto, src_x, src_y, font_width, font_height,
1681 BlitBitmap(src_bitmap, drawto, src_x, src_y, font_width, font_height,
1685 void AnimateEnvelope(int envelope_nr, int anim_mode, int action)
1687 int graphic = IMG_BACKGROUND_ENVELOPE_1 + envelope_nr;
1688 boolean draw_masked = graphic_info[graphic].draw_masked;
1689 int mask_mode = (draw_masked ? BLIT_MASKED : BLIT_ON_BACKGROUND);
1690 boolean ffwd_delay = (tape.playing && tape.fast_forward);
1691 boolean no_delay = (tape.warp_forward);
1692 unsigned long anim_delay = 0;
1693 int frame_delay_value = (ffwd_delay ? FfwdFrameDelay : GameFrameDelay);
1694 int anim_delay_value = (no_delay ? 0 : frame_delay_value);
1695 int font_nr = FONT_ENVELOPE_1 + envelope_nr;
1696 int font_width = getFontWidth(font_nr);
1697 int font_height = getFontHeight(font_nr);
1698 int max_xsize = level.envelope_xsize[envelope_nr];
1699 int max_ysize = level.envelope_ysize[envelope_nr];
1700 int xstart = (anim_mode & ANIM_VERTICAL ? max_xsize : 0);
1701 int ystart = (anim_mode & ANIM_HORIZONTAL ? max_ysize : 0);
1702 int xend = max_xsize;
1703 int yend = (anim_mode != ANIM_DEFAULT ? max_ysize : 0);
1704 int xstep = (xstart < xend ? 1 : 0);
1705 int ystep = (ystart < yend || xstep == 0 ? 1 : 0);
1708 for (x = xstart, y = ystart; x <= xend && y <= yend; x += xstep, y += ystep)
1710 int xsize = (action == ACTION_CLOSING ? xend - (x - xstart) : x) + 2;
1711 int ysize = (action == ACTION_CLOSING ? yend - (y - ystart) : y) + 2;
1712 int sx = (SXSIZE - xsize * font_width) / 2;
1713 int sy = (SYSIZE - ysize * font_height) / 2;
1716 SetDrawtoField(DRAW_BUFFERED);
1718 BlitBitmap(fieldbuffer, backbuffer, FX, FY, SXSIZE, SYSIZE, SX, SY);
1720 SetDrawtoField(DRAW_BACKBUFFER);
1722 for (yy = 0; yy < ysize; yy++) for (xx = 0; xx < xsize; xx++)
1723 DrawEnvelopeBackground(envelope_nr, sx,sy, xx,yy, xsize, ysize, font_nr);
1725 DrawTextToTextArea(SX + sx + font_width, SY + sy + font_height,
1726 level.envelope_text[envelope_nr], font_nr, max_xsize,
1727 xsize - 2, ysize - 2, mask_mode);
1729 redraw_mask |= REDRAW_FIELD | REDRAW_FROM_BACKBUFFER;
1732 WaitUntilDelayReached(&anim_delay, anim_delay_value / 2);
1736 void ShowEnvelope(int envelope_nr)
1738 int element = EL_ENVELOPE_1 + envelope_nr;
1739 int graphic = IMG_BACKGROUND_ENVELOPE_1 + envelope_nr;
1740 int sound_opening = element_info[element].sound[ACTION_OPENING];
1741 int sound_closing = element_info[element].sound[ACTION_CLOSING];
1742 boolean ffwd_delay = (tape.playing && tape.fast_forward);
1743 boolean no_delay = (tape.warp_forward);
1744 int normal_delay_value = ONE_SECOND_DELAY / (ffwd_delay ? 2 : 1);
1745 int wait_delay_value = (no_delay ? 0 : normal_delay_value);
1746 int anim_mode = graphic_info[graphic].anim_mode;
1747 int main_anim_mode = (anim_mode == ANIM_NONE ? ANIM_VERTICAL|ANIM_HORIZONTAL:
1748 anim_mode == ANIM_DEFAULT ? ANIM_VERTICAL : anim_mode);
1750 game.envelope_active = TRUE; /* needed for RedrawPlayfield() events */
1752 PlaySoundStereo(sound_opening, SOUND_MIDDLE);
1754 if (anim_mode == ANIM_DEFAULT)
1755 AnimateEnvelope(envelope_nr, ANIM_DEFAULT, ACTION_OPENING);
1757 AnimateEnvelope(envelope_nr, main_anim_mode, ACTION_OPENING);
1760 Delay(wait_delay_value);
1762 WaitForEventToContinue();
1764 PlaySoundStereo(sound_closing, SOUND_MIDDLE);
1766 if (anim_mode != ANIM_NONE)
1767 AnimateEnvelope(envelope_nr, main_anim_mode, ACTION_CLOSING);
1769 if (anim_mode == ANIM_DEFAULT)
1770 AnimateEnvelope(envelope_nr, ANIM_DEFAULT, ACTION_CLOSING);
1772 game.envelope_active = FALSE;
1774 SetDrawtoField(DRAW_BUFFERED);
1776 redraw_mask |= REDRAW_FIELD;
1780 void getMicroGraphicSource(int graphic, Bitmap **bitmap, int *x, int *y)
1782 Bitmap *src_bitmap = graphic_info[graphic].bitmap;
1783 int mini_startx = src_bitmap->width * 3 / 4;
1784 int mini_starty = src_bitmap->height * 2 / 3;
1785 int src_x = mini_startx + graphic_info[graphic].src_x / 8;
1786 int src_y = mini_starty + graphic_info[graphic].src_y / 8;
1788 *bitmap = src_bitmap;
1793 void DrawMicroElement(int xpos, int ypos, int element)
1797 int graphic = el2preimg(element);
1799 getMicroGraphicSource(graphic, &src_bitmap, &src_x, &src_y);
1800 BlitBitmap(src_bitmap, drawto, src_x, src_y, MICRO_TILEX, MICRO_TILEY,
1808 SetDrawBackgroundMask(REDRAW_NONE);
1811 for (x = BX1; x <= BX2; x++)
1812 for (y = BY1; y <= BY2; y++)
1813 DrawScreenField(x, y);
1815 redraw_mask |= REDRAW_FIELD;
1818 void DrawMiniLevel(int size_x, int size_y, int scroll_x, int scroll_y)
1822 for (x = 0; x < size_x; x++)
1823 for (y = 0; y < size_y; y++)
1824 DrawMiniElementOrWall(x, y, scroll_x, scroll_y);
1826 redraw_mask |= REDRAW_FIELD;
1829 static void DrawMicroLevelExt(int xpos, int ypos, int from_x, int from_y)
1833 DrawBackground(xpos, ypos, MICROLEV_XSIZE, MICROLEV_YSIZE);
1835 if (lev_fieldx < STD_LEV_FIELDX)
1836 xpos += (STD_LEV_FIELDX - lev_fieldx) / 2 * MICRO_TILEX;
1837 if (lev_fieldy < STD_LEV_FIELDY)
1838 ypos += (STD_LEV_FIELDY - lev_fieldy) / 2 * MICRO_TILEY;
1840 xpos += MICRO_TILEX;
1841 ypos += MICRO_TILEY;
1843 for (x = -1; x <= STD_LEV_FIELDX; x++)
1845 for (y = -1; y <= STD_LEV_FIELDY; y++)
1847 int lx = from_x + x, ly = from_y + y;
1849 if (lx >= 0 && lx < lev_fieldx && ly >= 0 && ly < lev_fieldy)
1850 DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
1851 level.field[lx][ly]);
1852 else if (lx >= -1 && lx < lev_fieldx+1 && ly >= -1 && ly < lev_fieldy+1
1853 && BorderElement != EL_EMPTY)
1854 DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
1855 getBorderElement(lx, ly));
1859 redraw_mask |= REDRAW_MICROLEVEL;
1862 #define MICROLABEL_EMPTY 0
1863 #define MICROLABEL_LEVEL_NAME 1
1864 #define MICROLABEL_CREATED_BY 2
1865 #define MICROLABEL_LEVEL_AUTHOR 3
1866 #define MICROLABEL_IMPORTED_FROM 4
1867 #define MICROLABEL_LEVEL_IMPORT_INFO 5
1869 static void DrawMicroLevelLabelExt(int mode)
1871 char label_text[MAX_OUTPUT_LINESIZE + 1];
1872 int max_len_label_text;
1873 int font_nr = FONT_TEXT_2;
1875 if (mode == MICROLABEL_CREATED_BY || mode == MICROLABEL_IMPORTED_FROM)
1876 font_nr = FONT_TEXT_3;
1878 max_len_label_text = SXSIZE / getFontWidth(font_nr);
1880 DrawBackground(SX, MICROLABEL_YPOS, SXSIZE, getFontHeight(font_nr));
1882 strncpy(label_text, (mode == MICROLABEL_LEVEL_NAME ? level.name :
1883 mode == MICROLABEL_CREATED_BY ? "created by" :
1884 mode == MICROLABEL_LEVEL_AUTHOR ? level.author :
1885 mode == MICROLABEL_IMPORTED_FROM ? "imported from" :
1886 mode == MICROLABEL_LEVEL_IMPORT_INFO ?
1887 leveldir_current->imported_from : ""),
1888 max_len_label_text);
1889 label_text[max_len_label_text] = '\0';
1891 if (strlen(label_text) > 0)
1893 int lxpos = SX + (SXSIZE - getTextWidth(label_text, font_nr)) / 2;
1894 int lypos = MICROLABEL_YPOS;
1896 DrawText(lxpos, lypos, label_text, font_nr);
1899 redraw_mask |= REDRAW_MICROLEVEL;
1902 void DrawMicroLevel(int xpos, int ypos, boolean restart)
1904 static unsigned long scroll_delay = 0;
1905 static unsigned long label_delay = 0;
1906 static int from_x, from_y, scroll_direction;
1907 static int label_state, label_counter;
1908 int last_game_status = game_status; /* save current game status */
1910 /* force PREVIEW font on preview level */
1911 game_status = GAME_MODE_PSEUDO_PREVIEW;
1915 from_x = from_y = 0;
1916 scroll_direction = MV_RIGHT;
1920 DrawMicroLevelExt(xpos, ypos, from_x, from_y);
1921 DrawMicroLevelLabelExt(label_state);
1923 /* initialize delay counters */
1924 DelayReached(&scroll_delay, 0);
1925 DelayReached(&label_delay, 0);
1927 if (leveldir_current->name)
1929 int text_width = getTextWidth(leveldir_current->name, FONT_TEXT_1);
1930 int lxpos = SX + (SXSIZE - text_width) / 2;
1931 int lypos = SY + 352;
1933 DrawText(lxpos, lypos, leveldir_current->name, FONT_TEXT_1);
1936 game_status = last_game_status; /* restore current game status */
1941 /* scroll micro level, if needed */
1942 if ((lev_fieldx > STD_LEV_FIELDX || lev_fieldy > STD_LEV_FIELDY) &&
1943 DelayReached(&scroll_delay, MICROLEVEL_SCROLL_DELAY))
1945 switch (scroll_direction)
1951 scroll_direction = MV_UP;
1955 if (from_x < lev_fieldx - STD_LEV_FIELDX)
1958 scroll_direction = MV_DOWN;
1965 scroll_direction = MV_RIGHT;
1969 if (from_y < lev_fieldy - STD_LEV_FIELDY)
1972 scroll_direction = MV_LEFT;
1979 DrawMicroLevelExt(xpos, ypos, from_x, from_y);
1982 /* redraw micro level label, if needed */
1983 if (strcmp(level.name, NAMELESS_LEVEL_NAME) != 0 &&
1984 strcmp(level.author, ANONYMOUS_NAME) != 0 &&
1985 strcmp(level.author, leveldir_current->name) != 0 &&
1986 DelayReached(&label_delay, MICROLEVEL_LABEL_DELAY))
1988 int max_label_counter = 23;
1990 if (leveldir_current->imported_from != NULL)
1991 max_label_counter += 14;
1993 label_counter = (label_counter + 1) % max_label_counter;
1994 label_state = (label_counter >= 0 && label_counter <= 7 ?
1995 MICROLABEL_LEVEL_NAME :
1996 label_counter >= 9 && label_counter <= 12 ?
1997 MICROLABEL_CREATED_BY :
1998 label_counter >= 14 && label_counter <= 21 ?
1999 MICROLABEL_LEVEL_AUTHOR :
2000 label_counter >= 23 && label_counter <= 26 ?
2001 MICROLABEL_IMPORTED_FROM :
2002 label_counter >= 28 && label_counter <= 35 ?
2003 MICROLABEL_LEVEL_IMPORT_INFO : MICROLABEL_EMPTY);
2004 DrawMicroLevelLabelExt(label_state);
2007 game_status = last_game_status; /* restore current game status */
2010 void WaitForEventToContinue()
2012 boolean still_wait = TRUE;
2014 /* simulate releasing mouse button over last gadget, if still pressed */
2016 HandleGadgets(-1, -1, 0);
2018 button_status = MB_RELEASED;
2030 case EVENT_BUTTONPRESS:
2031 case EVENT_KEYPRESS:
2035 case EVENT_KEYRELEASE:
2036 ClearPlayerAction();
2040 HandleOtherEvents(&event);
2044 else if (AnyJoystickButton() == JOY_BUTTON_NEW_PRESSED)
2051 /* don't eat all CPU time */
2056 #define MAX_REQUEST_LINES 13
2057 #define MAX_REQUEST_LINE_FONT1_LEN 7
2058 #define MAX_REQUEST_LINE_FONT2_LEN 10
2060 boolean Request(char *text, unsigned int req_state)
2062 int mx, my, ty, result = -1;
2063 unsigned int old_door_state;
2064 int last_game_status = game_status; /* save current game status */
2065 int max_request_line_len = MAX_REQUEST_LINE_FONT1_LEN;
2066 int font_nr = FONT_TEXT_2;
2067 int max_word_len = 0;
2070 for (text_ptr = text; *text_ptr; text_ptr++)
2072 max_word_len = (*text_ptr != ' ' ? max_word_len + 1 : 0);
2074 if (max_word_len > MAX_REQUEST_LINE_FONT1_LEN)
2076 max_request_line_len = MAX_REQUEST_LINE_FONT2_LEN;
2077 font_nr = FONT_LEVEL_NUMBER;
2084 /* disable deactivated drawing when quick-loading level tape recording */
2085 if (tape.playing && tape.deactivate_display)
2086 TapeDeactivateDisplayOff(TRUE);
2090 SetMouseCursor(CURSOR_DEFAULT);
2093 #if defined(NETWORK_AVALIABLE)
2094 /* pause network game while waiting for request to answer */
2095 if (options.network &&
2096 game_status == GAME_MODE_PLAYING &&
2097 req_state & REQUEST_WAIT_FOR)
2098 SendToServer_PausePlaying();
2101 old_door_state = GetDoorState();
2103 /* simulate releasing mouse button over last gadget, if still pressed */
2105 HandleGadgets(-1, -1, 0);
2109 CloseDoor(DOOR_CLOSE_1);
2111 /* save old door content */
2112 BlitBitmap(bitmap_db_door, bitmap_db_door,
2113 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE,
2114 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1);
2116 SetDrawBackgroundMask(REDRAW_FIELD | REDRAW_DOOR_1);
2118 /* clear door drawing field */
2119 DrawBackground(DX, DY, DXSIZE, DYSIZE);
2121 /* force DOOR font on preview level */
2122 game_status = GAME_MODE_PSEUDO_DOOR;
2124 /* write text for request */
2125 for (ty = 0; ty < MAX_REQUEST_LINES; ty++)
2127 char text_line[max_request_line_len + 1];
2133 for (tl = 0, tx = 0; tx < max_request_line_len; tl++, tx++)
2136 if (!tc || tc == ' ')
2147 strncpy(text_line, text, tl);
2150 DrawText(DX + (DXSIZE - tl * getFontWidth(font_nr)) / 2,
2151 DY + 8 + ty * (getFontHeight(font_nr) + 2),
2152 text_line, font_nr);
2154 text += tl + (tc == ' ' ? 1 : 0);
2157 game_status = last_game_status; /* restore current game status */
2159 if (req_state & REQ_ASK)
2161 MapGadget(tool_gadget[TOOL_CTRL_ID_YES]);
2162 MapGadget(tool_gadget[TOOL_CTRL_ID_NO]);
2164 else if (req_state & REQ_CONFIRM)
2166 MapGadget(tool_gadget[TOOL_CTRL_ID_CONFIRM]);
2168 else if (req_state & REQ_PLAYER)
2170 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_1]);
2171 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_2]);
2172 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_3]);
2173 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_4]);
2176 /* copy request gadgets to door backbuffer */
2177 BlitBitmap(drawto, bitmap_db_door,
2178 DX, DY, DXSIZE, DYSIZE,
2179 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
2181 OpenDoor(DOOR_OPEN_1);
2187 if (!(req_state & REQUEST_WAIT_FOR))
2189 SetDrawBackgroundMask(REDRAW_FIELD);
2194 if (game_status != GAME_MODE_MAIN)
2197 button_status = MB_RELEASED;
2199 request_gadget_id = -1;
2201 SetDrawBackgroundMask(REDRAW_FIELD | REDRAW_DOOR_1);
2204 SetMouseCursor(CURSOR_DEFAULT);
2217 case EVENT_BUTTONPRESS:
2218 case EVENT_BUTTONRELEASE:
2219 case EVENT_MOTIONNOTIFY:
2221 if (event.type == EVENT_MOTIONNOTIFY)
2223 if (!PointerInWindow(window))
2224 continue; /* window and pointer are on different screens */
2229 motion_status = TRUE;
2230 mx = ((MotionEvent *) &event)->x;
2231 my = ((MotionEvent *) &event)->y;
2235 motion_status = FALSE;
2236 mx = ((ButtonEvent *) &event)->x;
2237 my = ((ButtonEvent *) &event)->y;
2238 if (event.type == EVENT_BUTTONPRESS)
2239 button_status = ((ButtonEvent *) &event)->button;
2241 button_status = MB_RELEASED;
2244 /* this sets 'request_gadget_id' */
2245 HandleGadgets(mx, my, button_status);
2247 switch(request_gadget_id)
2249 case TOOL_CTRL_ID_YES:
2252 case TOOL_CTRL_ID_NO:
2255 case TOOL_CTRL_ID_CONFIRM:
2256 result = TRUE | FALSE;
2259 case TOOL_CTRL_ID_PLAYER_1:
2262 case TOOL_CTRL_ID_PLAYER_2:
2265 case TOOL_CTRL_ID_PLAYER_3:
2268 case TOOL_CTRL_ID_PLAYER_4:
2279 case EVENT_KEYPRESS:
2280 switch(GetEventKey((KeyEvent *)&event, TRUE))
2293 if (req_state & REQ_PLAYER)
2297 case EVENT_KEYRELEASE:
2298 ClearPlayerAction();
2302 HandleOtherEvents(&event);
2306 else if (AnyJoystickButton() == JOY_BUTTON_NEW_PRESSED)
2308 int joy = AnyJoystick();
2310 if (joy & JOY_BUTTON_1)
2312 else if (joy & JOY_BUTTON_2)
2318 /* don't eat all CPU time */
2322 if (game_status != GAME_MODE_MAIN)
2327 if (!(req_state & REQ_STAY_OPEN))
2329 CloseDoor(DOOR_CLOSE_1);
2331 if (!(req_state & REQ_STAY_CLOSED) && (old_door_state & DOOR_OPEN_1))
2333 BlitBitmap(bitmap_db_door, bitmap_db_door,
2334 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE,
2335 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
2336 OpenDoor(DOOR_OPEN_1);
2342 SetDrawBackgroundMask(REDRAW_FIELD);
2344 #if defined(NETWORK_AVALIABLE)
2345 /* continue network game after request */
2346 if (options.network &&
2347 game_status == GAME_MODE_PLAYING &&
2348 req_state & REQUEST_WAIT_FOR)
2349 SendToServer_ContinuePlaying();
2353 /* restore deactivated drawing when quick-loading level tape recording */
2354 if (tape.playing && tape.deactivate_display)
2355 TapeDeactivateDisplayOn();
2361 unsigned int OpenDoor(unsigned int door_state)
2363 unsigned int new_door_state;
2365 if (door_state & DOOR_COPY_BACK)
2367 BlitBitmap(bitmap_db_door, bitmap_db_door,
2368 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE + VYSIZE,
2369 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
2370 door_state &= ~DOOR_COPY_BACK;
2373 new_door_state = MoveDoor(door_state);
2375 return(new_door_state);
2378 unsigned int CloseDoor(unsigned int door_state)
2380 unsigned int new_door_state;
2382 BlitBitmap(backbuffer, bitmap_db_door,
2383 DX, DY, DXSIZE, DYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
2384 BlitBitmap(backbuffer, bitmap_db_door,
2385 VX, VY, VXSIZE, VYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2);
2387 new_door_state = MoveDoor(door_state);
2389 return(new_door_state);
2392 unsigned int GetDoorState()
2394 return MoveDoor(DOOR_GET_STATE);
2397 unsigned int SetDoorState(unsigned int door_state)
2399 return MoveDoor(door_state | DOOR_SET_STATE);
2402 unsigned int MoveDoor(unsigned int door_state)
2404 static int door1 = DOOR_OPEN_1;
2405 static int door2 = DOOR_CLOSE_2;
2406 unsigned long door_delay = 0;
2407 unsigned long door_delay_value;
2410 if (door_state == DOOR_GET_STATE)
2411 return(door1 | door2);
2413 if (door_state & DOOR_SET_STATE)
2415 if (door_state & DOOR_ACTION_1)
2416 door1 = door_state & DOOR_ACTION_1;
2417 if (door_state & DOOR_ACTION_2)
2418 door2 = door_state & DOOR_ACTION_2;
2420 return(door1 | door2);
2423 if (door1 == DOOR_OPEN_1 && door_state & DOOR_OPEN_1)
2424 door_state &= ~DOOR_OPEN_1;
2425 else if (door1 == DOOR_CLOSE_1 && door_state & DOOR_CLOSE_1)
2426 door_state &= ~DOOR_CLOSE_1;
2427 if (door2 == DOOR_OPEN_2 && door_state & DOOR_OPEN_2)
2428 door_state &= ~DOOR_OPEN_2;
2429 else if (door2 == DOOR_CLOSE_2 && door_state & DOOR_CLOSE_2)
2430 door_state &= ~DOOR_CLOSE_2;
2432 door_delay_value = (door_state & DOOR_ACTION_1 ? door_1.step_delay :
2435 if (setup.quick_doors)
2437 stepsize = 20; /* must be choosen to always draw last frame */
2438 door_delay_value = 0;
2441 StopSound(SND_DOOR_OPENING);
2442 StopSound(SND_DOOR_CLOSING);
2446 if (global.autoplay_leveldir)
2448 door_state |= DOOR_NO_DELAY;
2449 door_state &= ~DOOR_CLOSE_ALL;
2452 if (door_state & DOOR_ACTION)
2454 boolean door_1_done = !(door_state & DOOR_ACTION_1);
2455 boolean door_2_done = !(door_state & DOOR_ACTION_2);
2456 int start = ((door_state & DOOR_NO_DELAY) ? DXSIZE : 0);
2457 int end = (door_state & DOOR_ACTION_1 &&
2458 door_1.anim_mode == ANIM_VERTICAL ? DYSIZE : DXSIZE);
2461 if (!(door_state & DOOR_NO_DELAY) && !setup.quick_doors)
2463 /* opening door sound has priority over simultaneously closing door */
2464 if (door_state & (DOOR_OPEN_1 | DOOR_OPEN_2))
2465 PlaySoundStereo(SND_DOOR_OPENING, SOUND_MIDDLE);
2466 else if (door_state & (DOOR_CLOSE_1 | DOOR_CLOSE_2))
2467 PlaySoundStereo(SND_DOOR_CLOSING, SOUND_MIDDLE);
2470 for (x = start; x <= end && !(door_1_done && door_2_done); x += stepsize)
2472 Bitmap *bitmap = graphic_info[IMG_GLOBAL_DOOR].bitmap;
2473 GC gc = bitmap->stored_clip_gc;
2475 if (door_state & DOOR_ACTION_1)
2477 int a = MIN(x * door_1.step_offset, end);
2478 int i = (door_state & DOOR_OPEN_1 ? end - a : a);
2482 BlitBitmap(bitmap_db_door, drawto,
2483 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1 + i / 2,
2484 DXSIZE,DYSIZE - i / 2, DX, DY);
2486 ClearRectangle(drawto, DX, DY + DYSIZE - i / 2, DXSIZE, i / 2);
2489 if (door_1.anim_mode == ANIM_HORIZONTAL && x <= DXSIZE)
2491 int src1_x = DXSIZE, src1_y = DOOR_GFX_PAGEY1;
2492 int dst1_x = DX + DXSIZE - i, dst1_y = DY;
2493 int src2_x = DXSIZE - i, src2_y = DOOR_GFX_PAGEY1;
2494 int dst2_x = DX, dst2_y = DY;
2495 int width = i, height = DYSIZE;
2497 SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y);
2498 BlitBitmapMasked(bitmap, drawto, src1_x, src1_y, width, height,
2501 SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y);
2502 BlitBitmapMasked(bitmap, drawto, src2_x, src2_y, width, height,
2505 else if (door_1.anim_mode == ANIM_VERTICAL && x <= DYSIZE)
2507 int src1_x = DXSIZE, src1_y = DOOR_GFX_PAGEY1;
2508 int dst1_x = DX, dst1_y = DY + DYSIZE - i;
2509 int src2_x = 0, src2_y = DOOR_GFX_PAGEY1 + DYSIZE - i;
2510 int dst2_x = DX, dst2_y = DY;
2511 int width = DXSIZE, height = i;
2513 SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y);
2514 BlitBitmapMasked(bitmap, drawto, src1_x, src1_y, width, height,
2517 SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y);
2518 BlitBitmapMasked(bitmap, drawto, src2_x, src2_y, width, height,
2521 else if (x <= DXSIZE) /* ANIM_DEFAULT */
2523 int j = (door_1.anim_mode == ANIM_DEFAULT ? (DXSIZE - i) / 3 : 0);
2525 SetClipOrigin(bitmap, gc, DX - i, (DY + j) - DOOR_GFX_PAGEY1);
2526 BlitBitmapMasked(bitmap, drawto,
2527 DXSIZE, DOOR_GFX_PAGEY1, i, 77,
2528 DX + DXSIZE - i, DY + j);
2529 BlitBitmapMasked(bitmap, drawto,
2530 DXSIZE, DOOR_GFX_PAGEY1 + 140, i, 63,
2531 DX + DXSIZE - i, DY + 140 + j);
2532 SetClipOrigin(bitmap, gc, DX - DXSIZE + i,
2533 DY - (DOOR_GFX_PAGEY1 + j));
2534 BlitBitmapMasked(bitmap, drawto,
2535 DXSIZE - i, DOOR_GFX_PAGEY1 + j, i, 77 - j,
2537 BlitBitmapMasked(bitmap, drawto,
2538 DXSIZE-i, DOOR_GFX_PAGEY1 + 140, i, 63,
2541 BlitBitmapMasked(bitmap, drawto,
2542 DXSIZE - i, DOOR_GFX_PAGEY1 + 77, i, 63,
2544 BlitBitmapMasked(bitmap, drawto,
2545 DXSIZE - i, DOOR_GFX_PAGEY1 + 203, i, 77,
2547 SetClipOrigin(bitmap, gc, DX - i, (DY + j) - DOOR_GFX_PAGEY1);
2548 BlitBitmapMasked(bitmap, drawto,
2549 DXSIZE, DOOR_GFX_PAGEY1 + 77, i, 63,
2550 DX + DXSIZE - i, DY + 77 + j);
2551 BlitBitmapMasked(bitmap, drawto,
2552 DXSIZE, DOOR_GFX_PAGEY1 + 203, i, 77 - j,
2553 DX + DXSIZE - i, DY + 203 + j);
2556 redraw_mask |= REDRAW_DOOR_1;
2557 door_1_done = (a == end);
2560 if (door_state & DOOR_ACTION_2)
2562 int a = MIN(x * door_2.step_offset, VXSIZE);
2563 int i = (door_state & DOOR_OPEN_2 ? VXSIZE - a : a);
2567 BlitBitmap(bitmap_db_door, drawto,
2568 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2 + i / 2,
2569 VXSIZE, VYSIZE - i / 2, VX, VY);
2571 ClearRectangle(drawto, VX, VY + VYSIZE - i / 2, VXSIZE, i / 2);
2574 if (door_2.anim_mode == ANIM_HORIZONTAL && x <= VXSIZE)
2576 int src1_x = VXSIZE, src1_y = DOOR_GFX_PAGEY2;
2577 int dst1_x = VX + VXSIZE - i, dst1_y = VY;
2578 int src2_x = VXSIZE - i, src2_y = DOOR_GFX_PAGEY2;
2579 int dst2_x = VX, dst2_y = VY;
2580 int width = i, height = VYSIZE;
2582 SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y);
2583 BlitBitmapMasked(bitmap, drawto, src1_x, src1_y, width, height,
2586 SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y);
2587 BlitBitmapMasked(bitmap, drawto, src2_x, src2_y, width, height,
2590 else if (door_2.anim_mode == ANIM_VERTICAL && x <= VYSIZE)
2592 int src1_x = VXSIZE, src1_y = DOOR_GFX_PAGEY2;
2593 int dst1_x = VX, dst1_y = VY + VYSIZE - i;
2594 int src2_x = 0, src2_y = DOOR_GFX_PAGEY2 + VYSIZE - i;
2595 int dst2_x = VX, dst2_y = VY;
2596 int width = VXSIZE, height = i;
2598 SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y);
2599 BlitBitmapMasked(bitmap, drawto, src1_x, src1_y, width, height,
2602 SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y);
2603 BlitBitmapMasked(bitmap, drawto, src2_x, src2_y, width, height,
2606 else if (x <= VXSIZE) /* ANIM_DEFAULT */
2608 int j = (door_2.anim_mode == ANIM_DEFAULT ? (VXSIZE - i) / 3 : 0);
2610 SetClipOrigin(bitmap, gc, VX - i, (VY + j) - DOOR_GFX_PAGEY2);
2611 BlitBitmapMasked(bitmap, drawto,
2612 VXSIZE, DOOR_GFX_PAGEY2, i, VYSIZE / 2,
2613 VX + VXSIZE - i, VY + j);
2614 SetClipOrigin(bitmap, gc,
2615 VX - VXSIZE + i, VY - (DOOR_GFX_PAGEY2 + j));
2616 BlitBitmapMasked(bitmap, drawto,
2617 VXSIZE - i, DOOR_GFX_PAGEY2 + j, i, VYSIZE / 2 - j,
2620 BlitBitmapMasked(bitmap, drawto,
2621 VXSIZE - i, DOOR_GFX_PAGEY2 + VYSIZE / 2,
2622 i, VYSIZE / 2, VX, VY + VYSIZE / 2 - j);
2623 SetClipOrigin(bitmap, gc, VX - i, (VY + j) - DOOR_GFX_PAGEY2);
2624 BlitBitmapMasked(bitmap, drawto,
2625 VXSIZE, DOOR_GFX_PAGEY2 + VYSIZE / 2,
2627 VX + VXSIZE - i, VY + VYSIZE / 2 + j);
2630 redraw_mask |= REDRAW_DOOR_2;
2631 door_2_done = (a == VXSIZE);
2636 if (game_status == GAME_MODE_MAIN)
2639 if (!(door_state & DOOR_NO_DELAY))
2640 WaitUntilDelayReached(&door_delay, door_delay_value);
2645 if (setup.quick_doors)
2647 StopSound(SND_DOOR_OPENING);
2648 StopSound(SND_DOOR_CLOSING);
2652 if (door_state & DOOR_ACTION_1)
2653 door1 = door_state & DOOR_ACTION_1;
2654 if (door_state & DOOR_ACTION_2)
2655 door2 = door_state & DOOR_ACTION_2;
2657 return (door1 | door2);
2660 void DrawSpecialEditorDoor()
2662 /* draw bigger toolbox window */
2663 BlitBitmap(graphic_info[IMG_GLOBAL_DOOR].bitmap, drawto,
2664 DOOR_GFX_PAGEX7, 0, EXSIZE + 8, 8,
2666 BlitBitmap(graphic_info[IMG_GLOBAL_BORDER].bitmap, drawto,
2667 EX - 4, VY - 4, EXSIZE + 8, EYSIZE - VYSIZE + 4,
2670 redraw_mask |= REDRAW_ALL;
2673 void UndrawSpecialEditorDoor()
2675 /* draw normal tape recorder window */
2676 BlitBitmap(graphic_info[IMG_GLOBAL_BORDER].bitmap, drawto,
2677 EX - 4, EY - 12, EXSIZE + 8, EYSIZE - VYSIZE + 12,
2680 redraw_mask |= REDRAW_ALL;
2684 /* ---------- new tool button stuff ---------------------------------------- */
2686 /* graphic position values for tool buttons */
2687 #define TOOL_BUTTON_YES_XPOS 2
2688 #define TOOL_BUTTON_YES_YPOS 250
2689 #define TOOL_BUTTON_YES_GFX_YPOS 0
2690 #define TOOL_BUTTON_YES_XSIZE 46
2691 #define TOOL_BUTTON_YES_YSIZE 28
2692 #define TOOL_BUTTON_NO_XPOS 52
2693 #define TOOL_BUTTON_NO_YPOS TOOL_BUTTON_YES_YPOS
2694 #define TOOL_BUTTON_NO_GFX_YPOS TOOL_BUTTON_YES_GFX_YPOS
2695 #define TOOL_BUTTON_NO_XSIZE TOOL_BUTTON_YES_XSIZE
2696 #define TOOL_BUTTON_NO_YSIZE TOOL_BUTTON_YES_YSIZE
2697 #define TOOL_BUTTON_CONFIRM_XPOS TOOL_BUTTON_YES_XPOS
2698 #define TOOL_BUTTON_CONFIRM_YPOS TOOL_BUTTON_YES_YPOS
2699 #define TOOL_BUTTON_CONFIRM_GFX_YPOS 30
2700 #define TOOL_BUTTON_CONFIRM_XSIZE 96
2701 #define TOOL_BUTTON_CONFIRM_YSIZE TOOL_BUTTON_YES_YSIZE
2702 #define TOOL_BUTTON_PLAYER_XSIZE 30
2703 #define TOOL_BUTTON_PLAYER_YSIZE 30
2704 #define TOOL_BUTTON_PLAYER_GFX_XPOS 5
2705 #define TOOL_BUTTON_PLAYER_GFX_YPOS 185
2706 #define TOOL_BUTTON_PLAYER_XPOS (5 + TOOL_BUTTON_PLAYER_XSIZE / 2)
2707 #define TOOL_BUTTON_PLAYER_YPOS (215 - TOOL_BUTTON_PLAYER_YSIZE / 2)
2708 #define TOOL_BUTTON_PLAYER1_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2709 + 0 * TOOL_BUTTON_PLAYER_XSIZE)
2710 #define TOOL_BUTTON_PLAYER2_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2711 + 1 * TOOL_BUTTON_PLAYER_XSIZE)
2712 #define TOOL_BUTTON_PLAYER3_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2713 + 0 * TOOL_BUTTON_PLAYER_XSIZE)
2714 #define TOOL_BUTTON_PLAYER4_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2715 + 1 * TOOL_BUTTON_PLAYER_XSIZE)
2716 #define TOOL_BUTTON_PLAYER1_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2717 + 0 * TOOL_BUTTON_PLAYER_YSIZE)
2718 #define TOOL_BUTTON_PLAYER2_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2719 + 0 * TOOL_BUTTON_PLAYER_YSIZE)
2720 #define TOOL_BUTTON_PLAYER3_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2721 + 1 * TOOL_BUTTON_PLAYER_YSIZE)
2722 #define TOOL_BUTTON_PLAYER4_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2723 + 1 * TOOL_BUTTON_PLAYER_YSIZE)
2732 } toolbutton_info[NUM_TOOL_BUTTONS] =
2735 TOOL_BUTTON_YES_XPOS, TOOL_BUTTON_YES_GFX_YPOS,
2736 TOOL_BUTTON_YES_XPOS, TOOL_BUTTON_YES_YPOS,
2737 TOOL_BUTTON_YES_XSIZE, TOOL_BUTTON_YES_YSIZE,
2742 TOOL_BUTTON_NO_XPOS, TOOL_BUTTON_NO_GFX_YPOS,
2743 TOOL_BUTTON_NO_XPOS, TOOL_BUTTON_NO_YPOS,
2744 TOOL_BUTTON_NO_XSIZE, TOOL_BUTTON_NO_YSIZE,
2749 TOOL_BUTTON_CONFIRM_XPOS, TOOL_BUTTON_CONFIRM_GFX_YPOS,
2750 TOOL_BUTTON_CONFIRM_XPOS, TOOL_BUTTON_CONFIRM_YPOS,
2751 TOOL_BUTTON_CONFIRM_XSIZE, TOOL_BUTTON_CONFIRM_YSIZE,
2752 TOOL_CTRL_ID_CONFIRM,
2756 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2757 TOOL_BUTTON_PLAYER1_XPOS, TOOL_BUTTON_PLAYER1_YPOS,
2758 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2759 TOOL_CTRL_ID_PLAYER_1,
2763 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2764 TOOL_BUTTON_PLAYER2_XPOS, TOOL_BUTTON_PLAYER2_YPOS,
2765 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2766 TOOL_CTRL_ID_PLAYER_2,
2770 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2771 TOOL_BUTTON_PLAYER3_XPOS, TOOL_BUTTON_PLAYER3_YPOS,
2772 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2773 TOOL_CTRL_ID_PLAYER_3,
2777 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2778 TOOL_BUTTON_PLAYER4_XPOS, TOOL_BUTTON_PLAYER4_YPOS,
2779 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2780 TOOL_CTRL_ID_PLAYER_4,
2785 void CreateToolButtons()
2789 for (i = 0; i < NUM_TOOL_BUTTONS; i++)
2791 Bitmap *gd_bitmap = graphic_info[IMG_GLOBAL_DOOR].bitmap;
2792 Bitmap *deco_bitmap = None;
2793 int deco_x = 0, deco_y = 0, deco_xpos = 0, deco_ypos = 0;
2794 struct GadgetInfo *gi;
2795 unsigned long event_mask;
2796 int gd_xoffset, gd_yoffset;
2797 int gd_x1, gd_x2, gd_y;
2800 event_mask = GD_EVENT_RELEASED;
2802 gd_xoffset = toolbutton_info[i].xpos;
2803 gd_yoffset = toolbutton_info[i].ypos;
2804 gd_x1 = DOOR_GFX_PAGEX4 + gd_xoffset;
2805 gd_x2 = DOOR_GFX_PAGEX3 + gd_xoffset;
2806 gd_y = DOOR_GFX_PAGEY1 + gd_yoffset;
2808 if (id >= TOOL_CTRL_ID_PLAYER_1 && id <= TOOL_CTRL_ID_PLAYER_4)
2810 int player_nr = id - TOOL_CTRL_ID_PLAYER_1;
2812 getMiniGraphicSource(PLAYER_NR_GFX(IMG_PLAYER_1, player_nr),
2813 &deco_bitmap, &deco_x, &deco_y);
2814 deco_xpos = (toolbutton_info[i].width - MINI_TILEX) / 2;
2815 deco_ypos = (toolbutton_info[i].height - MINI_TILEY) / 2;
2818 gi = CreateGadget(GDI_CUSTOM_ID, id,
2819 GDI_INFO_TEXT, toolbutton_info[i].infotext,
2820 GDI_X, DX + toolbutton_info[i].x,
2821 GDI_Y, DY + toolbutton_info[i].y,
2822 GDI_WIDTH, toolbutton_info[i].width,
2823 GDI_HEIGHT, toolbutton_info[i].height,
2824 GDI_TYPE, GD_TYPE_NORMAL_BUTTON,
2825 GDI_STATE, GD_BUTTON_UNPRESSED,
2826 GDI_DESIGN_UNPRESSED, gd_bitmap, gd_x1, gd_y,
2827 GDI_DESIGN_PRESSED, gd_bitmap, gd_x2, gd_y,
2828 GDI_DECORATION_DESIGN, deco_bitmap, deco_x, deco_y,
2829 GDI_DECORATION_POSITION, deco_xpos, deco_ypos,
2830 GDI_DECORATION_SIZE, MINI_TILEX, MINI_TILEY,
2831 GDI_DECORATION_SHIFTING, 1, 1,
2832 GDI_EVENT_MASK, event_mask,
2833 GDI_CALLBACK_ACTION, HandleToolButtons,
2837 Error(ERR_EXIT, "cannot create gadget");
2839 tool_gadget[id] = gi;
2843 void FreeToolButtons()
2847 for (i = 0; i < NUM_TOOL_BUTTONS; i++)
2848 FreeGadget(tool_gadget[i]);
2851 static void UnmapToolButtons()
2855 for (i = 0; i < NUM_TOOL_BUTTONS; i++)
2856 UnmapGadget(tool_gadget[i]);
2859 static void HandleToolButtons(struct GadgetInfo *gi)
2861 request_gadget_id = gi->custom_id;
2864 int get_next_element(int element)
2868 case EL_QUICKSAND_FILLING: return EL_QUICKSAND_FULL;
2869 case EL_QUICKSAND_EMPTYING: return EL_QUICKSAND_EMPTY;
2870 case EL_MAGIC_WALL_FILLING: return EL_MAGIC_WALL_FULL;
2871 case EL_MAGIC_WALL_EMPTYING: return EL_MAGIC_WALL_ACTIVE;
2872 case EL_BD_MAGIC_WALL_FILLING: return EL_BD_MAGIC_WALL_FULL;
2873 case EL_BD_MAGIC_WALL_EMPTYING: return EL_BD_MAGIC_WALL_ACTIVE;
2874 case EL_AMOEBA_DROPPING: return EL_AMOEBA_WET;
2876 default: return element;
2880 int el_act_dir2img(int element, int action, int direction)
2882 element = GFX_ELEMENT(element);
2883 direction = MV_DIR_BIT(direction);
2885 return element_info[element].direction_graphic[action][direction];
2888 static int el_act_dir2crm(int element, int action, int direction)
2890 element = GFX_ELEMENT(element);
2891 direction = MV_DIR_BIT(direction);
2893 return element_info[element].direction_crumbled[action][direction];
2896 int el_act2img(int element, int action)
2898 element = GFX_ELEMENT(element);
2900 return element_info[element].graphic[action];
2903 int el_act2crm(int element, int action)
2905 element = GFX_ELEMENT(element);
2907 return element_info[element].crumbled[action];
2910 int el_dir2img(int element, int direction)
2912 element = GFX_ELEMENT(element);
2914 return el_act_dir2img(element, ACTION_DEFAULT, direction);
2917 int el2baseimg(int element)
2919 return element_info[element].graphic[ACTION_DEFAULT];
2922 int el2img(int element)
2924 element = GFX_ELEMENT(element);
2926 return element_info[element].graphic[ACTION_DEFAULT];
2929 int el2edimg(int element)
2931 element = GFX_ELEMENT(element);
2933 return element_info[element].special_graphic[GFX_SPECIAL_ARG_EDITOR];
2936 int el2preimg(int element)
2938 element = GFX_ELEMENT(element);
2940 return element_info[element].special_graphic[GFX_SPECIAL_ARG_PREVIEW];