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 void DumpTile(int x, int y)
49 printf("Field Info: SCREEN(%d, %d), LEVEL(%d, %d)\n", sx, sy, x, y);
52 if (!IN_LEV_FIELD(x, y))
54 printf("(not in level field)\n");
60 printf(" Feld: %d ['%s']\n", Feld[x][y],
61 element_info[Feld[x][y]].token_name);
62 printf(" Back: %d\n", Back[x][y]);
63 printf(" Store: %d\n", Store[x][y]);
64 printf(" Store2: %d\n", Store2[x][y]);
65 printf(" StorePlayer: %d\n", StorePlayer[x][y]);
66 printf(" MovPos: %d\n", MovPos[x][y]);
67 printf(" MovDir: %d\n", MovDir[x][y]);
68 printf(" MovDelay: %d\n", MovDelay[x][y]);
69 printf(" ChangeDelay: %d\n", ChangeDelay[x][y]);
70 printf(" GfxElement: %d\n", GfxElement[x][y]);
71 printf(" GfxAction: %d\n", GfxAction[x][y]);
72 printf(" GfxFrame: %d\n", GfxFrame[x][y]);
76 void SetDrawtoField(int mode)
78 if (mode == DRAW_BUFFERED && setup.soft_scrolling)
89 drawto_field = fieldbuffer;
91 else /* DRAW_DIRECT, DRAW_BACKBUFFER */
102 drawto_field = (mode == DRAW_DIRECT ? window : backbuffer);
106 void RedrawPlayfield(boolean force_redraw, int x, int y, int width, int height)
108 if (game_status == GAME_MODE_PLAYING && !game.envelope_active)
114 width = gfx.sxsize + 2 * TILEX;
115 height = gfx.sysize + 2 * TILEY;
118 if (force_redraw || setup.direct_draw)
121 int x1 = (x - SX) / TILEX, y1 = (y - SY) / TILEY;
122 int x2 = (x - SX + width) / TILEX, y2 = (y - SY + height) / TILEY;
124 if (setup.direct_draw)
125 SetDrawtoField(DRAW_BACKBUFFER);
127 for (xx = BX1; xx <= BX2; xx++)
128 for (yy = BY1; yy <= BY2; yy++)
129 if (xx >= x1 && xx <= x2 && yy >= y1 && yy <= y2)
130 DrawScreenField(xx, yy);
133 if (setup.direct_draw)
134 SetDrawtoField(DRAW_DIRECT);
137 if (setup.soft_scrolling)
139 int fx = FX, fy = FY;
141 fx += (ScreenMovDir & (MV_LEFT|MV_RIGHT) ? ScreenGfxPos : 0);
142 fy += (ScreenMovDir & (MV_UP|MV_DOWN) ? ScreenGfxPos : 0);
144 BlitBitmap(fieldbuffer, backbuffer, fx,fy, SXSIZE,SYSIZE, SX,SY);
148 BlitBitmap(drawto, window, x, y, width, height, x, y);
154 DrawBuffer *buffer = (drawto_field == window ? backbuffer : drawto_field);
156 if (setup.direct_draw && game_status == GAME_MODE_PLAYING)
157 redraw_mask &= ~REDRAW_MAIN;
159 if (redraw_mask & REDRAW_TILES && redraw_tiles > REDRAWTILES_THRESHOLD)
160 redraw_mask |= REDRAW_FIELD;
162 if (redraw_mask & REDRAW_FIELD)
163 redraw_mask &= ~REDRAW_TILES;
165 if (redraw_mask == REDRAW_NONE)
168 if (global.fps_slowdown && game_status == GAME_MODE_PLAYING)
170 static boolean last_frame_skipped = FALSE;
171 boolean skip_even_when_not_scrolling = TRUE;
172 boolean just_scrolling = (ScreenMovDir != 0);
173 boolean verbose = FALSE;
175 if (global.fps_slowdown_factor > 1 &&
176 (FrameCounter % global.fps_slowdown_factor) &&
177 (just_scrolling || skip_even_when_not_scrolling))
179 redraw_mask &= ~REDRAW_MAIN;
181 last_frame_skipped = TRUE;
184 printf("FRAME SKIPPED\n");
188 if (last_frame_skipped)
189 redraw_mask |= REDRAW_FIELD;
191 last_frame_skipped = FALSE;
194 printf("frame not skipped\n");
198 /* synchronize X11 graphics at this point; if we would synchronize the
199 display immediately after the buffer switching (after the XFlush),
200 this could mean that we have to wait for the graphics to complete,
201 although we could go on doing calculations for the next frame */
205 if (redraw_mask & REDRAW_ALL)
207 BlitBitmap(backbuffer, window, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
211 if (redraw_mask & REDRAW_FIELD)
213 if (game_status != GAME_MODE_PLAYING ||
214 redraw_mask & REDRAW_FROM_BACKBUFFER)
216 BlitBitmap(backbuffer, window,
217 REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE, REAL_SX, REAL_SY);
221 int fx = FX, fy = FY;
223 if (setup.soft_scrolling)
225 fx += (ScreenMovDir & (MV_LEFT | MV_RIGHT) ? ScreenGfxPos : 0);
226 fy += (ScreenMovDir & (MV_UP | MV_DOWN) ? ScreenGfxPos : 0);
229 if (setup.soft_scrolling ||
230 ABS(ScreenMovPos) + ScrollStepSize == TILEX ||
231 ABS(ScreenMovPos) == ScrollStepSize ||
232 redraw_tiles > REDRAWTILES_THRESHOLD)
234 BlitBitmap(buffer, window, fx, fy, SXSIZE, SYSIZE, SX, SY);
238 printf("redrawing all (ScreenGfxPos == %d) because %s\n",
240 (setup.soft_scrolling ?
241 "setup.soft_scrolling" :
242 ABS(ScreenGfxPos) + ScrollStepSize == TILEX ?
243 "ABS(ScreenGfxPos) + ScrollStepSize == TILEX" :
244 ABS(ScreenGfxPos) == ScrollStepSize ?
245 "ABS(ScreenGfxPos) == ScrollStepSize" :
246 "redraw_tiles > REDRAWTILES_THRESHOLD"));
252 redraw_mask &= ~REDRAW_MAIN;
255 if (redraw_mask & REDRAW_DOORS)
257 if (redraw_mask & REDRAW_DOOR_1)
258 BlitBitmap(backbuffer, window, DX, DY, DXSIZE, DYSIZE, DX, DY);
260 if (redraw_mask & REDRAW_DOOR_2)
263 if ((redraw_mask & REDRAW_DOOR_2) == REDRAW_DOOR_2)
265 BlitBitmap(backbuffer, window, VX, VY, VXSIZE, VYSIZE, VX, VY);
269 if (redraw_mask & REDRAW_VIDEO_1)
270 BlitBitmap(backbuffer, window,
271 VX + VIDEO_DISPLAY1_XPOS, VY + VIDEO_DISPLAY1_YPOS,
272 VIDEO_DISPLAY_XSIZE, VIDEO_DISPLAY_YSIZE,
273 VX + VIDEO_DISPLAY1_XPOS, VY + VIDEO_DISPLAY1_YPOS);
274 if (redraw_mask & REDRAW_VIDEO_2)
275 BlitBitmap(backbuffer, window,
276 VX + VIDEO_DISPLAY2_XPOS, VY + VIDEO_DISPLAY2_YPOS,
277 VIDEO_DISPLAY_XSIZE, VIDEO_DISPLAY_YSIZE,
278 VX + VIDEO_DISPLAY2_XPOS, VY + VIDEO_DISPLAY2_YPOS);
279 if (redraw_mask & REDRAW_VIDEO_3)
280 BlitBitmap(backbuffer, window,
281 VX + VIDEO_CONTROL_XPOS, VY + VIDEO_CONTROL_YPOS,
282 VIDEO_CONTROL_XSIZE, VIDEO_CONTROL_YSIZE,
283 VX + VIDEO_CONTROL_XPOS, VY + VIDEO_CONTROL_YPOS);
288 if (redraw_mask & REDRAW_DOOR_3)
289 BlitBitmap(backbuffer, window, EX, EY, EXSIZE, EYSIZE, EX, EY);
291 redraw_mask &= ~REDRAW_DOORS;
294 if (redraw_mask & REDRAW_MICROLEVEL)
296 BlitBitmap(backbuffer, window, SX, SY + 10 * TILEY, SXSIZE, 7 * TILEY,
297 SX, SY + 10 * TILEY);
299 redraw_mask &= ~REDRAW_MICROLEVEL;
302 if (redraw_mask & REDRAW_TILES)
304 for (x = 0; x < SCR_FIELDX; x++)
305 for (y = 0 ; y < SCR_FIELDY; y++)
306 if (redraw[redraw_x1 + x][redraw_y1 + y])
307 BlitBitmap(buffer, window,
308 FX + x * TILEX, FY + y * TILEY, TILEX, TILEY,
309 SX + x * TILEX, SY + y * TILEY);
312 if (redraw_mask & REDRAW_FPS) /* display frames per second */
317 sprintf(info1, " (only every %d. frame)", global.fps_slowdown_factor);
318 if (!global.fps_slowdown)
321 sprintf(text, "%.1f fps%s", global.frames_per_second, info1);
322 DrawTextExt(window, SX, SY, text, FONT_TEXT_2, BLIT_OPAQUE);
327 for (x = 0; x < MAX_BUF_XSIZE; x++)
328 for (y = 0; y < MAX_BUF_YSIZE; y++)
331 redraw_mask = REDRAW_NONE;
337 long fading_delay = 300;
339 if (setup.fading && (redraw_mask & REDRAW_FIELD))
346 ClearRectangle(window, REAL_SX,REAL_SY,FULL_SXSIZE,FULL_SYSIZE);
349 for (i = 0; i < 2 * FULL_SYSIZE; i++)
351 for (y = 0; y < FULL_SYSIZE; y++)
353 BlitBitmap(backbuffer, window,
354 REAL_SX,REAL_SY+i, FULL_SXSIZE,1, REAL_SX,REAL_SY+i);
362 for (i = 1; i < FULL_SYSIZE; i+=2)
363 BlitBitmap(backbuffer, window,
364 REAL_SX,REAL_SY+i, FULL_SXSIZE,1, REAL_SX,REAL_SY+i);
370 SetClipOrigin(clip_gc[PIX_FADEMASK], 0, 0);
371 BlitBitmapMasked(backbuffer, window,
372 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE,
377 SetClipOrigin(clip_gc[PIX_FADEMASK], -1, -1);
378 BlitBitmapMasked(backbuffer, window,
379 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE,
384 SetClipOrigin(clip_gc[PIX_FADEMASK], 0, -1);
385 BlitBitmapMasked(backbuffer, window,
386 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE,
391 SetClipOrigin(clip_gc[PIX_FADEMASK], -1, 0);
392 BlitBitmapMasked(backbuffer, window,
393 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE,
398 redraw_mask &= ~REDRAW_MAIN;
405 void SetMainBackgroundImage(int graphic)
407 SetMainBackgroundBitmap(graphic == IMG_UNDEFINED ? NULL :
408 graphic_info[graphic].bitmap ?
409 graphic_info[graphic].bitmap :
410 graphic_info[IMG_BACKGROUND].bitmap);
413 void SetDoorBackgroundImage(int graphic)
415 SetDoorBackgroundBitmap(graphic == IMG_UNDEFINED ? NULL :
416 graphic_info[graphic].bitmap ?
417 graphic_info[graphic].bitmap :
418 graphic_info[IMG_BACKGROUND].bitmap);
421 void DrawBackground(int dest_x, int dest_y, int width, int height)
423 ClearRectangleOnBackground(backbuffer, dest_x, dest_y, width, height);
425 redraw_mask |= REDRAW_FIELD;
430 DrawBackground(REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE);
432 if (setup.soft_scrolling && game_status == GAME_MODE_PLAYING)
434 ClearRectangle(fieldbuffer, 0, 0, FXSIZE, FYSIZE);
435 SetDrawtoField(DRAW_BUFFERED);
438 SetDrawtoField(DRAW_BACKBUFFER);
440 if (setup.direct_draw && game_status == GAME_MODE_PLAYING)
442 ClearRectangle(window, REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE);
443 SetDrawtoField(DRAW_DIRECT);
447 void MarkTileDirty(int x, int y)
449 int xx = redraw_x1 + x;
450 int yy = redraw_y1 + y;
455 redraw[xx][yy] = TRUE;
456 redraw_mask |= REDRAW_TILES;
459 void SetBorderElement()
463 BorderElement = EL_EMPTY;
465 for (y = 0; y < lev_fieldy && BorderElement == EL_EMPTY; y++)
467 for (x = 0; x < lev_fieldx; x++)
469 if (!IS_INDESTRUCTIBLE(Feld[x][y]))
470 BorderElement = EL_STEELWALL;
472 if (y != 0 && y != lev_fieldy - 1 && x != lev_fieldx - 1)
478 void SetRandomAnimationValue(int x, int y)
480 gfx.anim_random_frame = GfxRandom[x][y];
483 inline int getGraphicAnimationFrame(int graphic, int sync_frame)
485 /* animation synchronized with global frame counter, not move position */
486 if (graphic_info[graphic].anim_global_sync || sync_frame < 0)
487 sync_frame = FrameCounter;
489 return getAnimationFrame(graphic_info[graphic].anim_frames,
490 graphic_info[graphic].anim_delay,
491 graphic_info[graphic].anim_mode,
492 graphic_info[graphic].anim_start_frame,
496 inline void DrawGraphicAnimationExt(DrawBuffer *dst_bitmap, int x, int y,
497 int graphic, int sync_frame, int mask_mode)
499 int frame = getGraphicAnimationFrame(graphic, sync_frame);
501 if (mask_mode == USE_MASKING)
502 DrawGraphicThruMaskExt(dst_bitmap, x, y, graphic, frame);
504 DrawGraphicExt(dst_bitmap, x, y, graphic, frame);
507 inline void DrawGraphicAnimation(int x, int y, int graphic)
509 int lx = LEVELX(x), ly = LEVELY(y);
511 if (!IN_SCR_FIELD(x, y))
514 DrawGraphicAnimationExt(drawto_field, FX + x * TILEX, FY + y * TILEY,
515 graphic, GfxFrame[lx][ly], NO_MASKING);
519 void DrawLevelGraphicAnimation(int x, int y, int graphic)
521 DrawGraphicAnimation(SCREENX(x), SCREENY(y), graphic);
524 void DrawLevelElementAnimation(int x, int y, int element)
527 int graphic = el_act_dir2img(element, GfxAction[x][y], GfxDir[x][y]);
529 DrawGraphicAnimation(SCREENX(x), SCREENY(y), graphic);
531 DrawGraphicAnimation(SCREENX(x), SCREENY(y), el2img(element));
535 inline void DrawLevelGraphicAnimationIfNeeded(int x, int y, int graphic)
537 int sx = SCREENX(x), sy = SCREENY(y);
539 if (!IN_LEV_FIELD(x, y) || !IN_SCR_FIELD(sx, sy))
542 if (!IS_NEW_FRAME(GfxFrame[x][y], graphic))
545 DrawGraphicAnimation(sx, sy, graphic);
547 if (GFX_CRUMBLED(Feld[x][y]))
548 DrawLevelFieldCrumbledSand(x, y);
551 void DrawLevelElementAnimationIfNeeded(int x, int y, int element)
553 int sx = SCREENX(x), sy = SCREENY(y);
556 if (!IN_LEV_FIELD(x, y) || !IN_SCR_FIELD(sx, sy))
559 graphic = el_act_dir2img(element, GfxAction[x][y], GfxDir[x][y]);
561 if (!IS_NEW_FRAME(GfxFrame[x][y], graphic))
564 DrawGraphicAnimation(sx, sy, graphic);
566 if (GFX_CRUMBLED(element))
567 DrawLevelFieldCrumbledSand(x, y);
570 static int getPlayerGraphic(struct PlayerInfo *player, int move_dir)
572 if (player->use_murphy_graphic)
574 /* this works only because currently only one player can be "murphy" ... */
575 static int last_horizontal_dir = MV_LEFT;
576 int graphic = el_act_dir2img(EL_SP_MURPHY, player->GfxAction, move_dir);
578 if (move_dir == MV_LEFT || move_dir == MV_RIGHT)
579 last_horizontal_dir = move_dir;
581 if (graphic == IMG_SP_MURPHY) /* undefined => use special graphic */
583 int direction = (player->is_snapping ? move_dir : last_horizontal_dir);
585 graphic = el_act_dir2img(EL_SP_MURPHY, player->GfxAction, direction);
591 return el_act_dir2img(player->element_nr, player->GfxAction, move_dir);
594 static boolean equalGraphics(int graphic1, int graphic2)
596 struct GraphicInfo *g1 = &graphic_info[graphic1];
597 struct GraphicInfo *g2 = &graphic_info[graphic2];
599 return (g1->bitmap == g2->bitmap &&
600 g1->src_x == g2->src_x &&
601 g1->src_y == g2->src_y &&
602 g1->anim_frames == g2->anim_frames &&
603 g1->anim_delay == g2->anim_delay &&
604 g1->anim_mode == g2->anim_mode);
607 void DrawAllPlayers()
611 for (i = 0; i < MAX_PLAYERS; i++)
612 if (stored_player[i].active)
613 DrawPlayer(&stored_player[i]);
616 void DrawPlayerField(int x, int y)
618 if (!IS_PLAYER(x, y))
621 DrawPlayer(PLAYERINFO(x, y));
624 void DrawPlayer(struct PlayerInfo *player)
628 int move_dir = player->MovDir;
630 int last_jx = player->last_jx;
631 int last_jy = player->last_jy;
632 int next_jx = jx + (jx - last_jx);
633 int next_jy = jy + (jy - last_jy);
634 boolean player_is_moving = (last_jx != jx || last_jy != jy ? TRUE : FALSE);
636 int dx = (move_dir == MV_LEFT ? -1 : move_dir == MV_RIGHT ? +1 : 0);
637 int dy = (move_dir == MV_UP ? -1 : move_dir == MV_DOWN ? +1 : 0);
638 int last_jx = (player->is_moving ? jx - dx : jx);
639 int last_jy = (player->is_moving ? jy - dy : jy);
640 int next_jx = jx + dx;
641 int next_jy = jy + dy;
642 boolean player_is_moving = (player->MovPos ? TRUE : FALSE);
644 int sx = SCREENX(jx), sy = SCREENY(jy);
645 int sxx = 0, syy = 0;
646 int element = Feld[jx][jy], last_element = Feld[last_jx][last_jy];
648 int action = ACTION_DEFAULT;
649 int last_player_graphic = getPlayerGraphic(player, move_dir);
650 int last_player_frame = player->Frame;
653 if (!player->active || !IN_SCR_FIELD(SCREENX(last_jx), SCREENY(last_jy)))
657 if (!IN_LEV_FIELD(jx, jy))
659 printf("DrawPlayerField(): x = %d, y = %d\n",jx,jy);
660 printf("DrawPlayerField(): sx = %d, sy = %d\n",sx,sy);
661 printf("DrawPlayerField(): This should never happen!\n");
666 if (element == EL_EXPLOSION)
669 action = (player->is_pushing ? ACTION_PUSHING :
670 player->is_digging ? ACTION_DIGGING :
671 player->is_collecting ? ACTION_COLLECTING :
672 player->is_moving ? ACTION_MOVING :
673 player->is_snapping ? ACTION_SNAPPING :
674 player->is_dropping ? ACTION_DROPPING :
675 player->is_waiting ? player->action_waiting : ACTION_DEFAULT);
677 InitPlayerGfxAnimation(player, action, move_dir);
679 /* ----------------------------------------------------------------------- */
680 /* draw things in the field the player is leaving, if needed */
681 /* ----------------------------------------------------------------------- */
684 if (player->is_moving)
686 if (player_is_moving)
689 if (Back[last_jx][last_jy] && IS_DRAWABLE(last_element))
691 DrawLevelElement(last_jx, last_jy, Back[last_jx][last_jy]);
693 if (last_element == EL_DYNAMITE_ACTIVE ||
694 last_element == EL_SP_DISK_RED_ACTIVE)
695 DrawDynamite(last_jx, last_jy);
697 DrawLevelFieldThruMask(last_jx, last_jy);
699 else if (last_element == EL_DYNAMITE_ACTIVE ||
700 last_element == EL_SP_DISK_RED_ACTIVE)
701 DrawDynamite(last_jx, last_jy);
703 DrawLevelField(last_jx, last_jy);
705 if (player->is_pushing && IN_SCR_FIELD(SCREENX(next_jx), SCREENY(next_jy)))
706 DrawLevelElement(next_jx, next_jy, EL_EMPTY);
709 if (!IN_SCR_FIELD(sx, sy))
712 if (setup.direct_draw)
713 SetDrawtoField(DRAW_BUFFERED);
715 /* ----------------------------------------------------------------------- */
716 /* draw things behind the player, if needed */
717 /* ----------------------------------------------------------------------- */
720 DrawLevelElement(jx, jy, Back[jx][jy]);
721 else if (IS_ACTIVE_BOMB(element))
722 DrawLevelElement(jx, jy, EL_EMPTY);
725 if (player_is_moving && GfxElement[jx][jy] != EL_UNDEFINED)
727 if (GFX_CRUMBLED(GfxElement[jx][jy]))
728 DrawLevelFieldCrumbledSandDigging(jx, jy, move_dir, player->StepFrame);
731 int old_element = GfxElement[jx][jy];
732 int old_graphic = el_act_dir2img(old_element, action, move_dir);
733 int frame = getGraphicAnimationFrame(old_graphic, player->StepFrame);
735 DrawGraphic(sx, sy, old_graphic, frame);
740 GfxElement[jx][jy] = EL_UNDEFINED;
742 DrawLevelField(jx, jy);
746 /* ----------------------------------------------------------------------- */
747 /* draw player himself */
748 /* ----------------------------------------------------------------------- */
752 graphic = getPlayerGraphic(player, move_dir);
754 /* in the case of changed player action or direction, prevent the current
755 animation frame from being restarted for identical animations */
756 if (player->Frame == 0 && equalGraphics(graphic, last_player_graphic))
757 player->Frame = last_player_frame;
761 if (player->use_murphy_graphic)
763 static int last_horizontal_dir = MV_LEFT;
765 if (move_dir == MV_LEFT || move_dir == MV_RIGHT)
766 last_horizontal_dir = move_dir;
768 graphic = el_act_dir2img(EL_SP_MURPHY, player->GfxAction, move_dir);
770 if (graphic == IMG_SP_MURPHY) /* undefined => use special graphic */
772 int direction = (player->is_snapping ? move_dir : last_horizontal_dir);
774 graphic = el_act_dir2img(EL_SP_MURPHY, player->GfxAction, direction);
778 graphic = el_act_dir2img(player->element_nr, player->GfxAction, move_dir);
782 frame = getGraphicAnimationFrame(graphic, player->Frame);
786 if (move_dir == MV_LEFT || move_dir == MV_RIGHT)
787 sxx = player->GfxPos;
789 syy = player->GfxPos;
792 if (!setup.soft_scrolling && ScreenMovPos)
795 DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, frame, NO_CUTTING);
797 if (SHIELD_ON(player))
799 int graphic = (player->shield_deadly_time_left ? IMG_SHIELD_DEADLY_ACTIVE :
800 IMG_SHIELD_NORMAL_ACTIVE);
801 int frame = getGraphicAnimationFrame(graphic, -1);
803 DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, frame, NO_CUTTING);
806 /* ----------------------------------------------------------------------- */
807 /* draw things the player is pushing, if needed */
808 /* ----------------------------------------------------------------------- */
811 printf("::: %d, %d [%d, %d] [%d]\n",
812 player->is_pushing, player_is_moving, player->GfxAction,
813 player->is_moving, player_is_moving);
817 if (player->is_pushing && player->is_moving)
819 if (player->is_pushing && player_is_moving)
822 int px = SCREENX(next_jx), py = SCREENY(next_jy);
824 if (Back[next_jx][next_jy])
825 DrawLevelElement(next_jx, next_jy, Back[next_jx][next_jy]);
827 if ((sxx || syy) && element == EL_SOKOBAN_OBJECT)
828 DrawGraphicShiftedThruMask(px, py, sxx, syy, IMG_SOKOBAN_OBJECT, 0,
832 int element = MovingOrBlocked2Element(next_jx, next_jy);
833 int graphic = el_act_dir2img(element, ACTION_PUSHING, move_dir);
835 int frame = getGraphicAnimationFrame(graphic, player->StepFrame);
837 int frame = getGraphicAnimationFrame(graphic, player->Frame);
840 DrawGraphicShifted(px, py, sxx, syy, graphic, frame,
841 NO_CUTTING, NO_MASKING);
845 /* ----------------------------------------------------------------------- */
846 /* draw things in front of player (active dynamite or dynabombs) */
847 /* ----------------------------------------------------------------------- */
849 if (IS_ACTIVE_BOMB(element))
851 graphic = el2img(element);
852 frame = getGraphicAnimationFrame(graphic, GfxFrame[jx][jy]);
854 if (game.emulation == EMU_SUPAPLEX)
855 DrawGraphic(sx, sy, IMG_SP_DISK_RED, frame);
857 DrawGraphicThruMask(sx, sy, graphic, frame);
860 if (player_is_moving && last_element == EL_EXPLOSION)
862 int graphic = el_act2img(GfxElement[last_jx][last_jy], ACTION_EXPLODING);
863 int delay = (game.emulation == EMU_SUPAPLEX ? 3 : 2);
864 int phase = ExplodePhase[last_jx][last_jy] - 1;
865 int frame = getGraphicAnimationFrame(graphic, phase - delay);
868 DrawGraphicThruMask(SCREENX(last_jx), SCREENY(last_jy), graphic, frame);
871 /* ----------------------------------------------------------------------- */
872 /* draw elements the player is just walking/passing through/under */
873 /* ----------------------------------------------------------------------- */
875 /* handle the field the player is leaving ... */
876 if (player_is_moving && IS_ACCESSIBLE_INSIDE(last_element))
877 DrawLevelField(last_jx, last_jy);
878 else if (player_is_moving && IS_ACCESSIBLE_UNDER(last_element))
879 DrawLevelFieldThruMask(last_jx, last_jy);
882 /* !!! I have forgotton what this should be good for !!! */
883 /* !!! causes player being visible when pushing from within tubes !!! */
884 if (!player->is_pushing)
887 /* ... and the field the player is entering */
888 if (IS_ACCESSIBLE_INSIDE(element))
889 DrawLevelField(jx, jy);
890 else if (IS_ACCESSIBLE_UNDER(element))
891 DrawLevelFieldThruMask(jx, jy);
894 if (setup.direct_draw)
896 int dest_x = SX + SCREENX(MIN(jx, last_jx)) * TILEX;
897 int dest_y = SY + SCREENY(MIN(jy, last_jy)) * TILEY;
898 int x_size = TILEX * (1 + ABS(jx - last_jx));
899 int y_size = TILEY * (1 + ABS(jy - last_jy));
901 BlitBitmap(drawto_field, window,
902 dest_x, dest_y, x_size, y_size, dest_x, dest_y);
903 SetDrawtoField(DRAW_DIRECT);
906 MarkTileDirty(sx, sy);
909 void getGraphicSource(int graphic, int frame, Bitmap **bitmap, int *x, int *y)
911 struct GraphicInfo *g = &graphic_info[graphic];
915 if (g->offset_y == 0) /* frames are ordered horizontally */
917 int max_width = g->anim_frames_per_line * g->width;
919 *x = (g->src_x + frame * g->offset_x) % max_width;
920 *y = g->src_y + (g->src_x + frame * g->offset_x) / max_width * g->height;
922 else if (g->offset_x == 0) /* frames are ordered vertically */
924 int max_height = g->anim_frames_per_line * g->height;
926 *x = g->src_x + (g->src_y + frame * g->offset_y) / max_height * g->width;
927 *y = (g->src_y + frame * g->offset_y) % max_height;
929 else /* frames are ordered diagonally */
931 *x = g->src_x + frame * g->offset_x;
932 *y = g->src_y + frame * g->offset_y;
936 void DrawGraphic(int x, int y, int graphic, int frame)
939 if (!IN_SCR_FIELD(x, y))
941 printf("DrawGraphic(): x = %d, y = %d, graphic = %d\n", x, y, graphic);
942 printf("DrawGraphic(): This should never happen!\n");
947 DrawGraphicExt(drawto_field, FX + x * TILEX, FY + y * TILEY, graphic, frame);
951 void DrawGraphicExt(DrawBuffer *dst_bitmap, int x, int y, int graphic,
957 getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
958 BlitBitmap(src_bitmap, dst_bitmap, src_x, src_y, TILEX, TILEY, x, y);
961 void DrawGraphicThruMask(int x, int y, int graphic, int frame)
964 if (!IN_SCR_FIELD(x, y))
966 printf("DrawGraphicThruMask(): x = %d,y = %d, graphic = %d\n",x,y,graphic);
967 printf("DrawGraphicThruMask(): This should never happen!\n");
972 DrawGraphicThruMaskExt(drawto_field, FX + x * TILEX, FY + y *TILEY, graphic,
977 void DrawGraphicThruMaskExt(DrawBuffer *d, int dest_x, int dest_y, int graphic,
985 getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
986 drawing_gc = src_bitmap->stored_clip_gc;
988 GC drawing_gc = src_bitmap->stored_clip_gc;
989 Bitmap *src_bitmap = graphic_info[graphic].bitmap;
990 int src_x = graphic_info[graphic].src_x;
991 int src_y = graphic_info[graphic].src_y;
992 int offset_x = graphic_info[graphic].offset_x;
993 int offset_y = graphic_info[graphic].offset_y;
995 src_x += frame * offset_x;
996 src_y += frame * offset_y;
1000 SetClipOrigin(src_bitmap, drawing_gc, dest_x - src_x, dest_y - src_y);
1001 BlitBitmapMasked(src_bitmap, d, src_x, src_y, TILEX, TILEY, dest_x, dest_y);
1004 void DrawMiniGraphic(int x, int y, int graphic)
1006 DrawMiniGraphicExt(drawto, SX + x * MINI_TILEX,SY + y * MINI_TILEY, graphic);
1007 MarkTileDirty(x / 2, y / 2);
1010 void getMiniGraphicSource(int graphic, Bitmap **bitmap, int *x, int *y)
1012 struct GraphicInfo *g = &graphic_info[graphic];
1013 int mini_startx = 0;
1014 int mini_starty = g->bitmap->height * 2 / 3;
1016 *bitmap = g->bitmap;
1017 *x = mini_startx + g->src_x / 2;
1018 *y = mini_starty + g->src_y / 2;
1021 void DrawMiniGraphicExt(DrawBuffer *d, int x, int y, int graphic)
1026 getMiniGraphicSource(graphic, &src_bitmap, &src_x, &src_y);
1027 BlitBitmap(src_bitmap, d, src_x, src_y, MINI_TILEX, MINI_TILEY, x, y);
1030 void DrawGraphicShifted(int x, int y, int dx, int dy, int graphic, int frame,
1031 int cut_mode, int mask_mode)
1036 int width = TILEX, height = TILEY;
1042 DrawGraphic(x, y, graphic, frame);
1046 if (dx || dy) /* shifted graphic */
1048 if (x < BX1) /* object enters playfield from the left */
1055 else if (x > BX2) /* object enters playfield from the right */
1061 else if (x==BX1 && dx < 0) /* object leaves playfield to the left */
1067 else if (x==BX2 && dx > 0) /* object leaves playfield to the right */
1069 else if (dx) /* general horizontal movement */
1070 MarkTileDirty(x + SIGN(dx), y);
1072 if (y < BY1) /* object enters playfield from the top */
1074 if (cut_mode==CUT_BELOW) /* object completely above top border */
1082 else if (y > BY2) /* object enters playfield from the bottom */
1088 else if (y==BY1 && dy < 0) /* object leaves playfield to the top */
1094 else if (dy > 0 && cut_mode == CUT_ABOVE)
1096 if (y == BY2) /* object completely above bottom border */
1102 MarkTileDirty(x, y + 1);
1103 } /* object leaves playfield to the bottom */
1104 else if (dy > 0 && (y == BY2 || cut_mode == CUT_BELOW))
1106 else if (dy) /* general vertical movement */
1107 MarkTileDirty(x, y + SIGN(dy));
1111 getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
1113 src_bitmap = graphic_info[graphic].bitmap;
1114 src_x = graphic_info[graphic].src_x;
1115 src_y = graphic_info[graphic].src_y;
1116 offset_x = graphic_info[graphic].offset_x;
1117 offset_y = graphic_info[graphic].offset_y;
1119 src_x += frame * offset_x;
1120 src_y += frame * offset_y;
1123 drawing_gc = src_bitmap->stored_clip_gc;
1128 dest_x = FX + x * TILEX + dx;
1129 dest_y = FY + y * TILEY + dy;
1132 if (!IN_SCR_FIELD(x,y))
1134 printf("DrawGraphicShifted(): x = %d, y = %d, graphic = %d\n",x,y,graphic);
1135 printf("DrawGraphicShifted(): This should never happen!\n");
1140 if (mask_mode == USE_MASKING)
1142 SetClipOrigin(src_bitmap, drawing_gc, dest_x - src_x, dest_y - src_y);
1143 BlitBitmapMasked(src_bitmap, drawto_field, src_x, src_y, width, height,
1147 BlitBitmap(src_bitmap, drawto_field, src_x, src_y, width, height,
1150 MarkTileDirty(x, y);
1153 void DrawGraphicShiftedThruMask(int x, int y, int dx, int dy, int graphic,
1154 int frame, int cut_mode)
1156 DrawGraphicShifted(x, y, dx, dy, graphic, frame, cut_mode, USE_MASKING);
1159 void DrawScreenElementExt(int x, int y, int dx, int dy, int element,
1160 int cut_mode, int mask_mode)
1162 int lx = LEVELX(x), ly = LEVELY(y);
1166 if (IN_LEV_FIELD(lx, ly))
1168 SetRandomAnimationValue(lx, ly);
1170 graphic = el_act_dir2img(element, GfxAction[lx][ly], GfxDir[lx][ly]);
1171 frame = getGraphicAnimationFrame(graphic, GfxFrame[lx][ly]);
1173 else /* border element */
1175 graphic = el2img(element);
1176 frame = getGraphicAnimationFrame(graphic, -1);
1179 if (element == EL_EXPANDABLE_WALL)
1181 boolean left_stopped = FALSE, right_stopped = FALSE;
1183 if (!IN_LEV_FIELD(lx - 1, ly) || IS_WALL(Feld[lx - 1][ly]))
1184 left_stopped = TRUE;
1185 if (!IN_LEV_FIELD(lx + 1, ly) || IS_WALL(Feld[lx + 1][ly]))
1186 right_stopped = TRUE;
1188 if (left_stopped && right_stopped)
1190 else if (left_stopped)
1192 graphic = IMG_EXPANDABLE_WALL_GROWING_RIGHT;
1193 frame = graphic_info[graphic].anim_frames - 1;
1195 else if (right_stopped)
1197 graphic = IMG_EXPANDABLE_WALL_GROWING_LEFT;
1198 frame = graphic_info[graphic].anim_frames - 1;
1203 DrawGraphicShifted(x, y, dx, dy, graphic, frame, cut_mode, mask_mode);
1204 else if (mask_mode == USE_MASKING)
1205 DrawGraphicThruMask(x, y, graphic, frame);
1207 DrawGraphic(x, y, graphic, frame);
1210 void DrawLevelElementExt(int x, int y, int dx, int dy, int element,
1211 int cut_mode, int mask_mode)
1213 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1214 DrawScreenElementExt(SCREENX(x), SCREENY(y), dx, dy, element,
1215 cut_mode, mask_mode);
1218 void DrawScreenElementShifted(int x, int y, int dx, int dy, int element,
1221 DrawScreenElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
1224 void DrawLevelElementShifted(int x, int y, int dx, int dy, int element,
1227 DrawLevelElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
1230 void DrawLevelElementThruMask(int x, int y, int element)
1232 DrawLevelElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
1235 void DrawLevelFieldThruMask(int x, int y)
1237 DrawLevelElementExt(x, y, 0, 0, Feld[x][y], NO_CUTTING, USE_MASKING);
1240 #define TILE_GFX_ELEMENT(x, y) \
1241 (GfxElement[x][y] != EL_UNDEFINED && Feld[x][y] != EL_EXPLOSION ? \
1242 GfxElement[x][y] : Feld[x][y])
1244 static void DrawLevelFieldCrumbledSandExt(int x, int y, int graphic, int frame)
1248 int sx = SCREENX(x), sy = SCREENY(y);
1250 int width, height, cx, cy, i;
1252 int crumbled_border_size = graphic_info[graphic].border_size;
1254 int snip = TILEX / 8; /* number of border pixels from "crumbled graphic" */
1256 static int xy[4][2] =
1265 if (x == 0 && y == 7)
1266 printf("::: %d, %d [%d]\n", GfxElement[x][y], Feld[x][y],
1267 crumbled_border_size);
1270 if (!IN_LEV_FIELD(x, y))
1273 element = TILE_GFX_ELEMENT(x, y);
1275 /* crumble field itself */
1276 if (GFX_CRUMBLED(element) && !IS_MOVING(x, y))
1278 if (!IN_SCR_FIELD(sx, sy))
1281 getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
1283 for (i = 0; i < 4; i++)
1285 int xx = x + xy[i][0];
1286 int yy = y + xy[i][1];
1289 element = (IN_LEV_FIELD(xx, yy) ? TILE_GFX_ELEMENT(xx, yy) :
1292 element = (IN_LEV_FIELD(xx, yy) ? Feld[xx][yy] : BorderElement);
1295 /* check if neighbour field is of same type */
1296 if (GFX_CRUMBLED(element) && !IS_MOVING(xx, yy))
1300 if (Feld[x][y] == EL_CUSTOM_START + 123)
1301 printf("::: crumble [%d] THE CHAOS ENGINE (%d, %d): %d, %d\n",
1302 i, Feld[x][y], element,
1303 GFX_CRUMBLED(element), IS_MOVING(x, y));
1306 if (i == 1 || i == 2)
1308 width = crumbled_border_size;
1310 cx = (i == 2 ? TILEX - crumbled_border_size : 0);
1316 height = crumbled_border_size;
1318 cy = (i == 3 ? TILEY - crumbled_border_size : 0);
1321 BlitBitmap(src_bitmap, drawto_field, src_x + cx, src_y + cy,
1322 width, height, FX + sx * TILEX + cx, FY + sy * TILEY + cy);
1325 MarkTileDirty(sx, sy);
1327 else /* crumble neighbour fields */
1330 getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
1333 for (i = 0; i < 4; i++)
1335 int xx = x + xy[i][0];
1336 int yy = y + xy[i][1];
1337 int sxx = sx + xy[i][0];
1338 int syy = sy + xy[i][1];
1341 if (!IN_LEV_FIELD(xx, yy) ||
1342 !IN_SCR_FIELD(sxx, syy) ||
1346 element = TILE_GFX_ELEMENT(xx, yy);
1348 if (!GFX_CRUMBLED(element))
1351 if (!IN_LEV_FIELD(xx, yy) ||
1352 !IN_SCR_FIELD(sxx, syy) ||
1353 !GFX_CRUMBLED(Feld[xx][yy]) ||
1359 graphic = el_act2crm(Feld[xx][yy], ACTION_DEFAULT);
1360 crumbled_border_size = graphic_info[graphic].border_size;
1362 getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
1365 if (i == 1 || i == 2)
1367 width = crumbled_border_size;
1369 cx = (i == 1 ? TILEX - crumbled_border_size : 0);
1375 height = crumbled_border_size;
1377 cy = (i == 0 ? TILEY - crumbled_border_size : 0);
1380 BlitBitmap(src_bitmap, drawto_field, src_x + cx, src_y + cy,
1381 width, height, FX + sxx * TILEX + cx, FY + syy * TILEY + cy);
1383 MarkTileDirty(sxx, syy);
1388 void DrawLevelFieldCrumbledSand(int x, int y)
1393 if (!IN_LEV_FIELD(x, y))
1396 graphic = el_act2crm(Feld[x][y], ACTION_DEFAULT);
1398 DrawLevelFieldCrumbledSandExt(x, y, graphic, 0);
1400 DrawLevelFieldCrumbledSandExt(x, y, IMG_SAND_CRUMBLED, 0);
1404 void DrawLevelFieldCrumbledSandDigging(int x, int y, int direction,
1408 int graphic1 = el_act_dir2img(GfxElement[x][y], ACTION_DIGGING, direction);
1409 int graphic2 = el_act_dir2crm(GfxElement[x][y], ACTION_DIGGING, direction);
1411 int graphic1 = el_act_dir2img(EL_SAND, ACTION_DIGGING, direction);
1412 int graphic2 = el_act_dir2img(EL_SAND_CRUMBLED, ACTION_DIGGING, direction);
1414 int frame1 = getGraphicAnimationFrame(graphic1, step_frame);
1415 int frame2 = getGraphicAnimationFrame(graphic2, step_frame);
1416 int sx = SCREENX(x), sy = SCREENY(y);
1418 DrawGraphic(sx, sy, graphic1, frame1);
1419 DrawLevelFieldCrumbledSandExt(x, y, graphic2, frame2);
1422 void DrawLevelFieldCrumbledSandNeighbours(int x, int y)
1424 int sx = SCREENX(x), sy = SCREENY(y);
1425 static int xy[4][2] =
1434 for (i = 0; i < 4; i++)
1436 int xx = x + xy[i][0];
1437 int yy = y + xy[i][1];
1438 int sxx = sx + xy[i][0];
1439 int syy = sy + xy[i][1];
1441 if (!IN_LEV_FIELD(xx, yy) ||
1442 !IN_SCR_FIELD(sxx, syy) ||
1443 !GFX_CRUMBLED(Feld[xx][yy]) ||
1447 DrawLevelField(xx, yy);
1451 static int getBorderElement(int x, int y)
1455 { EL_STEELWALL_TOPLEFT, EL_INVISIBLE_STEELWALL_TOPLEFT },
1456 { EL_STEELWALL_TOPRIGHT, EL_INVISIBLE_STEELWALL_TOPRIGHT },
1457 { EL_STEELWALL_BOTTOMLEFT, EL_INVISIBLE_STEELWALL_BOTTOMLEFT },
1458 { EL_STEELWALL_BOTTOMRIGHT, EL_INVISIBLE_STEELWALL_BOTTOMRIGHT },
1459 { EL_STEELWALL_VERTICAL, EL_INVISIBLE_STEELWALL_VERTICAL },
1460 { EL_STEELWALL_HORIZONTAL, EL_INVISIBLE_STEELWALL_HORIZONTAL },
1461 { EL_STEELWALL, EL_INVISIBLE_STEELWALL }
1463 int steel_type = (BorderElement == EL_STEELWALL ? 0 : 1);
1464 int steel_position = (x == -1 && y == -1 ? 0 :
1465 x == lev_fieldx && y == -1 ? 1 :
1466 x == -1 && y == lev_fieldy ? 2 :
1467 x == lev_fieldx && y == lev_fieldy ? 3 :
1468 x == -1 || x == lev_fieldx ? 4 :
1469 y == -1 || y == lev_fieldy ? 5 : 6);
1471 return border[steel_position][steel_type];
1474 void DrawScreenElement(int x, int y, int element)
1476 DrawScreenElementExt(x, y, 0, 0, element, NO_CUTTING, NO_MASKING);
1477 DrawLevelFieldCrumbledSand(LEVELX(x), LEVELY(y));
1480 void DrawLevelElement(int x, int y, int element)
1482 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1483 DrawScreenElement(SCREENX(x), SCREENY(y), element);
1486 void DrawScreenField(int x, int y)
1488 int lx = LEVELX(x), ly = LEVELY(y);
1489 int element, content;
1491 if (!IN_LEV_FIELD(lx, ly))
1493 if (lx < -1 || lx > lev_fieldx || ly < -1 || ly > lev_fieldy)
1496 element = getBorderElement(lx, ly);
1498 DrawScreenElement(x, y, element);
1502 element = Feld[lx][ly];
1503 content = Store[lx][ly];
1505 if (IS_MOVING(lx, ly))
1507 int horiz_move = (MovDir[lx][ly] == MV_LEFT || MovDir[lx][ly] == MV_RIGHT);
1508 boolean cut_mode = NO_CUTTING;
1510 if (element == EL_QUICKSAND_EMPTYING ||
1511 element == EL_MAGIC_WALL_EMPTYING ||
1512 element == EL_BD_MAGIC_WALL_EMPTYING ||
1513 element == EL_AMOEBA_DROPPING)
1514 cut_mode = CUT_ABOVE;
1515 else if (element == EL_QUICKSAND_FILLING ||
1516 element == EL_MAGIC_WALL_FILLING ||
1517 element == EL_BD_MAGIC_WALL_FILLING)
1518 cut_mode = CUT_BELOW;
1520 if (cut_mode == CUT_ABOVE)
1521 DrawScreenElementShifted(x, y, 0, 0, element, NO_CUTTING);
1523 DrawScreenElement(x, y, EL_EMPTY);
1526 DrawScreenElementShifted(x, y, MovPos[lx][ly], 0, element, NO_CUTTING);
1527 else if (cut_mode == NO_CUTTING)
1528 DrawScreenElementShifted(x, y, 0, MovPos[lx][ly], element, cut_mode);
1530 DrawScreenElementShifted(x, y, 0, MovPos[lx][ly], content, cut_mode);
1532 if (content == EL_ACID)
1534 int dir = MovDir[lx][ly];
1535 int newlx = lx + (dir == MV_LEFT ? -1 : dir == MV_RIGHT ? +1 : 0);
1536 int newly = ly + (dir == MV_UP ? -1 : dir == MV_DOWN ? +1 : 0);
1538 DrawLevelElementThruMask(newlx, newly, EL_ACID);
1541 else if (IS_BLOCKED(lx, ly))
1546 boolean cut_mode = NO_CUTTING;
1547 int element_old, content_old;
1549 Blocked2Moving(lx, ly, &oldx, &oldy);
1552 horiz_move = (MovDir[oldx][oldy] == MV_LEFT ||
1553 MovDir[oldx][oldy] == MV_RIGHT);
1555 element_old = Feld[oldx][oldy];
1556 content_old = Store[oldx][oldy];
1558 if (element_old == EL_QUICKSAND_EMPTYING ||
1559 element_old == EL_MAGIC_WALL_EMPTYING ||
1560 element_old == EL_BD_MAGIC_WALL_EMPTYING ||
1561 element_old == EL_AMOEBA_DROPPING)
1562 cut_mode = CUT_ABOVE;
1564 DrawScreenElement(x, y, EL_EMPTY);
1567 DrawScreenElementShifted(sx, sy, MovPos[oldx][oldy], 0, element_old,
1569 else if (cut_mode == NO_CUTTING)
1570 DrawScreenElementShifted(sx, sy, 0, MovPos[oldx][oldy], element_old,
1573 DrawScreenElementShifted(sx, sy, 0, MovPos[oldx][oldy], content_old,
1576 else if (IS_DRAWABLE(element))
1577 DrawScreenElement(x, y, element);
1579 DrawScreenElement(x, y, EL_EMPTY);
1582 void DrawLevelField(int x, int y)
1584 if (IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1585 DrawScreenField(SCREENX(x), SCREENY(y));
1586 else if (IS_MOVING(x, y))
1590 Moving2Blocked(x, y, &newx, &newy);
1591 if (IN_SCR_FIELD(SCREENX(newx), SCREENY(newy)))
1592 DrawScreenField(SCREENX(newx), SCREENY(newy));
1594 else if (IS_BLOCKED(x, y))
1598 Blocked2Moving(x, y, &oldx, &oldy);
1599 if (IN_SCR_FIELD(SCREENX(oldx), SCREENY(oldy)))
1600 DrawScreenField(SCREENX(oldx), SCREENY(oldy));
1604 void DrawMiniElement(int x, int y, int element)
1608 graphic = el2edimg(element);
1609 DrawMiniGraphic(x, y, graphic);
1612 void DrawMiniElementOrWall(int sx, int sy, int scroll_x, int scroll_y)
1614 int x = sx + scroll_x, y = sy + scroll_y;
1616 if (x < -1 || x > lev_fieldx || y < -1 || y > lev_fieldy)
1617 DrawMiniElement(sx, sy, EL_EMPTY);
1618 else if (x > -1 && x < lev_fieldx && y > -1 && y < lev_fieldy)
1619 DrawMiniElement(sx, sy, Feld[x][y]);
1621 DrawMiniGraphic(sx, sy, el2edimg(getBorderElement(x, y)));
1624 void DrawEnvelopeBackground(int envelope_nr, int startx, int starty,
1625 int x, int y, int xsize, int ysize, int font_nr)
1627 int font_width = getFontWidth(font_nr);
1628 int font_height = getFontHeight(font_nr);
1629 int graphic = IMG_BACKGROUND_ENVELOPE_1 + envelope_nr;
1632 int dst_x = SX + startx + x * font_width;
1633 int dst_y = SY + starty + y * font_height;
1634 int width = graphic_info[graphic].width;
1635 int height = graphic_info[graphic].height;
1636 int inner_width = MAX(width - 2 * font_width, font_width);
1637 int inner_height = MAX(height - 2 * font_height, font_height);
1638 int inner_sx = (width >= 3 * font_width ? font_width : 0);
1639 int inner_sy = (height >= 3 * font_height ? font_height : 0);
1640 boolean draw_masked = graphic_info[graphic].draw_masked;
1642 getGraphicSource(graphic, 0, &src_bitmap, &src_x, &src_y);
1644 if (src_bitmap == NULL || width < font_width || height < font_height)
1646 ClearRectangle(drawto, dst_x, dst_y, font_width, font_height);
1650 src_x += (x == 0 ? 0 : x == xsize - 1 ? width - font_width :
1651 inner_sx + (x - 1) * font_width % inner_width);
1652 src_y += (y == 0 ? 0 : y == ysize - 1 ? height - font_height :
1653 inner_sy + (y - 1) * font_height % inner_height);
1657 SetClipOrigin(src_bitmap, src_bitmap->stored_clip_gc,
1658 dst_x - src_x, dst_y - src_y);
1659 BlitBitmapMasked(src_bitmap, drawto, src_x, src_y, font_width, font_height,
1663 BlitBitmap(src_bitmap, drawto, src_x, src_y, font_width, font_height,
1667 void AnimateEnvelope(int envelope_nr, int anim_mode, int action)
1669 int graphic = IMG_BACKGROUND_ENVELOPE_1 + envelope_nr;
1670 boolean draw_masked = graphic_info[graphic].draw_masked;
1671 int mask_mode = (draw_masked ? BLIT_MASKED : BLIT_ON_BACKGROUND);
1672 boolean ffwd_delay = (tape.playing && tape.fast_forward);
1673 boolean no_delay = (tape.warp_forward);
1674 unsigned long anim_delay = 0;
1675 int frame_delay_value = (ffwd_delay ? FfwdFrameDelay : GameFrameDelay);
1676 int anim_delay_value = (no_delay ? 0 : frame_delay_value);
1677 int font_nr = FONT_ENVELOPE_1 + envelope_nr;
1678 int font_width = getFontWidth(font_nr);
1679 int font_height = getFontHeight(font_nr);
1680 int max_xsize = level.envelope_xsize[envelope_nr];
1681 int max_ysize = level.envelope_ysize[envelope_nr];
1682 int xstart = (anim_mode & ANIM_VERTICAL ? max_xsize : 0);
1683 int ystart = (anim_mode & ANIM_HORIZONTAL ? max_ysize : 0);
1684 int xend = max_xsize;
1685 int yend = (anim_mode != ANIM_DEFAULT ? max_ysize : 0);
1686 int xstep = (xstart < xend ? 1 : 0);
1687 int ystep = (ystart < yend || xstep == 0 ? 1 : 0);
1690 for (x = xstart, y = ystart; x <= xend && y <= yend; x += xstep, y += ystep)
1692 int xsize = (action == ACTION_CLOSING ? xend - (x - xstart) : x) + 2;
1693 int ysize = (action == ACTION_CLOSING ? yend - (y - ystart) : y) + 2;
1694 int sx = (SXSIZE - xsize * font_width) / 2;
1695 int sy = (SYSIZE - ysize * font_height) / 2;
1698 SetDrawtoField(DRAW_BUFFERED);
1700 BlitBitmap(fieldbuffer, backbuffer, FX, FY, SXSIZE, SYSIZE, SX, SY);
1702 SetDrawtoField(DRAW_BACKBUFFER);
1704 for (yy = 0; yy < ysize; yy++) for (xx = 0; xx < xsize; xx++)
1705 DrawEnvelopeBackground(envelope_nr, sx,sy, xx,yy, xsize, ysize, font_nr);
1707 DrawTextToTextArea(SX + sx + font_width, SY + sy + font_height,
1708 level.envelope_text[envelope_nr], font_nr, max_xsize,
1709 xsize - 2, ysize - 2, mask_mode);
1711 redraw_mask |= REDRAW_FIELD | REDRAW_FROM_BACKBUFFER;
1714 WaitUntilDelayReached(&anim_delay, anim_delay_value / 2);
1718 void ShowEnvelope(int envelope_nr)
1720 int element = EL_ENVELOPE_1 + envelope_nr;
1721 int graphic = IMG_BACKGROUND_ENVELOPE_1 + envelope_nr;
1722 int sound_opening = element_info[element].sound[ACTION_OPENING];
1723 int sound_closing = element_info[element].sound[ACTION_CLOSING];
1724 boolean ffwd_delay = (tape.playing && tape.fast_forward);
1725 boolean no_delay = (tape.warp_forward);
1726 int normal_delay_value = ONE_SECOND_DELAY / (ffwd_delay ? 2 : 1);
1727 int wait_delay_value = (no_delay ? 0 : normal_delay_value);
1728 int anim_mode = graphic_info[graphic].anim_mode;
1729 int main_anim_mode = (anim_mode == ANIM_NONE ? ANIM_VERTICAL|ANIM_HORIZONTAL:
1730 anim_mode == ANIM_DEFAULT ? ANIM_VERTICAL : anim_mode);
1732 game.envelope_active = TRUE; /* needed for RedrawPlayfield() events */
1734 PlaySoundStereo(sound_opening, SOUND_MIDDLE);
1736 if (anim_mode == ANIM_DEFAULT)
1737 AnimateEnvelope(envelope_nr, ANIM_DEFAULT, ACTION_OPENING);
1739 AnimateEnvelope(envelope_nr, main_anim_mode, ACTION_OPENING);
1742 Delay(wait_delay_value);
1744 WaitForEventToContinue();
1746 PlaySoundStereo(sound_closing, SOUND_MIDDLE);
1748 if (anim_mode != ANIM_NONE)
1749 AnimateEnvelope(envelope_nr, main_anim_mode, ACTION_CLOSING);
1751 if (anim_mode == ANIM_DEFAULT)
1752 AnimateEnvelope(envelope_nr, ANIM_DEFAULT, ACTION_CLOSING);
1754 game.envelope_active = FALSE;
1756 SetDrawtoField(DRAW_BUFFERED);
1758 redraw_mask |= REDRAW_FIELD;
1762 void getMicroGraphicSource(int graphic, Bitmap **bitmap, int *x, int *y)
1764 Bitmap *src_bitmap = graphic_info[graphic].bitmap;
1765 int mini_startx = src_bitmap->width * 3 / 4;
1766 int mini_starty = src_bitmap->height * 2 / 3;
1767 int src_x = mini_startx + graphic_info[graphic].src_x / 8;
1768 int src_y = mini_starty + graphic_info[graphic].src_y / 8;
1770 *bitmap = src_bitmap;
1775 void DrawMicroElement(int xpos, int ypos, int element)
1779 int graphic = el2preimg(element);
1781 getMicroGraphicSource(graphic, &src_bitmap, &src_x, &src_y);
1782 BlitBitmap(src_bitmap, drawto, src_x, src_y, MICRO_TILEX, MICRO_TILEY,
1790 SetDrawBackgroundMask(REDRAW_NONE);
1793 for (x = BX1; x <= BX2; x++)
1794 for (y = BY1; y <= BY2; y++)
1795 DrawScreenField(x, y);
1797 redraw_mask |= REDRAW_FIELD;
1800 void DrawMiniLevel(int size_x, int size_y, int scroll_x, int scroll_y)
1804 for (x = 0; x < size_x; x++)
1805 for (y = 0; y < size_y; y++)
1806 DrawMiniElementOrWall(x, y, scroll_x, scroll_y);
1808 redraw_mask |= REDRAW_FIELD;
1811 static void DrawMicroLevelExt(int xpos, int ypos, int from_x, int from_y)
1815 DrawBackground(xpos, ypos, MICROLEV_XSIZE, MICROLEV_YSIZE);
1817 if (lev_fieldx < STD_LEV_FIELDX)
1818 xpos += (STD_LEV_FIELDX - lev_fieldx) / 2 * MICRO_TILEX;
1819 if (lev_fieldy < STD_LEV_FIELDY)
1820 ypos += (STD_LEV_FIELDY - lev_fieldy) / 2 * MICRO_TILEY;
1822 xpos += MICRO_TILEX;
1823 ypos += MICRO_TILEY;
1825 for (x = -1; x <= STD_LEV_FIELDX; x++)
1827 for (y = -1; y <= STD_LEV_FIELDY; y++)
1829 int lx = from_x + x, ly = from_y + y;
1831 if (lx >= 0 && lx < lev_fieldx && ly >= 0 && ly < lev_fieldy)
1832 DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
1833 level.field[lx][ly]);
1834 else if (lx >= -1 && lx < lev_fieldx+1 && ly >= -1 && ly < lev_fieldy+1
1835 && BorderElement != EL_EMPTY)
1836 DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
1837 getBorderElement(lx, ly));
1841 redraw_mask |= REDRAW_MICROLEVEL;
1844 #define MICROLABEL_EMPTY 0
1845 #define MICROLABEL_LEVEL_NAME 1
1846 #define MICROLABEL_CREATED_BY 2
1847 #define MICROLABEL_LEVEL_AUTHOR 3
1848 #define MICROLABEL_IMPORTED_FROM 4
1849 #define MICROLABEL_LEVEL_IMPORT_INFO 5
1851 static void DrawMicroLevelLabelExt(int mode)
1853 char label_text[MAX_OUTPUT_LINESIZE + 1];
1854 int max_len_label_text;
1855 int font_nr = FONT_TEXT_2;
1857 if (mode == MICROLABEL_CREATED_BY || mode == MICROLABEL_IMPORTED_FROM)
1858 font_nr = FONT_TEXT_3;
1860 max_len_label_text = SXSIZE / getFontWidth(font_nr);
1862 DrawBackground(SX, MICROLABEL_YPOS, SXSIZE, getFontHeight(font_nr));
1864 strncpy(label_text, (mode == MICROLABEL_LEVEL_NAME ? level.name :
1865 mode == MICROLABEL_CREATED_BY ? "created by" :
1866 mode == MICROLABEL_LEVEL_AUTHOR ? level.author :
1867 mode == MICROLABEL_IMPORTED_FROM ? "imported from" :
1868 mode == MICROLABEL_LEVEL_IMPORT_INFO ?
1869 leveldir_current->imported_from : ""),
1870 max_len_label_text);
1871 label_text[max_len_label_text] = '\0';
1873 if (strlen(label_text) > 0)
1875 int lxpos = SX + (SXSIZE - getTextWidth(label_text, font_nr)) / 2;
1876 int lypos = MICROLABEL_YPOS;
1878 DrawText(lxpos, lypos, label_text, font_nr);
1881 redraw_mask |= REDRAW_MICROLEVEL;
1884 void DrawMicroLevel(int xpos, int ypos, boolean restart)
1886 static unsigned long scroll_delay = 0;
1887 static unsigned long label_delay = 0;
1888 static int from_x, from_y, scroll_direction;
1889 static int label_state, label_counter;
1890 int last_game_status = game_status; /* save current game status */
1892 /* force PREVIEW font on preview level */
1893 game_status = GAME_MODE_PSEUDO_PREVIEW;
1897 from_x = from_y = 0;
1898 scroll_direction = MV_RIGHT;
1902 DrawMicroLevelExt(xpos, ypos, from_x, from_y);
1903 DrawMicroLevelLabelExt(label_state);
1905 /* initialize delay counters */
1906 DelayReached(&scroll_delay, 0);
1907 DelayReached(&label_delay, 0);
1909 if (leveldir_current->name)
1911 int text_width = getTextWidth(leveldir_current->name, FONT_TEXT_1);
1912 int lxpos = SX + (SXSIZE - text_width) / 2;
1913 int lypos = SY + 352;
1915 DrawText(lxpos, lypos, leveldir_current->name, FONT_TEXT_1);
1918 game_status = last_game_status; /* restore current game status */
1923 /* scroll micro level, if needed */
1924 if ((lev_fieldx > STD_LEV_FIELDX || lev_fieldy > STD_LEV_FIELDY) &&
1925 DelayReached(&scroll_delay, MICROLEVEL_SCROLL_DELAY))
1927 switch (scroll_direction)
1933 scroll_direction = MV_UP;
1937 if (from_x < lev_fieldx - STD_LEV_FIELDX)
1940 scroll_direction = MV_DOWN;
1947 scroll_direction = MV_RIGHT;
1951 if (from_y < lev_fieldy - STD_LEV_FIELDY)
1954 scroll_direction = MV_LEFT;
1961 DrawMicroLevelExt(xpos, ypos, from_x, from_y);
1964 /* redraw micro level label, if needed */
1965 if (strcmp(level.name, NAMELESS_LEVEL_NAME) != 0 &&
1966 strcmp(level.author, ANONYMOUS_NAME) != 0 &&
1967 strcmp(level.author, leveldir_current->name) != 0 &&
1968 DelayReached(&label_delay, MICROLEVEL_LABEL_DELAY))
1970 int max_label_counter = 23;
1972 if (leveldir_current->imported_from != NULL)
1973 max_label_counter += 14;
1975 label_counter = (label_counter + 1) % max_label_counter;
1976 label_state = (label_counter >= 0 && label_counter <= 7 ?
1977 MICROLABEL_LEVEL_NAME :
1978 label_counter >= 9 && label_counter <= 12 ?
1979 MICROLABEL_CREATED_BY :
1980 label_counter >= 14 && label_counter <= 21 ?
1981 MICROLABEL_LEVEL_AUTHOR :
1982 label_counter >= 23 && label_counter <= 26 ?
1983 MICROLABEL_IMPORTED_FROM :
1984 label_counter >= 28 && label_counter <= 35 ?
1985 MICROLABEL_LEVEL_IMPORT_INFO : MICROLABEL_EMPTY);
1986 DrawMicroLevelLabelExt(label_state);
1989 game_status = last_game_status; /* restore current game status */
1992 void WaitForEventToContinue()
1994 boolean still_wait = TRUE;
1996 /* simulate releasing mouse button over last gadget, if still pressed */
1998 HandleGadgets(-1, -1, 0);
2000 button_status = MB_RELEASED;
2012 case EVENT_BUTTONPRESS:
2013 case EVENT_KEYPRESS:
2017 case EVENT_KEYRELEASE:
2018 ClearPlayerAction();
2022 HandleOtherEvents(&event);
2026 else if (AnyJoystickButton() == JOY_BUTTON_NEW_PRESSED)
2033 /* don't eat all CPU time */
2038 #define MAX_REQUEST_LINES 13
2039 #define MAX_REQUEST_LINE_FONT1_LEN 7
2040 #define MAX_REQUEST_LINE_FONT2_LEN 10
2042 boolean Request(char *text, unsigned int req_state)
2044 int mx, my, ty, result = -1;
2045 unsigned int old_door_state;
2046 int last_game_status = game_status; /* save current game status */
2047 int max_request_line_len = MAX_REQUEST_LINE_FONT1_LEN;
2048 int font_nr = FONT_TEXT_2;
2049 int max_word_len = 0;
2052 for (text_ptr = text; *text_ptr; text_ptr++)
2054 max_word_len = (*text_ptr != ' ' ? max_word_len + 1 : 0);
2056 if (max_word_len > MAX_REQUEST_LINE_FONT1_LEN)
2058 max_request_line_len = MAX_REQUEST_LINE_FONT2_LEN;
2059 font_nr = FONT_LEVEL_NUMBER;
2066 /* disable deactivated drawing when quick-loading level tape recording */
2067 if (tape.playing && tape.deactivate_display)
2068 TapeDeactivateDisplayOff(TRUE);
2072 SetMouseCursor(CURSOR_DEFAULT);
2075 #if defined(PLATFORM_UNIX)
2076 /* pause network game while waiting for request to answer */
2077 if (options.network &&
2078 game_status == GAME_MODE_PLAYING &&
2079 req_state & REQUEST_WAIT_FOR)
2080 SendToServer_PausePlaying();
2083 old_door_state = GetDoorState();
2085 /* simulate releasing mouse button over last gadget, if still pressed */
2087 HandleGadgets(-1, -1, 0);
2091 CloseDoor(DOOR_CLOSE_1);
2093 /* save old door content */
2094 BlitBitmap(bitmap_db_door, bitmap_db_door,
2095 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE,
2096 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1);
2098 SetDrawBackgroundMask(REDRAW_FIELD | REDRAW_DOOR_1);
2100 /* clear door drawing field */
2101 DrawBackground(DX, DY, DXSIZE, DYSIZE);
2103 /* force DOOR font on preview level */
2104 game_status = GAME_MODE_PSEUDO_DOOR;
2106 /* write text for request */
2107 for (ty = 0; ty < MAX_REQUEST_LINES; ty++)
2109 char text_line[max_request_line_len + 1];
2115 for (tl = 0, tx = 0; tx < max_request_line_len; tl++, tx++)
2118 if (!tc || tc == ' ')
2129 strncpy(text_line, text, tl);
2132 DrawText(DX + (DXSIZE - tl * getFontWidth(font_nr)) / 2,
2133 DY + 8 + ty * (getFontHeight(font_nr) + 2),
2134 text_line, font_nr);
2136 text += tl + (tc == ' ' ? 1 : 0);
2139 game_status = last_game_status; /* restore current game status */
2141 if (req_state & REQ_ASK)
2143 MapGadget(tool_gadget[TOOL_CTRL_ID_YES]);
2144 MapGadget(tool_gadget[TOOL_CTRL_ID_NO]);
2146 else if (req_state & REQ_CONFIRM)
2148 MapGadget(tool_gadget[TOOL_CTRL_ID_CONFIRM]);
2150 else if (req_state & REQ_PLAYER)
2152 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_1]);
2153 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_2]);
2154 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_3]);
2155 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_4]);
2158 /* copy request gadgets to door backbuffer */
2159 BlitBitmap(drawto, bitmap_db_door,
2160 DX, DY, DXSIZE, DYSIZE,
2161 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
2163 OpenDoor(DOOR_OPEN_1);
2169 if (!(req_state & REQUEST_WAIT_FOR))
2171 SetDrawBackgroundMask(REDRAW_FIELD);
2176 if (game_status != GAME_MODE_MAIN)
2179 button_status = MB_RELEASED;
2181 request_gadget_id = -1;
2183 SetDrawBackgroundMask(REDRAW_FIELD | REDRAW_DOOR_1);
2186 SetMouseCursor(CURSOR_DEFAULT);
2199 case EVENT_BUTTONPRESS:
2200 case EVENT_BUTTONRELEASE:
2201 case EVENT_MOTIONNOTIFY:
2203 if (event.type == EVENT_MOTIONNOTIFY)
2205 if (!PointerInWindow(window))
2206 continue; /* window and pointer are on different screens */
2211 motion_status = TRUE;
2212 mx = ((MotionEvent *) &event)->x;
2213 my = ((MotionEvent *) &event)->y;
2217 motion_status = FALSE;
2218 mx = ((ButtonEvent *) &event)->x;
2219 my = ((ButtonEvent *) &event)->y;
2220 if (event.type == EVENT_BUTTONPRESS)
2221 button_status = ((ButtonEvent *) &event)->button;
2223 button_status = MB_RELEASED;
2226 /* this sets 'request_gadget_id' */
2227 HandleGadgets(mx, my, button_status);
2229 switch(request_gadget_id)
2231 case TOOL_CTRL_ID_YES:
2234 case TOOL_CTRL_ID_NO:
2237 case TOOL_CTRL_ID_CONFIRM:
2238 result = TRUE | FALSE;
2241 case TOOL_CTRL_ID_PLAYER_1:
2244 case TOOL_CTRL_ID_PLAYER_2:
2247 case TOOL_CTRL_ID_PLAYER_3:
2250 case TOOL_CTRL_ID_PLAYER_4:
2261 case EVENT_KEYPRESS:
2262 switch(GetEventKey((KeyEvent *)&event, TRUE))
2275 if (req_state & REQ_PLAYER)
2279 case EVENT_KEYRELEASE:
2280 ClearPlayerAction();
2284 HandleOtherEvents(&event);
2288 else if (AnyJoystickButton() == JOY_BUTTON_NEW_PRESSED)
2290 int joy = AnyJoystick();
2292 if (joy & JOY_BUTTON_1)
2294 else if (joy & JOY_BUTTON_2)
2300 /* don't eat all CPU time */
2304 if (game_status != GAME_MODE_MAIN)
2309 if (!(req_state & REQ_STAY_OPEN))
2311 CloseDoor(DOOR_CLOSE_1);
2313 if (!(req_state & REQ_STAY_CLOSED) && (old_door_state & DOOR_OPEN_1))
2315 BlitBitmap(bitmap_db_door, bitmap_db_door,
2316 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE,
2317 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
2318 OpenDoor(DOOR_OPEN_1);
2324 SetDrawBackgroundMask(REDRAW_FIELD);
2326 #if defined(PLATFORM_UNIX)
2327 /* continue network game after request */
2328 if (options.network &&
2329 game_status == GAME_MODE_PLAYING &&
2330 req_state & REQUEST_WAIT_FOR)
2331 SendToServer_ContinuePlaying();
2335 /* restore deactivated drawing when quick-loading level tape recording */
2336 if (tape.playing && tape.deactivate_display)
2337 TapeDeactivateDisplayOn();
2343 unsigned int OpenDoor(unsigned int door_state)
2345 unsigned int new_door_state;
2347 if (door_state & DOOR_COPY_BACK)
2349 BlitBitmap(bitmap_db_door, bitmap_db_door,
2350 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE + VYSIZE,
2351 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
2352 door_state &= ~DOOR_COPY_BACK;
2355 new_door_state = MoveDoor(door_state);
2357 return(new_door_state);
2360 unsigned int CloseDoor(unsigned int door_state)
2362 unsigned int new_door_state;
2364 BlitBitmap(backbuffer, bitmap_db_door,
2365 DX, DY, DXSIZE, DYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
2366 BlitBitmap(backbuffer, bitmap_db_door,
2367 VX, VY, VXSIZE, VYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2);
2369 new_door_state = MoveDoor(door_state);
2371 return(new_door_state);
2374 unsigned int GetDoorState()
2376 return MoveDoor(DOOR_GET_STATE);
2379 unsigned int SetDoorState(unsigned int door_state)
2381 return MoveDoor(door_state | DOOR_SET_STATE);
2384 unsigned int MoveDoor(unsigned int door_state)
2386 static int door1 = DOOR_OPEN_1;
2387 static int door2 = DOOR_CLOSE_2;
2388 unsigned long door_delay = 0;
2389 unsigned long door_delay_value;
2392 if (door_state == DOOR_GET_STATE)
2393 return(door1 | door2);
2395 if (door_state & DOOR_SET_STATE)
2397 if (door_state & DOOR_ACTION_1)
2398 door1 = door_state & DOOR_ACTION_1;
2399 if (door_state & DOOR_ACTION_2)
2400 door2 = door_state & DOOR_ACTION_2;
2402 return(door1 | door2);
2405 if (door1 == DOOR_OPEN_1 && door_state & DOOR_OPEN_1)
2406 door_state &= ~DOOR_OPEN_1;
2407 else if (door1 == DOOR_CLOSE_1 && door_state & DOOR_CLOSE_1)
2408 door_state &= ~DOOR_CLOSE_1;
2409 if (door2 == DOOR_OPEN_2 && door_state & DOOR_OPEN_2)
2410 door_state &= ~DOOR_OPEN_2;
2411 else if (door2 == DOOR_CLOSE_2 && door_state & DOOR_CLOSE_2)
2412 door_state &= ~DOOR_CLOSE_2;
2414 door_delay_value = (door_state & DOOR_ACTION_1 ? door_1.step_delay :
2417 if (setup.quick_doors)
2419 stepsize = 20; /* must be choosen to always draw last frame */
2420 door_delay_value = 0;
2423 StopSound(SND_DOOR_OPENING);
2424 StopSound(SND_DOOR_CLOSING);
2428 if (global.autoplay_leveldir)
2430 door_state |= DOOR_NO_DELAY;
2431 door_state &= ~DOOR_CLOSE_ALL;
2434 if (door_state & DOOR_ACTION)
2436 boolean door_1_done = !(door_state & DOOR_ACTION_1);
2437 boolean door_2_done = !(door_state & DOOR_ACTION_2);
2438 int start = ((door_state & DOOR_NO_DELAY) ? DXSIZE : 0);
2439 int end = (door_state & DOOR_ACTION_1 &&
2440 door_1.anim_mode == ANIM_VERTICAL ? DYSIZE : DXSIZE);
2443 if (!(door_state & DOOR_NO_DELAY) && !setup.quick_doors)
2445 /* opening door sound has priority over simultaneously closing door */
2446 if (door_state & (DOOR_OPEN_1 | DOOR_OPEN_2))
2447 PlaySoundStereo(SND_DOOR_OPENING, SOUND_MIDDLE);
2448 else if (door_state & (DOOR_CLOSE_1 | DOOR_CLOSE_2))
2449 PlaySoundStereo(SND_DOOR_CLOSING, SOUND_MIDDLE);
2452 for (x = start; x <= end && !(door_1_done && door_2_done); x += stepsize)
2454 Bitmap *bitmap = graphic_info[IMG_GLOBAL_DOOR].bitmap;
2455 GC gc = bitmap->stored_clip_gc;
2457 if (door_state & DOOR_ACTION_1)
2459 int a = MIN(x * door_1.step_offset, end);
2460 int i = (door_state & DOOR_OPEN_1 ? end - a : a);
2464 BlitBitmap(bitmap_db_door, drawto,
2465 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1 + i / 2,
2466 DXSIZE,DYSIZE - i / 2, DX, DY);
2468 ClearRectangle(drawto, DX, DY + DYSIZE - i / 2, DXSIZE, i / 2);
2471 if (door_1.anim_mode == ANIM_HORIZONTAL && x <= DXSIZE)
2473 int src1_x = DXSIZE, src1_y = DOOR_GFX_PAGEY1;
2474 int dst1_x = DX + DXSIZE - i, dst1_y = DY;
2475 int src2_x = DXSIZE - i, src2_y = DOOR_GFX_PAGEY1;
2476 int dst2_x = DX, dst2_y = DY;
2477 int width = i, height = DYSIZE;
2479 SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y);
2480 BlitBitmapMasked(bitmap, drawto, src1_x, src1_y, width, height,
2483 SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y);
2484 BlitBitmapMasked(bitmap, drawto, src2_x, src2_y, width, height,
2487 else if (door_1.anim_mode == ANIM_VERTICAL && x <= DYSIZE)
2489 int src1_x = DXSIZE, src1_y = DOOR_GFX_PAGEY1;
2490 int dst1_x = DX, dst1_y = DY + DYSIZE - i;
2491 int src2_x = 0, src2_y = DOOR_GFX_PAGEY1 + DYSIZE - i;
2492 int dst2_x = DX, dst2_y = DY;
2493 int width = DXSIZE, height = i;
2495 SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y);
2496 BlitBitmapMasked(bitmap, drawto, src1_x, src1_y, width, height,
2499 SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y);
2500 BlitBitmapMasked(bitmap, drawto, src2_x, src2_y, width, height,
2503 else if (x <= DXSIZE) /* ANIM_DEFAULT */
2505 int j = (door_1.anim_mode == ANIM_DEFAULT ? (DXSIZE - i) / 3 : 0);
2507 SetClipOrigin(bitmap, gc, DX - i, (DY + j) - DOOR_GFX_PAGEY1);
2508 BlitBitmapMasked(bitmap, drawto,
2509 DXSIZE, DOOR_GFX_PAGEY1, i, 77,
2510 DX + DXSIZE - i, DY + j);
2511 BlitBitmapMasked(bitmap, drawto,
2512 DXSIZE, DOOR_GFX_PAGEY1 + 140, i, 63,
2513 DX + DXSIZE - i, DY + 140 + j);
2514 SetClipOrigin(bitmap, gc, DX - DXSIZE + i,
2515 DY - (DOOR_GFX_PAGEY1 + j));
2516 BlitBitmapMasked(bitmap, drawto,
2517 DXSIZE - i, DOOR_GFX_PAGEY1 + j, i, 77 - j,
2519 BlitBitmapMasked(bitmap, drawto,
2520 DXSIZE-i, DOOR_GFX_PAGEY1 + 140, i, 63,
2523 BlitBitmapMasked(bitmap, drawto,
2524 DXSIZE - i, DOOR_GFX_PAGEY1 + 77, i, 63,
2526 BlitBitmapMasked(bitmap, drawto,
2527 DXSIZE - i, DOOR_GFX_PAGEY1 + 203, i, 77,
2529 SetClipOrigin(bitmap, gc, DX - i, (DY + j) - DOOR_GFX_PAGEY1);
2530 BlitBitmapMasked(bitmap, drawto,
2531 DXSIZE, DOOR_GFX_PAGEY1 + 77, i, 63,
2532 DX + DXSIZE - i, DY + 77 + j);
2533 BlitBitmapMasked(bitmap, drawto,
2534 DXSIZE, DOOR_GFX_PAGEY1 + 203, i, 77 - j,
2535 DX + DXSIZE - i, DY + 203 + j);
2538 redraw_mask |= REDRAW_DOOR_1;
2539 door_1_done = (a == end);
2542 if (door_state & DOOR_ACTION_2)
2544 int a = MIN(x * door_2.step_offset, VXSIZE);
2545 int i = (door_state & DOOR_OPEN_2 ? VXSIZE - a : a);
2549 BlitBitmap(bitmap_db_door, drawto,
2550 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2 + i / 2,
2551 VXSIZE, VYSIZE - i / 2, VX, VY);
2553 ClearRectangle(drawto, VX, VY + VYSIZE - i / 2, VXSIZE, i / 2);
2556 if (door_2.anim_mode == ANIM_HORIZONTAL && x <= VXSIZE)
2558 int src1_x = VXSIZE, src1_y = DOOR_GFX_PAGEY2;
2559 int dst1_x = VX + VXSIZE - i, dst1_y = VY;
2560 int src2_x = VXSIZE - i, src2_y = DOOR_GFX_PAGEY2;
2561 int dst2_x = VX, dst2_y = VY;
2562 int width = i, height = VYSIZE;
2564 SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y);
2565 BlitBitmapMasked(bitmap, drawto, src1_x, src1_y, width, height,
2568 SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y);
2569 BlitBitmapMasked(bitmap, drawto, src2_x, src2_y, width, height,
2572 else if (door_2.anim_mode == ANIM_VERTICAL && x <= VYSIZE)
2574 int src1_x = VXSIZE, src1_y = DOOR_GFX_PAGEY2;
2575 int dst1_x = VX, dst1_y = VY + VYSIZE - i;
2576 int src2_x = 0, src2_y = DOOR_GFX_PAGEY2 + VYSIZE - i;
2577 int dst2_x = VX, dst2_y = VY;
2578 int width = VXSIZE, height = i;
2580 SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y);
2581 BlitBitmapMasked(bitmap, drawto, src1_x, src1_y, width, height,
2584 SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y);
2585 BlitBitmapMasked(bitmap, drawto, src2_x, src2_y, width, height,
2588 else if (x <= VXSIZE) /* ANIM_DEFAULT */
2590 int j = (door_2.anim_mode == ANIM_DEFAULT ? (VXSIZE - i) / 3 : 0);
2592 SetClipOrigin(bitmap, gc, VX - i, (VY + j) - DOOR_GFX_PAGEY2);
2593 BlitBitmapMasked(bitmap, drawto,
2594 VXSIZE, DOOR_GFX_PAGEY2, i, VYSIZE / 2,
2595 VX + VXSIZE - i, VY + j);
2596 SetClipOrigin(bitmap, gc,
2597 VX - VXSIZE + i, VY - (DOOR_GFX_PAGEY2 + j));
2598 BlitBitmapMasked(bitmap, drawto,
2599 VXSIZE - i, DOOR_GFX_PAGEY2 + j, i, VYSIZE / 2 - j,
2602 BlitBitmapMasked(bitmap, drawto,
2603 VXSIZE - i, DOOR_GFX_PAGEY2 + VYSIZE / 2,
2604 i, VYSIZE / 2, VX, VY + VYSIZE / 2 - j);
2605 SetClipOrigin(bitmap, gc, VX - i, (VY + j) - DOOR_GFX_PAGEY2);
2606 BlitBitmapMasked(bitmap, drawto,
2607 VXSIZE, DOOR_GFX_PAGEY2 + VYSIZE / 2,
2609 VX + VXSIZE - i, VY + VYSIZE / 2 + j);
2612 redraw_mask |= REDRAW_DOOR_2;
2613 door_2_done = (a == VXSIZE);
2618 if (game_status == GAME_MODE_MAIN)
2621 if (!(door_state & DOOR_NO_DELAY))
2622 WaitUntilDelayReached(&door_delay, door_delay_value);
2627 if (setup.quick_doors)
2629 StopSound(SND_DOOR_OPENING);
2630 StopSound(SND_DOOR_CLOSING);
2634 if (door_state & DOOR_ACTION_1)
2635 door1 = door_state & DOOR_ACTION_1;
2636 if (door_state & DOOR_ACTION_2)
2637 door2 = door_state & DOOR_ACTION_2;
2639 return (door1 | door2);
2642 void DrawSpecialEditorDoor()
2644 /* draw bigger toolbox window */
2645 BlitBitmap(graphic_info[IMG_GLOBAL_DOOR].bitmap, drawto,
2646 DOOR_GFX_PAGEX7, 0, EXSIZE + 8, 8,
2648 BlitBitmap(graphic_info[IMG_GLOBAL_BORDER].bitmap, drawto,
2649 EX - 4, VY - 4, EXSIZE + 8, EYSIZE - VYSIZE + 4,
2652 redraw_mask |= REDRAW_ALL;
2655 void UndrawSpecialEditorDoor()
2657 /* draw normal tape recorder window */
2658 BlitBitmap(graphic_info[IMG_GLOBAL_BORDER].bitmap, drawto,
2659 EX - 4, EY - 12, EXSIZE + 8, EYSIZE - VYSIZE + 12,
2662 redraw_mask |= REDRAW_ALL;
2666 /* ---------- new tool button stuff ---------------------------------------- */
2668 /* graphic position values for tool buttons */
2669 #define TOOL_BUTTON_YES_XPOS 2
2670 #define TOOL_BUTTON_YES_YPOS 250
2671 #define TOOL_BUTTON_YES_GFX_YPOS 0
2672 #define TOOL_BUTTON_YES_XSIZE 46
2673 #define TOOL_BUTTON_YES_YSIZE 28
2674 #define TOOL_BUTTON_NO_XPOS 52
2675 #define TOOL_BUTTON_NO_YPOS TOOL_BUTTON_YES_YPOS
2676 #define TOOL_BUTTON_NO_GFX_YPOS TOOL_BUTTON_YES_GFX_YPOS
2677 #define TOOL_BUTTON_NO_XSIZE TOOL_BUTTON_YES_XSIZE
2678 #define TOOL_BUTTON_NO_YSIZE TOOL_BUTTON_YES_YSIZE
2679 #define TOOL_BUTTON_CONFIRM_XPOS TOOL_BUTTON_YES_XPOS
2680 #define TOOL_BUTTON_CONFIRM_YPOS TOOL_BUTTON_YES_YPOS
2681 #define TOOL_BUTTON_CONFIRM_GFX_YPOS 30
2682 #define TOOL_BUTTON_CONFIRM_XSIZE 96
2683 #define TOOL_BUTTON_CONFIRM_YSIZE TOOL_BUTTON_YES_YSIZE
2684 #define TOOL_BUTTON_PLAYER_XSIZE 30
2685 #define TOOL_BUTTON_PLAYER_YSIZE 30
2686 #define TOOL_BUTTON_PLAYER_GFX_XPOS 5
2687 #define TOOL_BUTTON_PLAYER_GFX_YPOS 185
2688 #define TOOL_BUTTON_PLAYER_XPOS (5 + TOOL_BUTTON_PLAYER_XSIZE / 2)
2689 #define TOOL_BUTTON_PLAYER_YPOS (215 - TOOL_BUTTON_PLAYER_YSIZE / 2)
2690 #define TOOL_BUTTON_PLAYER1_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2691 + 0 * TOOL_BUTTON_PLAYER_XSIZE)
2692 #define TOOL_BUTTON_PLAYER2_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2693 + 1 * TOOL_BUTTON_PLAYER_XSIZE)
2694 #define TOOL_BUTTON_PLAYER3_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2695 + 0 * TOOL_BUTTON_PLAYER_XSIZE)
2696 #define TOOL_BUTTON_PLAYER4_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2697 + 1 * TOOL_BUTTON_PLAYER_XSIZE)
2698 #define TOOL_BUTTON_PLAYER1_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2699 + 0 * TOOL_BUTTON_PLAYER_YSIZE)
2700 #define TOOL_BUTTON_PLAYER2_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2701 + 0 * TOOL_BUTTON_PLAYER_YSIZE)
2702 #define TOOL_BUTTON_PLAYER3_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2703 + 1 * TOOL_BUTTON_PLAYER_YSIZE)
2704 #define TOOL_BUTTON_PLAYER4_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2705 + 1 * TOOL_BUTTON_PLAYER_YSIZE)
2714 } toolbutton_info[NUM_TOOL_BUTTONS] =
2717 TOOL_BUTTON_YES_XPOS, TOOL_BUTTON_YES_GFX_YPOS,
2718 TOOL_BUTTON_YES_XPOS, TOOL_BUTTON_YES_YPOS,
2719 TOOL_BUTTON_YES_XSIZE, TOOL_BUTTON_YES_YSIZE,
2724 TOOL_BUTTON_NO_XPOS, TOOL_BUTTON_NO_GFX_YPOS,
2725 TOOL_BUTTON_NO_XPOS, TOOL_BUTTON_NO_YPOS,
2726 TOOL_BUTTON_NO_XSIZE, TOOL_BUTTON_NO_YSIZE,
2731 TOOL_BUTTON_CONFIRM_XPOS, TOOL_BUTTON_CONFIRM_GFX_YPOS,
2732 TOOL_BUTTON_CONFIRM_XPOS, TOOL_BUTTON_CONFIRM_YPOS,
2733 TOOL_BUTTON_CONFIRM_XSIZE, TOOL_BUTTON_CONFIRM_YSIZE,
2734 TOOL_CTRL_ID_CONFIRM,
2738 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2739 TOOL_BUTTON_PLAYER1_XPOS, TOOL_BUTTON_PLAYER1_YPOS,
2740 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2741 TOOL_CTRL_ID_PLAYER_1,
2745 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2746 TOOL_BUTTON_PLAYER2_XPOS, TOOL_BUTTON_PLAYER2_YPOS,
2747 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2748 TOOL_CTRL_ID_PLAYER_2,
2752 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2753 TOOL_BUTTON_PLAYER3_XPOS, TOOL_BUTTON_PLAYER3_YPOS,
2754 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2755 TOOL_CTRL_ID_PLAYER_3,
2759 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2760 TOOL_BUTTON_PLAYER4_XPOS, TOOL_BUTTON_PLAYER4_YPOS,
2761 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2762 TOOL_CTRL_ID_PLAYER_4,
2767 void CreateToolButtons()
2771 for (i = 0; i < NUM_TOOL_BUTTONS; i++)
2773 Bitmap *gd_bitmap = graphic_info[IMG_GLOBAL_DOOR].bitmap;
2774 Bitmap *deco_bitmap = None;
2775 int deco_x = 0, deco_y = 0, deco_xpos = 0, deco_ypos = 0;
2776 struct GadgetInfo *gi;
2777 unsigned long event_mask;
2778 int gd_xoffset, gd_yoffset;
2779 int gd_x1, gd_x2, gd_y;
2782 event_mask = GD_EVENT_RELEASED;
2784 gd_xoffset = toolbutton_info[i].xpos;
2785 gd_yoffset = toolbutton_info[i].ypos;
2786 gd_x1 = DOOR_GFX_PAGEX4 + gd_xoffset;
2787 gd_x2 = DOOR_GFX_PAGEX3 + gd_xoffset;
2788 gd_y = DOOR_GFX_PAGEY1 + gd_yoffset;
2790 if (id >= TOOL_CTRL_ID_PLAYER_1 && id <= TOOL_CTRL_ID_PLAYER_4)
2792 int player_nr = id - TOOL_CTRL_ID_PLAYER_1;
2794 getMiniGraphicSource(PLAYER_NR_GFX(IMG_PLAYER_1, player_nr),
2795 &deco_bitmap, &deco_x, &deco_y);
2796 deco_xpos = (toolbutton_info[i].width - MINI_TILEX) / 2;
2797 deco_ypos = (toolbutton_info[i].height - MINI_TILEY) / 2;
2800 gi = CreateGadget(GDI_CUSTOM_ID, id,
2801 GDI_INFO_TEXT, toolbutton_info[i].infotext,
2802 GDI_X, DX + toolbutton_info[i].x,
2803 GDI_Y, DY + toolbutton_info[i].y,
2804 GDI_WIDTH, toolbutton_info[i].width,
2805 GDI_HEIGHT, toolbutton_info[i].height,
2806 GDI_TYPE, GD_TYPE_NORMAL_BUTTON,
2807 GDI_STATE, GD_BUTTON_UNPRESSED,
2808 GDI_DESIGN_UNPRESSED, gd_bitmap, gd_x1, gd_y,
2809 GDI_DESIGN_PRESSED, gd_bitmap, gd_x2, gd_y,
2810 GDI_DECORATION_DESIGN, deco_bitmap, deco_x, deco_y,
2811 GDI_DECORATION_POSITION, deco_xpos, deco_ypos,
2812 GDI_DECORATION_SIZE, MINI_TILEX, MINI_TILEY,
2813 GDI_DECORATION_SHIFTING, 1, 1,
2814 GDI_EVENT_MASK, event_mask,
2815 GDI_CALLBACK_ACTION, HandleToolButtons,
2819 Error(ERR_EXIT, "cannot create gadget");
2821 tool_gadget[id] = gi;
2825 void FreeToolButtons()
2829 for (i = 0; i < NUM_TOOL_BUTTONS; i++)
2830 FreeGadget(tool_gadget[i]);
2833 static void UnmapToolButtons()
2837 for (i = 0; i < NUM_TOOL_BUTTONS; i++)
2838 UnmapGadget(tool_gadget[i]);
2841 static void HandleToolButtons(struct GadgetInfo *gi)
2843 request_gadget_id = gi->custom_id;
2846 int get_next_element(int element)
2850 case EL_QUICKSAND_FILLING: return EL_QUICKSAND_FULL;
2851 case EL_QUICKSAND_EMPTYING: return EL_QUICKSAND_EMPTY;
2852 case EL_MAGIC_WALL_FILLING: return EL_MAGIC_WALL_FULL;
2853 case EL_MAGIC_WALL_EMPTYING: return EL_MAGIC_WALL_ACTIVE;
2854 case EL_BD_MAGIC_WALL_FILLING: return EL_BD_MAGIC_WALL_FULL;
2855 case EL_BD_MAGIC_WALL_EMPTYING: return EL_BD_MAGIC_WALL_ACTIVE;
2856 case EL_AMOEBA_DROPPING: return EL_AMOEBA_WET;
2858 default: return element;
2862 int el_act_dir2img(int element, int action, int direction)
2864 element = GFX_ELEMENT(element);
2865 direction = MV_DIR_BIT(direction);
2867 return element_info[element].direction_graphic[action][direction];
2870 static int el_act_dir2crm(int element, int action, int direction)
2872 element = GFX_ELEMENT(element);
2873 direction = MV_DIR_BIT(direction);
2875 return element_info[element].direction_crumbled[action][direction];
2878 int el_act2img(int element, int action)
2880 element = GFX_ELEMENT(element);
2882 return element_info[element].graphic[action];
2885 int el_act2crm(int element, int action)
2887 element = GFX_ELEMENT(element);
2889 return element_info[element].crumbled[action];
2892 int el_dir2img(int element, int direction)
2894 element = GFX_ELEMENT(element);
2896 return el_act_dir2img(element, ACTION_DEFAULT, direction);
2899 int el2baseimg(int element)
2901 return element_info[element].graphic[ACTION_DEFAULT];
2904 int el2img(int element)
2906 element = GFX_ELEMENT(element);
2908 return element_info[element].graphic[ACTION_DEFAULT];
2911 int el2edimg(int element)
2913 element = GFX_ELEMENT(element);
2915 return element_info[element].special_graphic[GFX_SPECIAL_ARG_EDITOR];
2918 int el2preimg(int element)
2920 element = GFX_ELEMENT(element);
2922 return element_info[element].special_graphic[GFX_SPECIAL_ARG_PREVIEW];