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, FX + 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);
881 /* ... and the field the player is entering */
882 if (IS_ACCESSIBLE_INSIDE(element))
883 DrawLevelField(jx, jy);
884 else if (IS_ACCESSIBLE_UNDER(element))
885 DrawLevelFieldThruMask(jx, jy);
887 if (setup.direct_draw)
889 int dest_x = SX + SCREENX(MIN(jx, last_jx)) * TILEX;
890 int dest_y = SY + SCREENY(MIN(jy, last_jy)) * TILEY;
891 int x_size = TILEX * (1 + ABS(jx - last_jx));
892 int y_size = TILEY * (1 + ABS(jy - last_jy));
894 BlitBitmap(drawto_field, window,
895 dest_x, dest_y, x_size, y_size, dest_x, dest_y);
896 SetDrawtoField(DRAW_DIRECT);
899 MarkTileDirty(sx, sy);
902 void getGraphicSource(int graphic, int frame, Bitmap **bitmap, int *x, int *y)
904 struct GraphicInfo *g = &graphic_info[graphic];
908 if (g->offset_y == 0) /* frames are ordered horizontally */
910 int max_width = g->anim_frames_per_line * g->width;
912 *x = (g->src_x + frame * g->offset_x) % max_width;
913 *y = g->src_y + (g->src_x + frame * g->offset_x) / max_width * g->height;
915 else if (g->offset_x == 0) /* frames are ordered vertically */
917 int max_height = g->anim_frames_per_line * g->height;
919 *x = g->src_x + (g->src_y + frame * g->offset_y) / max_height * g->width;
920 *y = (g->src_y + frame * g->offset_y) % max_height;
922 else /* frames are ordered diagonally */
924 *x = g->src_x + frame * g->offset_x;
925 *y = g->src_y + frame * g->offset_y;
929 void DrawGraphic(int x, int y, int graphic, int frame)
932 if (!IN_SCR_FIELD(x, y))
934 printf("DrawGraphic(): x = %d, y = %d, graphic = %d\n", x, y, graphic);
935 printf("DrawGraphic(): This should never happen!\n");
940 DrawGraphicExt(drawto_field, FX + x * TILEX, FY + y * TILEY, graphic, frame);
944 void DrawGraphicExt(DrawBuffer *dst_bitmap, int x, int y, int graphic,
950 getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
951 BlitBitmap(src_bitmap, dst_bitmap, src_x, src_y, TILEX, TILEY, x, y);
954 void DrawGraphicThruMask(int x, int y, int graphic, int frame)
957 if (!IN_SCR_FIELD(x, y))
959 printf("DrawGraphicThruMask(): x = %d,y = %d, graphic = %d\n",x,y,graphic);
960 printf("DrawGraphicThruMask(): This should never happen!\n");
965 DrawGraphicThruMaskExt(drawto_field, FX + x * TILEX, FY + y *TILEY, graphic,
970 void DrawGraphicThruMaskExt(DrawBuffer *d, int dest_x, int dest_y, int graphic,
978 getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
979 drawing_gc = src_bitmap->stored_clip_gc;
981 GC drawing_gc = src_bitmap->stored_clip_gc;
982 Bitmap *src_bitmap = graphic_info[graphic].bitmap;
983 int src_x = graphic_info[graphic].src_x;
984 int src_y = graphic_info[graphic].src_y;
985 int offset_x = graphic_info[graphic].offset_x;
986 int offset_y = graphic_info[graphic].offset_y;
988 src_x += frame * offset_x;
989 src_y += frame * offset_y;
993 SetClipOrigin(src_bitmap, drawing_gc, dest_x - src_x, dest_y - src_y);
994 BlitBitmapMasked(src_bitmap, d, src_x, src_y, TILEX, TILEY, dest_x, dest_y);
997 void DrawMiniGraphic(int x, int y, int graphic)
999 DrawMiniGraphicExt(drawto, SX + x * MINI_TILEX,SY + y * MINI_TILEY, graphic);
1000 MarkTileDirty(x / 2, y / 2);
1003 void getMiniGraphicSource(int graphic, Bitmap **bitmap, int *x, int *y)
1005 struct GraphicInfo *g = &graphic_info[graphic];
1006 int mini_startx = 0;
1007 int mini_starty = g->bitmap->height * 2 / 3;
1009 *bitmap = g->bitmap;
1010 *x = mini_startx + g->src_x / 2;
1011 *y = mini_starty + g->src_y / 2;
1014 void DrawMiniGraphicExt(DrawBuffer *d, int x, int y, int graphic)
1019 getMiniGraphicSource(graphic, &src_bitmap, &src_x, &src_y);
1020 BlitBitmap(src_bitmap, d, src_x, src_y, MINI_TILEX, MINI_TILEY, x, y);
1023 void DrawGraphicShifted(int x, int y, int dx, int dy, int graphic, int frame,
1024 int cut_mode, int mask_mode)
1029 int width = TILEX, height = TILEY;
1035 DrawGraphic(x, y, graphic, frame);
1039 if (dx || dy) /* shifted graphic */
1041 if (x < BX1) /* object enters playfield from the left */
1048 else if (x > BX2) /* object enters playfield from the right */
1054 else if (x==BX1 && dx < 0) /* object leaves playfield to the left */
1060 else if (x==BX2 && dx > 0) /* object leaves playfield to the right */
1062 else if (dx) /* general horizontal movement */
1063 MarkTileDirty(x + SIGN(dx), y);
1065 if (y < BY1) /* object enters playfield from the top */
1067 if (cut_mode==CUT_BELOW) /* object completely above top border */
1075 else if (y > BY2) /* object enters playfield from the bottom */
1081 else if (y==BY1 && dy < 0) /* object leaves playfield to the top */
1087 else if (dy > 0 && cut_mode == CUT_ABOVE)
1089 if (y == BY2) /* object completely above bottom border */
1095 MarkTileDirty(x, y + 1);
1096 } /* object leaves playfield to the bottom */
1097 else if (dy > 0 && (y == BY2 || cut_mode == CUT_BELOW))
1099 else if (dy) /* general vertical movement */
1100 MarkTileDirty(x, y + SIGN(dy));
1104 getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
1106 src_bitmap = graphic_info[graphic].bitmap;
1107 src_x = graphic_info[graphic].src_x;
1108 src_y = graphic_info[graphic].src_y;
1109 offset_x = graphic_info[graphic].offset_x;
1110 offset_y = graphic_info[graphic].offset_y;
1112 src_x += frame * offset_x;
1113 src_y += frame * offset_y;
1116 drawing_gc = src_bitmap->stored_clip_gc;
1121 dest_x = FX + x * TILEX + dx;
1122 dest_y = FY + y * TILEY + dy;
1125 if (!IN_SCR_FIELD(x,y))
1127 printf("DrawGraphicShifted(): x = %d, y = %d, graphic = %d\n",x,y,graphic);
1128 printf("DrawGraphicShifted(): This should never happen!\n");
1133 if (mask_mode == USE_MASKING)
1135 SetClipOrigin(src_bitmap, drawing_gc, dest_x - src_x, dest_y - src_y);
1136 BlitBitmapMasked(src_bitmap, drawto_field, src_x, src_y, width, height,
1140 BlitBitmap(src_bitmap, drawto_field, src_x, src_y, width, height,
1143 MarkTileDirty(x, y);
1146 void DrawGraphicShiftedThruMask(int x, int y, int dx, int dy, int graphic,
1147 int frame, int cut_mode)
1149 DrawGraphicShifted(x, y, dx, dy, graphic, frame, cut_mode, USE_MASKING);
1152 void DrawScreenElementExt(int x, int y, int dx, int dy, int element,
1153 int cut_mode, int mask_mode)
1155 int lx = LEVELX(x), ly = LEVELY(y);
1159 if (IN_LEV_FIELD(lx, ly))
1161 SetRandomAnimationValue(lx, ly);
1163 graphic = el_act_dir2img(element, GfxAction[lx][ly], GfxDir[lx][ly]);
1164 frame = getGraphicAnimationFrame(graphic, GfxFrame[lx][ly]);
1166 else /* border element */
1168 graphic = el2img(element);
1169 frame = getGraphicAnimationFrame(graphic, -1);
1172 if (element == EL_EXPANDABLE_WALL)
1174 boolean left_stopped = FALSE, right_stopped = FALSE;
1176 if (!IN_LEV_FIELD(lx - 1, ly) || IS_WALL(Feld[lx - 1][ly]))
1177 left_stopped = TRUE;
1178 if (!IN_LEV_FIELD(lx + 1, ly) || IS_WALL(Feld[lx + 1][ly]))
1179 right_stopped = TRUE;
1181 if (left_stopped && right_stopped)
1183 else if (left_stopped)
1185 graphic = IMG_EXPANDABLE_WALL_GROWING_RIGHT;
1186 frame = graphic_info[graphic].anim_frames - 1;
1188 else if (right_stopped)
1190 graphic = IMG_EXPANDABLE_WALL_GROWING_LEFT;
1191 frame = graphic_info[graphic].anim_frames - 1;
1196 DrawGraphicShifted(x, y, dx, dy, graphic, frame, cut_mode, mask_mode);
1197 else if (mask_mode == USE_MASKING)
1198 DrawGraphicThruMask(x, y, graphic, frame);
1200 DrawGraphic(x, y, graphic, frame);
1203 void DrawLevelElementExt(int x, int y, int dx, int dy, int element,
1204 int cut_mode, int mask_mode)
1206 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1207 DrawScreenElementExt(SCREENX(x), SCREENY(y), dx, dy, element,
1208 cut_mode, mask_mode);
1211 void DrawScreenElementShifted(int x, int y, int dx, int dy, int element,
1214 DrawScreenElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
1217 void DrawLevelElementShifted(int x, int y, int dx, int dy, int element,
1220 DrawLevelElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
1223 void DrawLevelElementThruMask(int x, int y, int element)
1225 DrawLevelElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
1228 void DrawLevelFieldThruMask(int x, int y)
1230 DrawLevelElementExt(x, y, 0, 0, Feld[x][y], NO_CUTTING, USE_MASKING);
1233 #define TILE_GFX_ELEMENT(x, y) \
1234 (GfxElement[x][y] != EL_UNDEFINED && Feld[x][y] != EL_EXPLOSION ? \
1235 GfxElement[x][y] : Feld[x][y])
1237 static void DrawLevelFieldCrumbledSandExt(int x, int y, int graphic, int frame)
1241 int sx = SCREENX(x), sy = SCREENY(y);
1243 int width, height, cx, cy, i;
1245 int crumbled_border_size = graphic_info[graphic].border_size;
1247 int snip = TILEX / 8; /* number of border pixels from "crumbled graphic" */
1249 static int xy[4][2] =
1258 if (x == 0 && y == 7)
1259 printf("::: %d, %d [%d]\n", GfxElement[x][y], Feld[x][y],
1260 crumbled_border_size);
1263 if (!IN_LEV_FIELD(x, y))
1266 element = TILE_GFX_ELEMENT(x, y);
1268 /* crumble field itself */
1269 if (GFX_CRUMBLED(element) && !IS_MOVING(x, y))
1271 if (!IN_SCR_FIELD(sx, sy))
1274 getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
1276 for (i = 0; i < 4; i++)
1278 int xx = x + xy[i][0];
1279 int yy = y + xy[i][1];
1282 element = (IN_LEV_FIELD(xx, yy) ? TILE_GFX_ELEMENT(xx, yy) :
1285 element = (IN_LEV_FIELD(xx, yy) ? Feld[xx][yy] : BorderElement);
1288 /* check if neighbour field is of same type */
1289 if (GFX_CRUMBLED(element) && !IS_MOVING(xx, yy))
1293 if (Feld[x][y] == EL_CUSTOM_START + 123)
1294 printf("::: crumble [%d] THE CHAOS ENGINE (%d, %d): %d, %d\n",
1295 i, Feld[x][y], element,
1296 GFX_CRUMBLED(element), IS_MOVING(x, y));
1299 if (i == 1 || i == 2)
1301 width = crumbled_border_size;
1303 cx = (i == 2 ? TILEX - crumbled_border_size : 0);
1309 height = crumbled_border_size;
1311 cy = (i == 3 ? TILEY - crumbled_border_size : 0);
1314 BlitBitmap(src_bitmap, drawto_field, src_x + cx, src_y + cy,
1315 width, height, FX + sx * TILEX + cx, FY + sy * TILEY + cy);
1318 MarkTileDirty(sx, sy);
1320 else /* crumble neighbour fields */
1323 getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
1326 for (i = 0; i < 4; i++)
1328 int xx = x + xy[i][0];
1329 int yy = y + xy[i][1];
1330 int sxx = sx + xy[i][0];
1331 int syy = sy + xy[i][1];
1334 if (!IN_LEV_FIELD(xx, yy) ||
1335 !IN_SCR_FIELD(sxx, syy) ||
1339 element = TILE_GFX_ELEMENT(xx, yy);
1341 if (!GFX_CRUMBLED(element))
1344 if (!IN_LEV_FIELD(xx, yy) ||
1345 !IN_SCR_FIELD(sxx, syy) ||
1346 !GFX_CRUMBLED(Feld[xx][yy]) ||
1352 graphic = el_act2crm(Feld[xx][yy], ACTION_DEFAULT);
1353 crumbled_border_size = graphic_info[graphic].border_size;
1355 getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
1358 if (i == 1 || i == 2)
1360 width = crumbled_border_size;
1362 cx = (i == 1 ? TILEX - crumbled_border_size : 0);
1368 height = crumbled_border_size;
1370 cy = (i == 0 ? TILEY - crumbled_border_size : 0);
1373 BlitBitmap(src_bitmap, drawto_field, src_x + cx, src_y + cy,
1374 width, height, FX + sxx * TILEX + cx, FY + syy * TILEY + cy);
1376 MarkTileDirty(sxx, syy);
1381 void DrawLevelFieldCrumbledSand(int x, int y)
1386 if (!IN_LEV_FIELD(x, y))
1389 graphic = el_act2crm(Feld[x][y], ACTION_DEFAULT);
1391 DrawLevelFieldCrumbledSandExt(x, y, graphic, 0);
1393 DrawLevelFieldCrumbledSandExt(x, y, IMG_SAND_CRUMBLED, 0);
1397 void DrawLevelFieldCrumbledSandDigging(int x, int y, int direction,
1401 int graphic1 = el_act_dir2img(GfxElement[x][y], ACTION_DIGGING, direction);
1402 int graphic2 = el_act_dir2crm(GfxElement[x][y], ACTION_DIGGING, direction);
1404 int graphic1 = el_act_dir2img(EL_SAND, ACTION_DIGGING, direction);
1405 int graphic2 = el_act_dir2img(EL_SAND_CRUMBLED, ACTION_DIGGING, direction);
1407 int frame1 = getGraphicAnimationFrame(graphic1, step_frame);
1408 int frame2 = getGraphicAnimationFrame(graphic2, step_frame);
1409 int sx = SCREENX(x), sy = SCREENY(y);
1411 DrawGraphic(sx, sy, graphic1, frame1);
1412 DrawLevelFieldCrumbledSandExt(x, y, graphic2, frame2);
1415 void DrawLevelFieldCrumbledSandNeighbours(int x, int y)
1417 int sx = SCREENX(x), sy = SCREENY(y);
1418 static int xy[4][2] =
1427 for (i = 0; i < 4; i++)
1429 int xx = x + xy[i][0];
1430 int yy = y + xy[i][1];
1431 int sxx = sx + xy[i][0];
1432 int syy = sy + xy[i][1];
1434 if (!IN_LEV_FIELD(xx, yy) ||
1435 !IN_SCR_FIELD(sxx, syy) ||
1436 !GFX_CRUMBLED(Feld[xx][yy]) ||
1440 DrawLevelField(xx, yy);
1444 static int getBorderElement(int x, int y)
1448 { EL_STEELWALL_TOPLEFT, EL_INVISIBLE_STEELWALL_TOPLEFT },
1449 { EL_STEELWALL_TOPRIGHT, EL_INVISIBLE_STEELWALL_TOPRIGHT },
1450 { EL_STEELWALL_BOTTOMLEFT, EL_INVISIBLE_STEELWALL_BOTTOMLEFT },
1451 { EL_STEELWALL_BOTTOMRIGHT, EL_INVISIBLE_STEELWALL_BOTTOMRIGHT },
1452 { EL_STEELWALL_VERTICAL, EL_INVISIBLE_STEELWALL_VERTICAL },
1453 { EL_STEELWALL_HORIZONTAL, EL_INVISIBLE_STEELWALL_HORIZONTAL },
1454 { EL_STEELWALL, EL_INVISIBLE_STEELWALL }
1456 int steel_type = (BorderElement == EL_STEELWALL ? 0 : 1);
1457 int steel_position = (x == -1 && y == -1 ? 0 :
1458 x == lev_fieldx && y == -1 ? 1 :
1459 x == -1 && y == lev_fieldy ? 2 :
1460 x == lev_fieldx && y == lev_fieldy ? 3 :
1461 x == -1 || x == lev_fieldx ? 4 :
1462 y == -1 || y == lev_fieldy ? 5 : 6);
1464 return border[steel_position][steel_type];
1467 void DrawScreenElement(int x, int y, int element)
1469 DrawScreenElementExt(x, y, 0, 0, element, NO_CUTTING, NO_MASKING);
1470 DrawLevelFieldCrumbledSand(LEVELX(x), LEVELY(y));
1473 void DrawLevelElement(int x, int y, int element)
1475 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1476 DrawScreenElement(SCREENX(x), SCREENY(y), element);
1479 void DrawScreenField(int x, int y)
1481 int lx = LEVELX(x), ly = LEVELY(y);
1482 int element, content;
1484 if (!IN_LEV_FIELD(lx, ly))
1486 if (lx < -1 || lx > lev_fieldx || ly < -1 || ly > lev_fieldy)
1489 element = getBorderElement(lx, ly);
1491 DrawScreenElement(x, y, element);
1495 element = Feld[lx][ly];
1496 content = Store[lx][ly];
1498 if (IS_MOVING(lx, ly))
1500 int horiz_move = (MovDir[lx][ly] == MV_LEFT || MovDir[lx][ly] == MV_RIGHT);
1501 boolean cut_mode = NO_CUTTING;
1503 if (element == EL_QUICKSAND_EMPTYING ||
1504 element == EL_MAGIC_WALL_EMPTYING ||
1505 element == EL_BD_MAGIC_WALL_EMPTYING ||
1506 element == EL_AMOEBA_DROPPING)
1507 cut_mode = CUT_ABOVE;
1508 else if (element == EL_QUICKSAND_FILLING ||
1509 element == EL_MAGIC_WALL_FILLING ||
1510 element == EL_BD_MAGIC_WALL_FILLING)
1511 cut_mode = CUT_BELOW;
1513 if (cut_mode == CUT_ABOVE)
1514 DrawScreenElementShifted(x, y, 0, 0, element, NO_CUTTING);
1516 DrawScreenElement(x, y, EL_EMPTY);
1519 DrawScreenElementShifted(x, y, MovPos[lx][ly], 0, element, NO_CUTTING);
1520 else if (cut_mode == NO_CUTTING)
1521 DrawScreenElementShifted(x, y, 0, MovPos[lx][ly], element, cut_mode);
1523 DrawScreenElementShifted(x, y, 0, MovPos[lx][ly], content, cut_mode);
1525 if (content == EL_ACID)
1527 int dir = MovDir[lx][ly];
1528 int newlx = lx + (dir == MV_LEFT ? -1 : dir == MV_RIGHT ? +1 : 0);
1529 int newly = ly + (dir == MV_UP ? -1 : dir == MV_DOWN ? +1 : 0);
1531 DrawLevelElementThruMask(newlx, newly, EL_ACID);
1534 else if (IS_BLOCKED(lx, ly))
1539 boolean cut_mode = NO_CUTTING;
1540 int element_old, content_old;
1542 Blocked2Moving(lx, ly, &oldx, &oldy);
1545 horiz_move = (MovDir[oldx][oldy] == MV_LEFT ||
1546 MovDir[oldx][oldy] == MV_RIGHT);
1548 element_old = Feld[oldx][oldy];
1549 content_old = Store[oldx][oldy];
1551 if (element_old == EL_QUICKSAND_EMPTYING ||
1552 element_old == EL_MAGIC_WALL_EMPTYING ||
1553 element_old == EL_BD_MAGIC_WALL_EMPTYING ||
1554 element_old == EL_AMOEBA_DROPPING)
1555 cut_mode = CUT_ABOVE;
1557 DrawScreenElement(x, y, EL_EMPTY);
1560 DrawScreenElementShifted(sx, sy, MovPos[oldx][oldy], 0, element_old,
1562 else if (cut_mode == NO_CUTTING)
1563 DrawScreenElementShifted(sx, sy, 0, MovPos[oldx][oldy], element_old,
1566 DrawScreenElementShifted(sx, sy, 0, MovPos[oldx][oldy], content_old,
1569 else if (IS_DRAWABLE(element))
1570 DrawScreenElement(x, y, element);
1572 DrawScreenElement(x, y, EL_EMPTY);
1575 void DrawLevelField(int x, int y)
1577 if (IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1578 DrawScreenField(SCREENX(x), SCREENY(y));
1579 else if (IS_MOVING(x, y))
1583 Moving2Blocked(x, y, &newx, &newy);
1584 if (IN_SCR_FIELD(SCREENX(newx), SCREENY(newy)))
1585 DrawScreenField(SCREENX(newx), SCREENY(newy));
1587 else if (IS_BLOCKED(x, y))
1591 Blocked2Moving(x, y, &oldx, &oldy);
1592 if (IN_SCR_FIELD(SCREENX(oldx), SCREENY(oldy)))
1593 DrawScreenField(SCREENX(oldx), SCREENY(oldy));
1597 void DrawMiniElement(int x, int y, int element)
1601 graphic = el2edimg(element);
1602 DrawMiniGraphic(x, y, graphic);
1605 void DrawMiniElementOrWall(int sx, int sy, int scroll_x, int scroll_y)
1607 int x = sx + scroll_x, y = sy + scroll_y;
1609 if (x < -1 || x > lev_fieldx || y < -1 || y > lev_fieldy)
1610 DrawMiniElement(sx, sy, EL_EMPTY);
1611 else if (x > -1 && x < lev_fieldx && y > -1 && y < lev_fieldy)
1612 DrawMiniElement(sx, sy, Feld[x][y]);
1614 DrawMiniGraphic(sx, sy, el2edimg(getBorderElement(x, y)));
1617 void DrawEnvelopeBackground(int envelope_nr, int startx, int starty,
1618 int x, int y, int xsize, int ysize, int font_nr)
1620 int font_width = getFontWidth(font_nr);
1621 int font_height = getFontHeight(font_nr);
1622 int graphic = IMG_BACKGROUND_ENVELOPE_1 + envelope_nr;
1625 int dst_x = SX + startx + x * font_width;
1626 int dst_y = SY + starty + y * font_height;
1627 int width = graphic_info[graphic].width;
1628 int height = graphic_info[graphic].height;
1629 int inner_width = MAX(width - 2 * font_width, font_width);
1630 int inner_height = MAX(height - 2 * font_height, font_height);
1631 int inner_sx = (width >= 3 * font_width ? font_width : 0);
1632 int inner_sy = (height >= 3 * font_height ? font_height : 0);
1633 boolean draw_masked = graphic_info[graphic].draw_masked;
1635 getGraphicSource(graphic, 0, &src_bitmap, &src_x, &src_y);
1637 if (src_bitmap == NULL || width < font_width || height < font_height)
1639 ClearRectangle(drawto, dst_x, dst_y, font_width, font_height);
1643 src_x += (x == 0 ? 0 : x == xsize - 1 ? width - font_width :
1644 inner_sx + (x - 1) * font_width % inner_width);
1645 src_y += (y == 0 ? 0 : y == ysize - 1 ? height - font_height :
1646 inner_sy + (y - 1) * font_height % inner_height);
1650 SetClipOrigin(src_bitmap, src_bitmap->stored_clip_gc,
1651 dst_x - src_x, dst_y - src_y);
1652 BlitBitmapMasked(src_bitmap, drawto, src_x, src_y, font_width, font_height,
1656 BlitBitmap(src_bitmap, drawto, src_x, src_y, font_width, font_height,
1660 void AnimateEnvelope(int envelope_nr, int anim_mode, int action)
1662 int graphic = IMG_BACKGROUND_ENVELOPE_1 + envelope_nr;
1663 boolean draw_masked = graphic_info[graphic].draw_masked;
1664 int mask_mode = (draw_masked ? BLIT_MASKED : BLIT_ON_BACKGROUND);
1665 boolean ffwd_delay = (tape.playing && tape.fast_forward);
1666 boolean no_delay = (tape.warp_forward);
1667 unsigned long anim_delay = 0;
1668 int frame_delay_value = (ffwd_delay ? FfwdFrameDelay : GameFrameDelay);
1669 int anim_delay_value = (no_delay ? 0 : frame_delay_value);
1670 int font_nr = FONT_ENVELOPE_1 + envelope_nr;
1671 int font_width = getFontWidth(font_nr);
1672 int font_height = getFontHeight(font_nr);
1673 int max_xsize = level.envelope_xsize[envelope_nr];
1674 int max_ysize = level.envelope_ysize[envelope_nr];
1675 int xstart = (anim_mode & ANIM_VERTICAL ? max_xsize : 0);
1676 int ystart = (anim_mode & ANIM_HORIZONTAL ? max_ysize : 0);
1677 int xend = max_xsize;
1678 int yend = (anim_mode != ANIM_DEFAULT ? max_ysize : 0);
1679 int xstep = (xstart < xend ? 1 : 0);
1680 int ystep = (ystart < yend || xstep == 0 ? 1 : 0);
1683 for (x = xstart, y = ystart; x <= xend && y <= yend; x += xstep, y += ystep)
1685 int xsize = (action == ACTION_CLOSING ? xend - (x - xstart) : x) + 2;
1686 int ysize = (action == ACTION_CLOSING ? yend - (y - ystart) : y) + 2;
1687 int sx = (SXSIZE - xsize * font_width) / 2;
1688 int sy = (SYSIZE - ysize * font_height) / 2;
1691 SetDrawtoField(DRAW_BUFFERED);
1693 BlitBitmap(fieldbuffer, backbuffer, FX, FY, SXSIZE, SYSIZE, SX, SY);
1695 SetDrawtoField(DRAW_BACKBUFFER);
1697 for (yy = 0; yy < ysize; yy++) for (xx = 0; xx < xsize; xx++)
1698 DrawEnvelopeBackground(envelope_nr, sx,sy, xx,yy, xsize, ysize, font_nr);
1700 DrawTextToTextArea(SX + sx + font_width, SY + sy + font_height,
1701 level.envelope_text[envelope_nr], font_nr, max_xsize,
1702 xsize - 2, ysize - 2, mask_mode);
1704 redraw_mask |= REDRAW_FIELD | REDRAW_FROM_BACKBUFFER;
1707 WaitUntilDelayReached(&anim_delay, anim_delay_value / 2);
1711 void ShowEnvelope(int envelope_nr)
1713 int element = EL_ENVELOPE_1 + envelope_nr;
1714 int graphic = IMG_BACKGROUND_ENVELOPE_1 + envelope_nr;
1715 int sound_opening = element_info[element].sound[ACTION_OPENING];
1716 int sound_closing = element_info[element].sound[ACTION_CLOSING];
1717 boolean ffwd_delay = (tape.playing && tape.fast_forward);
1718 boolean no_delay = (tape.warp_forward);
1719 int normal_delay_value = ONE_SECOND_DELAY / (ffwd_delay ? 2 : 1);
1720 int wait_delay_value = (no_delay ? 0 : normal_delay_value);
1721 int anim_mode = graphic_info[graphic].anim_mode;
1722 int main_anim_mode = (anim_mode == ANIM_NONE ? ANIM_VERTICAL|ANIM_HORIZONTAL:
1723 anim_mode == ANIM_DEFAULT ? ANIM_VERTICAL : anim_mode);
1725 game.envelope_active = TRUE; /* needed for RedrawPlayfield() events */
1727 PlaySoundStereo(sound_opening, SOUND_MIDDLE);
1729 if (anim_mode == ANIM_DEFAULT)
1730 AnimateEnvelope(envelope_nr, ANIM_DEFAULT, ACTION_OPENING);
1732 AnimateEnvelope(envelope_nr, main_anim_mode, ACTION_OPENING);
1735 Delay(wait_delay_value);
1737 WaitForEventToContinue();
1739 PlaySoundStereo(sound_closing, SOUND_MIDDLE);
1741 if (anim_mode != ANIM_NONE)
1742 AnimateEnvelope(envelope_nr, main_anim_mode, ACTION_CLOSING);
1744 if (anim_mode == ANIM_DEFAULT)
1745 AnimateEnvelope(envelope_nr, ANIM_DEFAULT, ACTION_CLOSING);
1747 game.envelope_active = FALSE;
1749 SetDrawtoField(DRAW_BUFFERED);
1751 redraw_mask |= REDRAW_FIELD;
1755 void getMicroGraphicSource(int graphic, Bitmap **bitmap, int *x, int *y)
1757 Bitmap *src_bitmap = graphic_info[graphic].bitmap;
1758 int mini_startx = src_bitmap->width * 3 / 4;
1759 int mini_starty = src_bitmap->height * 2 / 3;
1760 int src_x = mini_startx + graphic_info[graphic].src_x / 8;
1761 int src_y = mini_starty + graphic_info[graphic].src_y / 8;
1763 *bitmap = src_bitmap;
1768 void DrawMicroElement(int xpos, int ypos, int element)
1772 int graphic = el2preimg(element);
1774 getMicroGraphicSource(graphic, &src_bitmap, &src_x, &src_y);
1775 BlitBitmap(src_bitmap, drawto, src_x, src_y, MICRO_TILEX, MICRO_TILEY,
1783 SetDrawBackgroundMask(REDRAW_NONE);
1786 for (x = BX1; x <= BX2; x++)
1787 for (y = BY1; y <= BY2; y++)
1788 DrawScreenField(x, y);
1790 redraw_mask |= REDRAW_FIELD;
1793 void DrawMiniLevel(int size_x, int size_y, int scroll_x, int scroll_y)
1797 for (x = 0; x < size_x; x++)
1798 for (y = 0; y < size_y; y++)
1799 DrawMiniElementOrWall(x, y, scroll_x, scroll_y);
1801 redraw_mask |= REDRAW_FIELD;
1804 static void DrawMicroLevelExt(int xpos, int ypos, int from_x, int from_y)
1808 DrawBackground(xpos, ypos, MICROLEV_XSIZE, MICROLEV_YSIZE);
1810 if (lev_fieldx < STD_LEV_FIELDX)
1811 xpos += (STD_LEV_FIELDX - lev_fieldx) / 2 * MICRO_TILEX;
1812 if (lev_fieldy < STD_LEV_FIELDY)
1813 ypos += (STD_LEV_FIELDY - lev_fieldy) / 2 * MICRO_TILEY;
1815 xpos += MICRO_TILEX;
1816 ypos += MICRO_TILEY;
1818 for (x = -1; x <= STD_LEV_FIELDX; x++)
1820 for (y = -1; y <= STD_LEV_FIELDY; y++)
1822 int lx = from_x + x, ly = from_y + y;
1824 if (lx >= 0 && lx < lev_fieldx && ly >= 0 && ly < lev_fieldy)
1825 DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
1826 level.field[lx][ly]);
1827 else if (lx >= -1 && lx < lev_fieldx+1 && ly >= -1 && ly < lev_fieldy+1
1828 && BorderElement != EL_EMPTY)
1829 DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
1830 getBorderElement(lx, ly));
1834 redraw_mask |= REDRAW_MICROLEVEL;
1837 #define MICROLABEL_EMPTY 0
1838 #define MICROLABEL_LEVEL_NAME 1
1839 #define MICROLABEL_CREATED_BY 2
1840 #define MICROLABEL_LEVEL_AUTHOR 3
1841 #define MICROLABEL_IMPORTED_FROM 4
1842 #define MICROLABEL_LEVEL_IMPORT_INFO 5
1844 static void DrawMicroLevelLabelExt(int mode)
1846 char label_text[MAX_OUTPUT_LINESIZE + 1];
1847 int max_len_label_text;
1848 int font_nr = FONT_TEXT_2;
1850 if (mode == MICROLABEL_CREATED_BY || mode == MICROLABEL_IMPORTED_FROM)
1851 font_nr = FONT_TEXT_3;
1853 max_len_label_text = SXSIZE / getFontWidth(font_nr);
1855 DrawBackground(SX, MICROLABEL_YPOS, SXSIZE, getFontHeight(font_nr));
1857 strncpy(label_text, (mode == MICROLABEL_LEVEL_NAME ? level.name :
1858 mode == MICROLABEL_CREATED_BY ? "created by" :
1859 mode == MICROLABEL_LEVEL_AUTHOR ? level.author :
1860 mode == MICROLABEL_IMPORTED_FROM ? "imported from" :
1861 mode == MICROLABEL_LEVEL_IMPORT_INFO ?
1862 leveldir_current->imported_from : ""),
1863 max_len_label_text);
1864 label_text[max_len_label_text] = '\0';
1866 if (strlen(label_text) > 0)
1868 int lxpos = SX + (SXSIZE - getTextWidth(label_text, font_nr)) / 2;
1869 int lypos = MICROLABEL_YPOS;
1871 DrawText(lxpos, lypos, label_text, font_nr);
1874 redraw_mask |= REDRAW_MICROLEVEL;
1877 void DrawMicroLevel(int xpos, int ypos, boolean restart)
1879 static unsigned long scroll_delay = 0;
1880 static unsigned long label_delay = 0;
1881 static int from_x, from_y, scroll_direction;
1882 static int label_state, label_counter;
1883 int last_game_status = game_status; /* save current game status */
1885 /* force PREVIEW font on preview level */
1886 game_status = GAME_MODE_PSEUDO_PREVIEW;
1890 from_x = from_y = 0;
1891 scroll_direction = MV_RIGHT;
1895 DrawMicroLevelExt(xpos, ypos, from_x, from_y);
1896 DrawMicroLevelLabelExt(label_state);
1898 /* initialize delay counters */
1899 DelayReached(&scroll_delay, 0);
1900 DelayReached(&label_delay, 0);
1902 if (leveldir_current->name)
1904 int text_width = getTextWidth(leveldir_current->name, FONT_TEXT_1);
1905 int lxpos = SX + (SXSIZE - text_width) / 2;
1906 int lypos = SY + 352;
1908 DrawText(lxpos, lypos, leveldir_current->name, FONT_TEXT_1);
1911 game_status = last_game_status; /* restore current game status */
1916 /* scroll micro level, if needed */
1917 if ((lev_fieldx > STD_LEV_FIELDX || lev_fieldy > STD_LEV_FIELDY) &&
1918 DelayReached(&scroll_delay, MICROLEVEL_SCROLL_DELAY))
1920 switch (scroll_direction)
1926 scroll_direction = MV_UP;
1930 if (from_x < lev_fieldx - STD_LEV_FIELDX)
1933 scroll_direction = MV_DOWN;
1940 scroll_direction = MV_RIGHT;
1944 if (from_y < lev_fieldy - STD_LEV_FIELDY)
1947 scroll_direction = MV_LEFT;
1954 DrawMicroLevelExt(xpos, ypos, from_x, from_y);
1957 /* redraw micro level label, if needed */
1958 if (strcmp(level.name, NAMELESS_LEVEL_NAME) != 0 &&
1959 strcmp(level.author, ANONYMOUS_NAME) != 0 &&
1960 strcmp(level.author, leveldir_current->name) != 0 &&
1961 DelayReached(&label_delay, MICROLEVEL_LABEL_DELAY))
1963 int max_label_counter = 23;
1965 if (leveldir_current->imported_from != NULL)
1966 max_label_counter += 14;
1968 label_counter = (label_counter + 1) % max_label_counter;
1969 label_state = (label_counter >= 0 && label_counter <= 7 ?
1970 MICROLABEL_LEVEL_NAME :
1971 label_counter >= 9 && label_counter <= 12 ?
1972 MICROLABEL_CREATED_BY :
1973 label_counter >= 14 && label_counter <= 21 ?
1974 MICROLABEL_LEVEL_AUTHOR :
1975 label_counter >= 23 && label_counter <= 26 ?
1976 MICROLABEL_IMPORTED_FROM :
1977 label_counter >= 28 && label_counter <= 35 ?
1978 MICROLABEL_LEVEL_IMPORT_INFO : MICROLABEL_EMPTY);
1979 DrawMicroLevelLabelExt(label_state);
1982 game_status = last_game_status; /* restore current game status */
1985 void WaitForEventToContinue()
1987 boolean still_wait = TRUE;
1989 /* simulate releasing mouse button over last gadget, if still pressed */
1991 HandleGadgets(-1, -1, 0);
1993 button_status = MB_RELEASED;
2005 case EVENT_BUTTONPRESS:
2006 case EVENT_KEYPRESS:
2010 case EVENT_KEYRELEASE:
2011 ClearPlayerAction();
2015 HandleOtherEvents(&event);
2019 else if (AnyJoystickButton() == JOY_BUTTON_NEW_PRESSED)
2026 /* don't eat all CPU time */
2031 #define MAX_REQUEST_LINES 13
2032 #define MAX_REQUEST_LINE_FONT1_LEN 7
2033 #define MAX_REQUEST_LINE_FONT2_LEN 10
2035 boolean Request(char *text, unsigned int req_state)
2037 int mx, my, ty, result = -1;
2038 unsigned int old_door_state;
2039 int last_game_status = game_status; /* save current game status */
2040 int max_request_line_len = MAX_REQUEST_LINE_FONT1_LEN;
2041 int font_nr = FONT_TEXT_2;
2042 int max_word_len = 0;
2045 for (text_ptr = text; *text_ptr; text_ptr++)
2047 max_word_len = (*text_ptr != ' ' ? max_word_len + 1 : 0);
2049 if (max_word_len > MAX_REQUEST_LINE_FONT1_LEN)
2051 max_request_line_len = MAX_REQUEST_LINE_FONT2_LEN;
2052 font_nr = FONT_LEVEL_NUMBER;
2059 /* disable deactivated drawing when quick-loading level tape recording */
2060 if (tape.playing && tape.deactivate_display)
2061 TapeDeactivateDisplayOff(TRUE);
2065 SetMouseCursor(CURSOR_DEFAULT);
2068 #if defined(PLATFORM_UNIX)
2069 /* pause network game while waiting for request to answer */
2070 if (options.network &&
2071 game_status == GAME_MODE_PLAYING &&
2072 req_state & REQUEST_WAIT_FOR)
2073 SendToServer_PausePlaying();
2076 old_door_state = GetDoorState();
2078 /* simulate releasing mouse button over last gadget, if still pressed */
2080 HandleGadgets(-1, -1, 0);
2084 CloseDoor(DOOR_CLOSE_1);
2086 /* save old door content */
2087 BlitBitmap(bitmap_db_door, bitmap_db_door,
2088 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE,
2089 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1);
2091 SetDrawBackgroundMask(REDRAW_FIELD | REDRAW_DOOR_1);
2093 /* clear door drawing field */
2094 DrawBackground(DX, DY, DXSIZE, DYSIZE);
2096 /* force DOOR font on preview level */
2097 game_status = GAME_MODE_PSEUDO_DOOR;
2099 /* write text for request */
2100 for (ty = 0; ty < MAX_REQUEST_LINES; ty++)
2102 char text_line[max_request_line_len + 1];
2108 for (tl = 0, tx = 0; tx < max_request_line_len; tl++, tx++)
2111 if (!tc || tc == ' ')
2122 strncpy(text_line, text, tl);
2125 DrawText(DX + (DXSIZE - tl * getFontWidth(font_nr)) / 2,
2126 DY + 8 + ty * (getFontHeight(font_nr) + 2),
2127 text_line, font_nr);
2129 text += tl + (tc == ' ' ? 1 : 0);
2132 game_status = last_game_status; /* restore current game status */
2134 if (req_state & REQ_ASK)
2136 MapGadget(tool_gadget[TOOL_CTRL_ID_YES]);
2137 MapGadget(tool_gadget[TOOL_CTRL_ID_NO]);
2139 else if (req_state & REQ_CONFIRM)
2141 MapGadget(tool_gadget[TOOL_CTRL_ID_CONFIRM]);
2143 else if (req_state & REQ_PLAYER)
2145 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_1]);
2146 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_2]);
2147 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_3]);
2148 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_4]);
2151 /* copy request gadgets to door backbuffer */
2152 BlitBitmap(drawto, bitmap_db_door,
2153 DX, DY, DXSIZE, DYSIZE,
2154 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
2156 OpenDoor(DOOR_OPEN_1);
2162 if (!(req_state & REQUEST_WAIT_FOR))
2164 SetDrawBackgroundMask(REDRAW_FIELD);
2169 if (game_status != GAME_MODE_MAIN)
2172 button_status = MB_RELEASED;
2174 request_gadget_id = -1;
2176 SetDrawBackgroundMask(REDRAW_FIELD | REDRAW_DOOR_1);
2179 SetMouseCursor(CURSOR_DEFAULT);
2192 case EVENT_BUTTONPRESS:
2193 case EVENT_BUTTONRELEASE:
2194 case EVENT_MOTIONNOTIFY:
2196 if (event.type == EVENT_MOTIONNOTIFY)
2198 if (!PointerInWindow(window))
2199 continue; /* window and pointer are on different screens */
2204 motion_status = TRUE;
2205 mx = ((MotionEvent *) &event)->x;
2206 my = ((MotionEvent *) &event)->y;
2210 motion_status = FALSE;
2211 mx = ((ButtonEvent *) &event)->x;
2212 my = ((ButtonEvent *) &event)->y;
2213 if (event.type == EVENT_BUTTONPRESS)
2214 button_status = ((ButtonEvent *) &event)->button;
2216 button_status = MB_RELEASED;
2219 /* this sets 'request_gadget_id' */
2220 HandleGadgets(mx, my, button_status);
2222 switch(request_gadget_id)
2224 case TOOL_CTRL_ID_YES:
2227 case TOOL_CTRL_ID_NO:
2230 case TOOL_CTRL_ID_CONFIRM:
2231 result = TRUE | FALSE;
2234 case TOOL_CTRL_ID_PLAYER_1:
2237 case TOOL_CTRL_ID_PLAYER_2:
2240 case TOOL_CTRL_ID_PLAYER_3:
2243 case TOOL_CTRL_ID_PLAYER_4:
2254 case EVENT_KEYPRESS:
2255 switch(GetEventKey((KeyEvent *)&event, TRUE))
2268 if (req_state & REQ_PLAYER)
2272 case EVENT_KEYRELEASE:
2273 ClearPlayerAction();
2277 HandleOtherEvents(&event);
2281 else if (AnyJoystickButton() == JOY_BUTTON_NEW_PRESSED)
2283 int joy = AnyJoystick();
2285 if (joy & JOY_BUTTON_1)
2287 else if (joy & JOY_BUTTON_2)
2293 /* don't eat all CPU time */
2297 if (game_status != GAME_MODE_MAIN)
2302 if (!(req_state & REQ_STAY_OPEN))
2304 CloseDoor(DOOR_CLOSE_1);
2306 if (!(req_state & REQ_STAY_CLOSED) && (old_door_state & DOOR_OPEN_1))
2308 BlitBitmap(bitmap_db_door, bitmap_db_door,
2309 DOOR_GFX_PAGEX2,DOOR_GFX_PAGEY1, DXSIZE,DYSIZE,
2310 DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY1);
2311 OpenDoor(DOOR_OPEN_1);
2317 SetDrawBackgroundMask(REDRAW_FIELD);
2319 #if defined(PLATFORM_UNIX)
2320 /* continue network game after request */
2321 if (options.network &&
2322 game_status == GAME_MODE_PLAYING &&
2323 req_state & REQUEST_WAIT_FOR)
2324 SendToServer_ContinuePlaying();
2328 /* restore deactivated drawing when quick-loading level tape recording */
2329 if (tape.playing && tape.deactivate_display)
2330 TapeDeactivateDisplayOn();
2336 unsigned int OpenDoor(unsigned int door_state)
2338 unsigned int new_door_state;
2340 if (door_state & DOOR_COPY_BACK)
2342 BlitBitmap(bitmap_db_door, bitmap_db_door,
2343 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE + VYSIZE,
2344 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
2345 door_state &= ~DOOR_COPY_BACK;
2348 new_door_state = MoveDoor(door_state);
2350 return(new_door_state);
2353 unsigned int CloseDoor(unsigned int door_state)
2355 unsigned int new_door_state;
2357 BlitBitmap(backbuffer, bitmap_db_door,
2358 DX, DY, DXSIZE, DYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
2359 BlitBitmap(backbuffer, bitmap_db_door,
2360 VX, VY, VXSIZE, VYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2);
2362 new_door_state = MoveDoor(door_state);
2364 return(new_door_state);
2367 unsigned int GetDoorState()
2369 return MoveDoor(DOOR_GET_STATE);
2372 unsigned int SetDoorState(unsigned int door_state)
2374 return MoveDoor(door_state | DOOR_SET_STATE);
2377 unsigned int MoveDoor(unsigned int door_state)
2379 static int door1 = DOOR_OPEN_1;
2380 static int door2 = DOOR_CLOSE_2;
2381 unsigned long door_delay = 0;
2382 unsigned long door_delay_value;
2385 if (door_state == DOOR_GET_STATE)
2386 return(door1 | door2);
2388 if (door_state & DOOR_SET_STATE)
2390 if (door_state & DOOR_ACTION_1)
2391 door1 = door_state & DOOR_ACTION_1;
2392 if (door_state & DOOR_ACTION_2)
2393 door2 = door_state & DOOR_ACTION_2;
2395 return(door1 | door2);
2398 if (door1 == DOOR_OPEN_1 && door_state & DOOR_OPEN_1)
2399 door_state &= ~DOOR_OPEN_1;
2400 else if (door1 == DOOR_CLOSE_1 && door_state & DOOR_CLOSE_1)
2401 door_state &= ~DOOR_CLOSE_1;
2402 if (door2 == DOOR_OPEN_2 && door_state & DOOR_OPEN_2)
2403 door_state &= ~DOOR_OPEN_2;
2404 else if (door2 == DOOR_CLOSE_2 && door_state & DOOR_CLOSE_2)
2405 door_state &= ~DOOR_CLOSE_2;
2407 door_delay_value = (door_state & DOOR_ACTION_1 ? door_1.step_delay :
2410 if (setup.quick_doors)
2412 stepsize = 20; /* must be choosen to always draw last frame */
2413 door_delay_value = 0;
2416 StopSound(SND_DOOR_OPENING);
2417 StopSound(SND_DOOR_CLOSING);
2421 if (global.autoplay_leveldir)
2423 door_state |= DOOR_NO_DELAY;
2424 door_state &= ~DOOR_CLOSE_ALL;
2427 if (door_state & DOOR_ACTION)
2429 boolean door_1_done = !(door_state & DOOR_ACTION_1);
2430 boolean door_2_done = !(door_state & DOOR_ACTION_2);
2431 int start = ((door_state & DOOR_NO_DELAY) ? DXSIZE : 0);
2432 int end = (door_state & DOOR_ACTION_1 &&
2433 door_1.anim_mode == ANIM_VERTICAL ? DYSIZE : DXSIZE);
2436 if (!(door_state & DOOR_NO_DELAY) && !setup.quick_doors)
2438 /* opening door sound has priority over simultaneously closing door */
2439 if (door_state & (DOOR_OPEN_1 | DOOR_OPEN_2))
2440 PlaySoundStereo(SND_DOOR_OPENING, SOUND_MIDDLE);
2441 else if (door_state & (DOOR_CLOSE_1 | DOOR_CLOSE_2))
2442 PlaySoundStereo(SND_DOOR_CLOSING, SOUND_MIDDLE);
2445 for (x = start; x <= end && !(door_1_done && door_2_done); x += stepsize)
2447 Bitmap *bitmap = graphic_info[IMG_GLOBAL_DOOR].bitmap;
2448 GC gc = bitmap->stored_clip_gc;
2450 if (door_state & DOOR_ACTION_1)
2452 int a = MIN(x * door_1.step_offset, end);
2453 int i = (door_state & DOOR_OPEN_1 ? end - a : a);
2457 BlitBitmap(bitmap_db_door, drawto,
2458 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1 + i / 2,
2459 DXSIZE,DYSIZE - i / 2, DX, DY);
2461 ClearRectangle(drawto, DX, DY + DYSIZE - i / 2, DXSIZE, i / 2);
2464 if (door_1.anim_mode == ANIM_HORIZONTAL && x <= DXSIZE)
2466 int src1_x = DXSIZE, src1_y = DOOR_GFX_PAGEY1;
2467 int dst1_x = DX + DXSIZE - i, dst1_y = DY;
2468 int src2_x = DXSIZE - i, src2_y = DOOR_GFX_PAGEY1;
2469 int dst2_x = DX, dst2_y = DY;
2470 int width = i, height = DYSIZE;
2472 SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y);
2473 BlitBitmapMasked(bitmap, drawto, src1_x, src1_y, width, height,
2476 SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y);
2477 BlitBitmapMasked(bitmap, drawto, src2_x, src2_y, width, height,
2480 else if (door_1.anim_mode == ANIM_VERTICAL && x <= DYSIZE)
2482 int src1_x = DXSIZE, src1_y = DOOR_GFX_PAGEY1;
2483 int dst1_x = DX, dst1_y = DY + DYSIZE - i;
2484 int src2_x = 0, src2_y = DOOR_GFX_PAGEY1 + DYSIZE - i;
2485 int dst2_x = DX, dst2_y = DY;
2486 int width = DXSIZE, height = i;
2488 SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y);
2489 BlitBitmapMasked(bitmap, drawto, src1_x, src1_y, width, height,
2492 SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y);
2493 BlitBitmapMasked(bitmap, drawto, src2_x, src2_y, width, height,
2496 else if (x <= DXSIZE) /* ANIM_DEFAULT */
2498 int j = (door_1.anim_mode == ANIM_DEFAULT ? (DXSIZE - i) / 3 : 0);
2500 SetClipOrigin(bitmap, gc, DX - i, (DY + j) - DOOR_GFX_PAGEY1);
2501 BlitBitmapMasked(bitmap, drawto,
2502 DXSIZE, DOOR_GFX_PAGEY1, i, 77,
2503 DX + DXSIZE - i, DY + j);
2504 BlitBitmapMasked(bitmap, drawto,
2505 DXSIZE, DOOR_GFX_PAGEY1 + 140, i, 63,
2506 DX + DXSIZE - i, DY + 140 + j);
2507 SetClipOrigin(bitmap, gc, DX - DXSIZE + i,
2508 DY - (DOOR_GFX_PAGEY1 + j));
2509 BlitBitmapMasked(bitmap, drawto,
2510 DXSIZE - i, DOOR_GFX_PAGEY1 + j, i, 77 - j,
2512 BlitBitmapMasked(bitmap, drawto,
2513 DXSIZE-i, DOOR_GFX_PAGEY1 + 140, i, 63,
2516 BlitBitmapMasked(bitmap, drawto,
2517 DXSIZE - i, DOOR_GFX_PAGEY1 + 77, i, 63,
2519 BlitBitmapMasked(bitmap, drawto,
2520 DXSIZE - i, DOOR_GFX_PAGEY1 + 203, i, 77,
2522 SetClipOrigin(bitmap, gc, DX - i, (DY + j) - DOOR_GFX_PAGEY1);
2523 BlitBitmapMasked(bitmap, drawto,
2524 DXSIZE, DOOR_GFX_PAGEY1 + 77, i, 63,
2525 DX + DXSIZE - i, DY + 77 + j);
2526 BlitBitmapMasked(bitmap, drawto,
2527 DXSIZE, DOOR_GFX_PAGEY1 + 203, i, 77 - j,
2528 DX + DXSIZE - i, DY + 203 + j);
2531 redraw_mask |= REDRAW_DOOR_1;
2532 door_1_done = (a == end);
2535 if (door_state & DOOR_ACTION_2)
2537 int a = MIN(x * door_2.step_offset, VXSIZE);
2538 int i = (door_state & DOOR_OPEN_2 ? VXSIZE - a : a);
2542 BlitBitmap(bitmap_db_door, drawto,
2543 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2 + i / 2,
2544 VXSIZE, VYSIZE - i / 2, VX, VY);
2546 ClearRectangle(drawto, VX, VY + VYSIZE - i / 2, VXSIZE, i / 2);
2549 if (door_2.anim_mode == ANIM_HORIZONTAL && x <= VXSIZE)
2551 int src1_x = VXSIZE, src1_y = DOOR_GFX_PAGEY2;
2552 int dst1_x = VX + VXSIZE - i, dst1_y = VY;
2553 int src2_x = VXSIZE - i, src2_y = DOOR_GFX_PAGEY2;
2554 int dst2_x = VX, dst2_y = VY;
2555 int width = i, height = VYSIZE;
2557 SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y);
2558 BlitBitmapMasked(bitmap, drawto, src1_x, src1_y, width, height,
2561 SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y);
2562 BlitBitmapMasked(bitmap, drawto, src2_x, src2_y, width, height,
2565 else if (door_2.anim_mode == ANIM_VERTICAL && x <= VYSIZE)
2567 int src1_x = VXSIZE, src1_y = DOOR_GFX_PAGEY2;
2568 int dst1_x = VX, dst1_y = VY + VYSIZE - i;
2569 int src2_x = 0, src2_y = DOOR_GFX_PAGEY2 + VYSIZE - i;
2570 int dst2_x = VX, dst2_y = VY;
2571 int width = VXSIZE, height = i;
2573 SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y);
2574 BlitBitmapMasked(bitmap, drawto, src1_x, src1_y, width, height,
2577 SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y);
2578 BlitBitmapMasked(bitmap, drawto, src2_x, src2_y, width, height,
2581 else if (x <= VXSIZE) /* ANIM_DEFAULT */
2583 int j = (door_2.anim_mode == ANIM_DEFAULT ? (VXSIZE - i) / 3 : 0);
2585 SetClipOrigin(bitmap, gc, VX - i, (VY + j) - DOOR_GFX_PAGEY2);
2586 BlitBitmapMasked(bitmap, drawto,
2587 VXSIZE, DOOR_GFX_PAGEY2, i, VYSIZE / 2,
2588 VX + VXSIZE - i, VY + j);
2589 SetClipOrigin(bitmap, gc,
2590 VX - VXSIZE + i, VY - (DOOR_GFX_PAGEY2 + j));
2591 BlitBitmapMasked(bitmap, drawto,
2592 VXSIZE - i, DOOR_GFX_PAGEY2 + j, i, VYSIZE / 2 - j,
2595 BlitBitmapMasked(bitmap, drawto,
2596 VXSIZE - i, DOOR_GFX_PAGEY2 + VYSIZE / 2,
2597 i, VYSIZE / 2, VX, VY + VYSIZE / 2 - j);
2598 SetClipOrigin(bitmap, gc, VX - i, (VY + j) - DOOR_GFX_PAGEY2);
2599 BlitBitmapMasked(bitmap, drawto,
2600 VXSIZE, DOOR_GFX_PAGEY2 + VYSIZE / 2,
2602 VX + VXSIZE - i, VY + VYSIZE / 2 + j);
2605 redraw_mask |= REDRAW_DOOR_2;
2606 door_2_done = (a == VXSIZE);
2611 if (game_status == GAME_MODE_MAIN)
2614 if (!(door_state & DOOR_NO_DELAY))
2615 WaitUntilDelayReached(&door_delay, door_delay_value);
2620 if (setup.quick_doors)
2622 StopSound(SND_DOOR_OPENING);
2623 StopSound(SND_DOOR_CLOSING);
2627 if (door_state & DOOR_ACTION_1)
2628 door1 = door_state & DOOR_ACTION_1;
2629 if (door_state & DOOR_ACTION_2)
2630 door2 = door_state & DOOR_ACTION_2;
2632 return (door1 | door2);
2635 void DrawSpecialEditorDoor()
2637 /* draw bigger toolbox window */
2638 BlitBitmap(graphic_info[IMG_GLOBAL_DOOR].bitmap, drawto,
2639 DOOR_GFX_PAGEX7, 0, EXSIZE + 8, 8,
2641 BlitBitmap(graphic_info[IMG_GLOBAL_BORDER].bitmap, drawto,
2642 EX - 4, VY - 4, EXSIZE + 8, EYSIZE - VYSIZE + 4,
2645 redraw_mask |= REDRAW_ALL;
2648 void UndrawSpecialEditorDoor()
2650 /* draw normal tape recorder window */
2651 BlitBitmap(graphic_info[IMG_GLOBAL_BORDER].bitmap, drawto,
2652 EX - 4, EY - 12, EXSIZE + 8, EYSIZE - VYSIZE + 12,
2655 redraw_mask |= REDRAW_ALL;
2659 /* ---------- new tool button stuff ---------------------------------------- */
2661 /* graphic position values for tool buttons */
2662 #define TOOL_BUTTON_YES_XPOS 2
2663 #define TOOL_BUTTON_YES_YPOS 250
2664 #define TOOL_BUTTON_YES_GFX_YPOS 0
2665 #define TOOL_BUTTON_YES_XSIZE 46
2666 #define TOOL_BUTTON_YES_YSIZE 28
2667 #define TOOL_BUTTON_NO_XPOS 52
2668 #define TOOL_BUTTON_NO_YPOS TOOL_BUTTON_YES_YPOS
2669 #define TOOL_BUTTON_NO_GFX_YPOS TOOL_BUTTON_YES_GFX_YPOS
2670 #define TOOL_BUTTON_NO_XSIZE TOOL_BUTTON_YES_XSIZE
2671 #define TOOL_BUTTON_NO_YSIZE TOOL_BUTTON_YES_YSIZE
2672 #define TOOL_BUTTON_CONFIRM_XPOS TOOL_BUTTON_YES_XPOS
2673 #define TOOL_BUTTON_CONFIRM_YPOS TOOL_BUTTON_YES_YPOS
2674 #define TOOL_BUTTON_CONFIRM_GFX_YPOS 30
2675 #define TOOL_BUTTON_CONFIRM_XSIZE 96
2676 #define TOOL_BUTTON_CONFIRM_YSIZE TOOL_BUTTON_YES_YSIZE
2677 #define TOOL_BUTTON_PLAYER_XSIZE 30
2678 #define TOOL_BUTTON_PLAYER_YSIZE 30
2679 #define TOOL_BUTTON_PLAYER_GFX_XPOS 5
2680 #define TOOL_BUTTON_PLAYER_GFX_YPOS 185
2681 #define TOOL_BUTTON_PLAYER_XPOS (5 + TOOL_BUTTON_PLAYER_XSIZE / 2)
2682 #define TOOL_BUTTON_PLAYER_YPOS (215 - TOOL_BUTTON_PLAYER_YSIZE / 2)
2683 #define TOOL_BUTTON_PLAYER1_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2684 + 0 * TOOL_BUTTON_PLAYER_XSIZE)
2685 #define TOOL_BUTTON_PLAYER2_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2686 + 1 * TOOL_BUTTON_PLAYER_XSIZE)
2687 #define TOOL_BUTTON_PLAYER3_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2688 + 0 * TOOL_BUTTON_PLAYER_XSIZE)
2689 #define TOOL_BUTTON_PLAYER4_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2690 + 1 * TOOL_BUTTON_PLAYER_XSIZE)
2691 #define TOOL_BUTTON_PLAYER1_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2692 + 0 * TOOL_BUTTON_PLAYER_YSIZE)
2693 #define TOOL_BUTTON_PLAYER2_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2694 + 0 * TOOL_BUTTON_PLAYER_YSIZE)
2695 #define TOOL_BUTTON_PLAYER3_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2696 + 1 * TOOL_BUTTON_PLAYER_YSIZE)
2697 #define TOOL_BUTTON_PLAYER4_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2698 + 1 * TOOL_BUTTON_PLAYER_YSIZE)
2707 } toolbutton_info[NUM_TOOL_BUTTONS] =
2710 TOOL_BUTTON_YES_XPOS, TOOL_BUTTON_YES_GFX_YPOS,
2711 TOOL_BUTTON_YES_XPOS, TOOL_BUTTON_YES_YPOS,
2712 TOOL_BUTTON_YES_XSIZE, TOOL_BUTTON_YES_YSIZE,
2717 TOOL_BUTTON_NO_XPOS, TOOL_BUTTON_NO_GFX_YPOS,
2718 TOOL_BUTTON_NO_XPOS, TOOL_BUTTON_NO_YPOS,
2719 TOOL_BUTTON_NO_XSIZE, TOOL_BUTTON_NO_YSIZE,
2724 TOOL_BUTTON_CONFIRM_XPOS, TOOL_BUTTON_CONFIRM_GFX_YPOS,
2725 TOOL_BUTTON_CONFIRM_XPOS, TOOL_BUTTON_CONFIRM_YPOS,
2726 TOOL_BUTTON_CONFIRM_XSIZE, TOOL_BUTTON_CONFIRM_YSIZE,
2727 TOOL_CTRL_ID_CONFIRM,
2731 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2732 TOOL_BUTTON_PLAYER1_XPOS, TOOL_BUTTON_PLAYER1_YPOS,
2733 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2734 TOOL_CTRL_ID_PLAYER_1,
2738 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2739 TOOL_BUTTON_PLAYER2_XPOS, TOOL_BUTTON_PLAYER2_YPOS,
2740 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2741 TOOL_CTRL_ID_PLAYER_2,
2745 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2746 TOOL_BUTTON_PLAYER3_XPOS, TOOL_BUTTON_PLAYER3_YPOS,
2747 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2748 TOOL_CTRL_ID_PLAYER_3,
2752 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2753 TOOL_BUTTON_PLAYER4_XPOS, TOOL_BUTTON_PLAYER4_YPOS,
2754 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2755 TOOL_CTRL_ID_PLAYER_4,
2760 void CreateToolButtons()
2764 for (i = 0; i < NUM_TOOL_BUTTONS; i++)
2766 Bitmap *gd_bitmap = graphic_info[IMG_GLOBAL_DOOR].bitmap;
2767 Bitmap *deco_bitmap = None;
2768 int deco_x = 0, deco_y = 0, deco_xpos = 0, deco_ypos = 0;
2769 struct GadgetInfo *gi;
2770 unsigned long event_mask;
2771 int gd_xoffset, gd_yoffset;
2772 int gd_x1, gd_x2, gd_y;
2775 event_mask = GD_EVENT_RELEASED;
2777 gd_xoffset = toolbutton_info[i].xpos;
2778 gd_yoffset = toolbutton_info[i].ypos;
2779 gd_x1 = DOOR_GFX_PAGEX4 + gd_xoffset;
2780 gd_x2 = DOOR_GFX_PAGEX3 + gd_xoffset;
2781 gd_y = DOOR_GFX_PAGEY1 + gd_yoffset;
2783 if (id >= TOOL_CTRL_ID_PLAYER_1 && id <= TOOL_CTRL_ID_PLAYER_4)
2785 int player_nr = id - TOOL_CTRL_ID_PLAYER_1;
2787 getMiniGraphicSource(PLAYER_NR_GFX(IMG_PLAYER_1, player_nr),
2788 &deco_bitmap, &deco_x, &deco_y);
2789 deco_xpos = (toolbutton_info[i].width - MINI_TILEX) / 2;
2790 deco_ypos = (toolbutton_info[i].height - MINI_TILEY) / 2;
2793 gi = CreateGadget(GDI_CUSTOM_ID, id,
2794 GDI_INFO_TEXT, toolbutton_info[i].infotext,
2795 GDI_X, DX + toolbutton_info[i].x,
2796 GDI_Y, DY + toolbutton_info[i].y,
2797 GDI_WIDTH, toolbutton_info[i].width,
2798 GDI_HEIGHT, toolbutton_info[i].height,
2799 GDI_TYPE, GD_TYPE_NORMAL_BUTTON,
2800 GDI_STATE, GD_BUTTON_UNPRESSED,
2801 GDI_DESIGN_UNPRESSED, gd_bitmap, gd_x1, gd_y,
2802 GDI_DESIGN_PRESSED, gd_bitmap, gd_x2, gd_y,
2803 GDI_DECORATION_DESIGN, deco_bitmap, deco_x, deco_y,
2804 GDI_DECORATION_POSITION, deco_xpos, deco_ypos,
2805 GDI_DECORATION_SIZE, MINI_TILEX, MINI_TILEY,
2806 GDI_DECORATION_SHIFTING, 1, 1,
2807 GDI_EVENT_MASK, event_mask,
2808 GDI_CALLBACK_ACTION, HandleToolButtons,
2812 Error(ERR_EXIT, "cannot create gadget");
2814 tool_gadget[id] = gi;
2818 void FreeToolButtons()
2822 for (i = 0; i < NUM_TOOL_BUTTONS; i++)
2823 FreeGadget(tool_gadget[i]);
2826 static void UnmapToolButtons()
2830 for (i = 0; i < NUM_TOOL_BUTTONS; i++)
2831 UnmapGadget(tool_gadget[i]);
2834 static void HandleToolButtons(struct GadgetInfo *gi)
2836 request_gadget_id = gi->custom_id;
2839 int get_next_element(int element)
2843 case EL_QUICKSAND_FILLING: return EL_QUICKSAND_FULL;
2844 case EL_QUICKSAND_EMPTYING: return EL_QUICKSAND_EMPTY;
2845 case EL_MAGIC_WALL_FILLING: return EL_MAGIC_WALL_FULL;
2846 case EL_MAGIC_WALL_EMPTYING: return EL_MAGIC_WALL_ACTIVE;
2847 case EL_BD_MAGIC_WALL_FILLING: return EL_BD_MAGIC_WALL_FULL;
2848 case EL_BD_MAGIC_WALL_EMPTYING: return EL_BD_MAGIC_WALL_ACTIVE;
2849 case EL_AMOEBA_DROPPING: return EL_AMOEBA_WET;
2851 default: return element;
2855 int el_act_dir2img(int element, int action, int direction)
2857 element = GFX_ELEMENT(element);
2858 direction = MV_DIR_BIT(direction);
2860 return element_info[element].direction_graphic[action][direction];
2863 static int el_act_dir2crm(int element, int action, int direction)
2865 element = GFX_ELEMENT(element);
2866 direction = MV_DIR_BIT(direction);
2868 return element_info[element].direction_crumbled[action][direction];
2871 int el_act2img(int element, int action)
2873 element = GFX_ELEMENT(element);
2875 return element_info[element].graphic[action];
2878 int el_act2crm(int element, int action)
2880 element = GFX_ELEMENT(element);
2882 return element_info[element].crumbled[action];
2885 int el_dir2img(int element, int direction)
2887 element = GFX_ELEMENT(element);
2889 return el_act_dir2img(element, ACTION_DEFAULT, direction);
2892 int el2img(int element)
2894 element = GFX_ELEMENT(element);
2896 return element_info[element].graphic[ACTION_DEFAULT];
2899 int el2edimg(int element)
2901 element = GFX_ELEMENT(element);
2903 return element_info[element].special_graphic[GFX_SPECIAL_ARG_EDITOR];
2906 int el2preimg(int element)
2908 element = GFX_ELEMENT(element);
2910 return element_info[element].special_graphic[GFX_SPECIAL_ARG_PREVIEW];