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);
259 if (redraw_mask & REDRAW_DOOR_2)
262 if ((redraw_mask & REDRAW_DOOR_2) == REDRAW_DOOR_2)
264 BlitBitmap(backbuffer, window, VX, VY, VXSIZE, VYSIZE, VX, VY);
268 if (redraw_mask & REDRAW_VIDEO_1)
269 BlitBitmap(backbuffer, window,
270 VX + VIDEO_DISPLAY1_XPOS, VY + VIDEO_DISPLAY1_YPOS,
271 VIDEO_DISPLAY_XSIZE, VIDEO_DISPLAY_YSIZE,
272 VX + VIDEO_DISPLAY1_XPOS, VY + VIDEO_DISPLAY1_YPOS);
273 if (redraw_mask & REDRAW_VIDEO_2)
274 BlitBitmap(backbuffer, window,
275 VX + VIDEO_DISPLAY2_XPOS, VY + VIDEO_DISPLAY2_YPOS,
276 VIDEO_DISPLAY_XSIZE, VIDEO_DISPLAY_YSIZE,
277 VX + VIDEO_DISPLAY2_XPOS, VY + VIDEO_DISPLAY2_YPOS);
278 if (redraw_mask & REDRAW_VIDEO_3)
279 BlitBitmap(backbuffer, window,
280 VX + VIDEO_CONTROL_XPOS, VY + VIDEO_CONTROL_YPOS,
281 VIDEO_CONTROL_XSIZE, VIDEO_CONTROL_YSIZE,
282 VX + VIDEO_CONTROL_XPOS, VY + VIDEO_CONTROL_YPOS);
287 if (redraw_mask & REDRAW_DOOR_3)
288 BlitBitmap(backbuffer, window, EX, EY, EXSIZE, EYSIZE, EX, EY);
290 redraw_mask &= ~REDRAW_DOORS;
293 if (redraw_mask & REDRAW_MICROLEVEL)
295 BlitBitmap(backbuffer, window, SX, SY + 10 * TILEY, SXSIZE, 7 * TILEY,
296 SX, SY + 10 * TILEY);
298 redraw_mask &= ~REDRAW_MICROLEVEL;
301 if (redraw_mask & REDRAW_TILES)
303 for (x = 0; x < SCR_FIELDX; x++)
304 for (y =0 ; y < SCR_FIELDY; y++)
305 if (redraw[redraw_x1 + x][redraw_y1 + y])
306 BlitBitmap(buffer, window,
307 FX + x * TILEX, FX + y * TILEY, TILEX, TILEY,
308 SX + x * TILEX, SY + y * TILEY);
311 if (redraw_mask & REDRAW_FPS) /* display frames per second */
316 sprintf(info1, " (only every %d. frame)", global.fps_slowdown_factor);
317 if (!global.fps_slowdown)
320 sprintf(text, "%.1f fps%s", global.frames_per_second, info1);
321 DrawTextExt(window, SX, SY, text, FONT_TEXT_2, BLIT_OPAQUE);
326 for (x = 0; x < MAX_BUF_XSIZE; x++)
327 for (y = 0; y < MAX_BUF_YSIZE; y++)
330 redraw_mask = REDRAW_NONE;
336 long fading_delay = 300;
338 if (setup.fading && (redraw_mask & REDRAW_FIELD))
345 ClearRectangle(window, REAL_SX,REAL_SY,FULL_SXSIZE,FULL_SYSIZE);
348 for (i = 0; i < 2 * FULL_SYSIZE; i++)
350 for (y = 0; y < FULL_SYSIZE; y++)
352 BlitBitmap(backbuffer, window,
353 REAL_SX,REAL_SY+i, FULL_SXSIZE,1, REAL_SX,REAL_SY+i);
361 for (i = 1; i < FULL_SYSIZE; i+=2)
362 BlitBitmap(backbuffer, window,
363 REAL_SX,REAL_SY+i, FULL_SXSIZE,1, REAL_SX,REAL_SY+i);
369 SetClipOrigin(clip_gc[PIX_FADEMASK], 0, 0);
370 BlitBitmapMasked(backbuffer, window,
371 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE,
376 SetClipOrigin(clip_gc[PIX_FADEMASK], -1, -1);
377 BlitBitmapMasked(backbuffer, window,
378 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE,
383 SetClipOrigin(clip_gc[PIX_FADEMASK], 0, -1);
384 BlitBitmapMasked(backbuffer, window,
385 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE,
390 SetClipOrigin(clip_gc[PIX_FADEMASK], -1, 0);
391 BlitBitmapMasked(backbuffer, window,
392 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE,
397 redraw_mask &= ~REDRAW_MAIN;
404 void SetMainBackgroundImage(int graphic)
406 SetMainBackgroundBitmap(graphic == IMG_UNDEFINED ? NULL :
407 graphic_info[graphic].bitmap ?
408 graphic_info[graphic].bitmap :
409 graphic_info[IMG_BACKGROUND].bitmap);
412 void SetDoorBackgroundImage(int graphic)
414 SetDoorBackgroundBitmap(graphic == IMG_UNDEFINED ? NULL :
415 graphic_info[graphic].bitmap ?
416 graphic_info[graphic].bitmap :
417 graphic_info[IMG_BACKGROUND].bitmap);
420 void DrawBackground(int dest_x, int dest_y, int width, int height)
422 ClearRectangleOnBackground(backbuffer, dest_x, dest_y, width, height);
424 redraw_mask |= REDRAW_FIELD;
429 DrawBackground(REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE);
431 if (setup.soft_scrolling && game_status == GAME_MODE_PLAYING)
433 ClearRectangle(fieldbuffer, 0, 0, FXSIZE, FYSIZE);
434 SetDrawtoField(DRAW_BUFFERED);
437 SetDrawtoField(DRAW_BACKBUFFER);
439 if (setup.direct_draw && game_status == GAME_MODE_PLAYING)
441 ClearRectangle(window, REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE);
442 SetDrawtoField(DRAW_DIRECT);
446 void MarkTileDirty(int x, int y)
448 int xx = redraw_x1 + x;
449 int yy = redraw_y1 + y;
454 redraw[xx][yy] = TRUE;
455 redraw_mask |= REDRAW_TILES;
458 void SetBorderElement()
462 BorderElement = EL_EMPTY;
464 for (y = 0; y < lev_fieldy && BorderElement == EL_EMPTY; y++)
466 for (x = 0; x < lev_fieldx; x++)
468 if (!IS_INDESTRUCTIBLE(Feld[x][y]))
469 BorderElement = EL_STEELWALL;
471 if (y != 0 && y != lev_fieldy - 1 && x != lev_fieldx - 1)
477 void SetRandomAnimationValue(int x, int y)
479 gfx.anim_random_frame = GfxRandom[x][y];
482 inline int getGraphicAnimationFrame(int graphic, int sync_frame)
484 /* animation synchronized with global frame counter, not move position */
485 if (graphic_info[graphic].anim_global_sync || sync_frame < 0)
486 sync_frame = FrameCounter;
488 return getAnimationFrame(graphic_info[graphic].anim_frames,
489 graphic_info[graphic].anim_delay,
490 graphic_info[graphic].anim_mode,
491 graphic_info[graphic].anim_start_frame,
495 inline void DrawGraphicAnimationExt(DrawBuffer *dst_bitmap, int x, int y,
496 int graphic, int sync_frame, int mask_mode)
498 int frame = getGraphicAnimationFrame(graphic, sync_frame);
500 if (mask_mode == USE_MASKING)
501 DrawGraphicThruMaskExt(dst_bitmap, x, y, graphic, frame);
503 DrawGraphicExt(dst_bitmap, x, y, graphic, frame);
506 inline void DrawGraphicAnimation(int x, int y, int graphic)
508 int lx = LEVELX(x), ly = LEVELY(y);
510 if (!IN_SCR_FIELD(x, y))
513 DrawGraphicAnimationExt(drawto_field, FX + x * TILEX, FY + y * TILEY,
514 graphic, GfxFrame[lx][ly], NO_MASKING);
518 void DrawLevelGraphicAnimation(int x, int y, int graphic)
520 DrawGraphicAnimation(SCREENX(x), SCREENY(y), graphic);
523 void DrawLevelElementAnimation(int x, int y, int element)
526 int graphic = el_act_dir2img(element, GfxAction[x][y], GfxDir[x][y]);
528 DrawGraphicAnimation(SCREENX(x), SCREENY(y), graphic);
530 DrawGraphicAnimation(SCREENX(x), SCREENY(y), el2img(element));
534 inline void DrawLevelGraphicAnimationIfNeeded(int x, int y, int graphic)
536 int sx = SCREENX(x), sy = SCREENY(y);
538 if (!IN_LEV_FIELD(x, y) || !IN_SCR_FIELD(sx, sy))
541 if (!IS_NEW_FRAME(GfxFrame[x][y], graphic))
544 DrawGraphicAnimation(sx, sy, graphic);
546 if (GFX_CRUMBLED(Feld[x][y]))
547 DrawLevelFieldCrumbledSand(x, y);
550 void DrawLevelElementAnimationIfNeeded(int x, int y, int element)
552 int sx = SCREENX(x), sy = SCREENY(y);
555 if (!IN_LEV_FIELD(x, y) || !IN_SCR_FIELD(sx, sy))
558 graphic = el_act_dir2img(element, GfxAction[x][y], GfxDir[x][y]);
560 if (!IS_NEW_FRAME(GfxFrame[x][y], graphic))
563 DrawGraphicAnimation(sx, sy, graphic);
565 if (GFX_CRUMBLED(element))
566 DrawLevelFieldCrumbledSand(x, y);
569 static int getPlayerGraphic(struct PlayerInfo *player, int move_dir)
571 if (player->use_murphy_graphic)
573 /* this works only because currently only one player can be "murphy" ... */
574 static int last_horizontal_dir = MV_LEFT;
575 int graphic = el_act_dir2img(EL_SP_MURPHY, player->GfxAction, move_dir);
577 if (move_dir == MV_LEFT || move_dir == MV_RIGHT)
578 last_horizontal_dir = move_dir;
580 if (graphic == IMG_SP_MURPHY) /* undefined => use special graphic */
582 int direction = (player->is_snapping ? move_dir : last_horizontal_dir);
584 graphic = el_act_dir2img(EL_SP_MURPHY, player->GfxAction, direction);
590 return el_act_dir2img(player->element_nr, player->GfxAction, move_dir);
593 static boolean equalGraphics(int graphic1, int graphic2)
595 struct GraphicInfo *g1 = &graphic_info[graphic1];
596 struct GraphicInfo *g2 = &graphic_info[graphic2];
598 return (g1->bitmap == g2->bitmap &&
599 g1->src_x == g2->src_x &&
600 g1->src_y == g2->src_y &&
601 g1->anim_frames == g2->anim_frames &&
602 g1->anim_delay == g2->anim_delay &&
603 g1->anim_mode == g2->anim_mode);
606 void DrawAllPlayers()
610 for (i = 0; i < MAX_PLAYERS; i++)
611 if (stored_player[i].active)
612 DrawPlayer(&stored_player[i]);
615 void DrawPlayerField(int x, int y)
617 if (!IS_PLAYER(x, y))
620 DrawPlayer(PLAYERINFO(x, y));
623 void DrawPlayer(struct PlayerInfo *player)
627 int move_dir = player->MovDir;
629 int last_jx = player->last_jx;
630 int last_jy = player->last_jy;
631 int next_jx = jx + (jx - last_jx);
632 int next_jy = jy + (jy - last_jy);
633 boolean player_is_moving = (last_jx != jx || last_jy != jy ? TRUE : FALSE);
635 int dx = (move_dir == MV_LEFT ? -1 : move_dir == MV_RIGHT ? +1 : 0);
636 int dy = (move_dir == MV_UP ? -1 : move_dir == MV_DOWN ? +1 : 0);
637 int last_jx = (player->is_moving ? jx - dx : jx);
638 int last_jy = (player->is_moving ? jy - dy : jy);
639 int next_jx = jx + dx;
640 int next_jy = jy + dy;
641 boolean player_is_moving = (player->MovPos ? TRUE : FALSE);
643 int sx = SCREENX(jx), sy = SCREENY(jy);
644 int sxx = 0, syy = 0;
645 int element = Feld[jx][jy], last_element = Feld[last_jx][last_jy];
647 int action = ACTION_DEFAULT;
648 int last_player_graphic = getPlayerGraphic(player, move_dir);
649 int last_player_frame = player->Frame;
652 if (!player->active || !IN_SCR_FIELD(SCREENX(last_jx), SCREENY(last_jy)))
656 if (!IN_LEV_FIELD(jx, jy))
658 printf("DrawPlayerField(): x = %d, y = %d\n",jx,jy);
659 printf("DrawPlayerField(): sx = %d, sy = %d\n",sx,sy);
660 printf("DrawPlayerField(): This should never happen!\n");
665 if (element == EL_EXPLOSION)
668 action = (player->is_pushing ? ACTION_PUSHING :
669 player->is_digging ? ACTION_DIGGING :
670 player->is_collecting ? ACTION_COLLECTING :
671 player->is_moving ? ACTION_MOVING :
672 player->is_snapping ? ACTION_SNAPPING :
673 player->is_dropping ? ACTION_DROPPING :
674 player->is_waiting ? player->action_waiting : ACTION_DEFAULT);
676 InitPlayerGfxAnimation(player, action, move_dir);
678 /* ----------------------------------------------------------------------- */
679 /* draw things in the field the player is leaving, if needed */
680 /* ----------------------------------------------------------------------- */
683 if (player->is_moving)
685 if (player_is_moving)
688 if (Back[last_jx][last_jy] && IS_DRAWABLE(last_element))
690 DrawLevelElement(last_jx, last_jy, Back[last_jx][last_jy]);
692 if (last_element == EL_DYNAMITE_ACTIVE ||
693 last_element == EL_SP_DISK_RED_ACTIVE)
694 DrawDynamite(last_jx, last_jy);
696 DrawLevelFieldThruMask(last_jx, last_jy);
698 else if (last_element == EL_DYNAMITE_ACTIVE ||
699 last_element == EL_SP_DISK_RED_ACTIVE)
700 DrawDynamite(last_jx, last_jy);
702 DrawLevelField(last_jx, last_jy);
704 if (player->is_pushing && IN_SCR_FIELD(SCREENX(next_jx), SCREENY(next_jy)))
705 DrawLevelElement(next_jx, next_jy, EL_EMPTY);
708 if (!IN_SCR_FIELD(sx, sy))
711 if (setup.direct_draw)
712 SetDrawtoField(DRAW_BUFFERED);
714 /* ----------------------------------------------------------------------- */
715 /* draw things behind the player, if needed */
716 /* ----------------------------------------------------------------------- */
719 DrawLevelElement(jx, jy, Back[jx][jy]);
720 else if (IS_ACTIVE_BOMB(element))
721 DrawLevelElement(jx, jy, EL_EMPTY);
724 if (player_is_moving && GfxElement[jx][jy] != EL_UNDEFINED)
726 if (GFX_CRUMBLED(GfxElement[jx][jy]))
727 DrawLevelFieldCrumbledSandDigging(jx, jy, move_dir, player->StepFrame);
730 int old_element = GfxElement[jx][jy];
731 int old_graphic = el_act_dir2img(old_element, action, move_dir);
732 int frame = getGraphicAnimationFrame(old_graphic, player->StepFrame);
734 DrawGraphic(sx, sy, old_graphic, frame);
739 GfxElement[jx][jy] = EL_UNDEFINED;
741 DrawLevelField(jx, jy);
745 /* ----------------------------------------------------------------------- */
746 /* draw player himself */
747 /* ----------------------------------------------------------------------- */
751 graphic = getPlayerGraphic(player, move_dir);
753 /* in the case of changed player action or direction, prevent the current
754 animation frame from being restarted for identical animations */
755 if (player->Frame == 0 && equalGraphics(graphic, last_player_graphic))
756 player->Frame = last_player_frame;
760 if (player->use_murphy_graphic)
762 static int last_horizontal_dir = MV_LEFT;
764 if (move_dir == MV_LEFT || move_dir == MV_RIGHT)
765 last_horizontal_dir = move_dir;
767 graphic = el_act_dir2img(EL_SP_MURPHY, player->GfxAction, move_dir);
769 if (graphic == IMG_SP_MURPHY) /* undefined => use special graphic */
771 int direction = (player->is_snapping ? move_dir : last_horizontal_dir);
773 graphic = el_act_dir2img(EL_SP_MURPHY, player->GfxAction, direction);
777 graphic = el_act_dir2img(player->element_nr, player->GfxAction, move_dir);
781 frame = getGraphicAnimationFrame(graphic, player->Frame);
785 if (move_dir == MV_LEFT || move_dir == MV_RIGHT)
786 sxx = player->GfxPos;
788 syy = player->GfxPos;
791 if (!setup.soft_scrolling && ScreenMovPos)
794 DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, frame, NO_CUTTING);
796 if (SHIELD_ON(player))
798 int graphic = (player->shield_deadly_time_left ? IMG_SHIELD_DEADLY_ACTIVE :
799 IMG_SHIELD_NORMAL_ACTIVE);
800 int frame = getGraphicAnimationFrame(graphic, -1);
802 DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, frame, NO_CUTTING);
805 /* ----------------------------------------------------------------------- */
806 /* draw things the player is pushing, if needed */
807 /* ----------------------------------------------------------------------- */
810 printf("::: %d, %d [%d, %d] [%d]\n",
811 player->is_pushing, player_is_moving, player->GfxAction,
812 player->is_moving, player_is_moving);
816 if (player->is_pushing && player->is_moving)
818 if (player->is_pushing && player_is_moving)
821 int px = SCREENX(next_jx), py = SCREENY(next_jy);
823 if (Back[next_jx][next_jy])
824 DrawLevelElement(next_jx, next_jy, Back[next_jx][next_jy]);
826 if ((sxx || syy) && element == EL_SOKOBAN_OBJECT)
827 DrawGraphicShiftedThruMask(px, py, sxx, syy, IMG_SOKOBAN_OBJECT, 0,
831 int element = MovingOrBlocked2Element(next_jx, next_jy);
832 int graphic = el_act_dir2img(element, ACTION_PUSHING, move_dir);
834 int frame = getGraphicAnimationFrame(graphic, player->StepFrame);
836 int frame = getGraphicAnimationFrame(graphic, player->Frame);
839 DrawGraphicShifted(px, py, sxx, syy, graphic, frame,
840 NO_CUTTING, NO_MASKING);
844 /* ----------------------------------------------------------------------- */
845 /* draw things in front of player (active dynamite or dynabombs) */
846 /* ----------------------------------------------------------------------- */
848 if (IS_ACTIVE_BOMB(element))
850 graphic = el2img(element);
851 frame = getGraphicAnimationFrame(graphic, GfxFrame[jx][jy]);
853 if (game.emulation == EMU_SUPAPLEX)
854 DrawGraphic(sx, sy, IMG_SP_DISK_RED, frame);
856 DrawGraphicThruMask(sx, sy, graphic, frame);
859 if (player_is_moving && last_element == EL_EXPLOSION)
861 int graphic = el_act2img(GfxElement[last_jx][last_jy], ACTION_EXPLODING);
862 int delay = (game.emulation == EMU_SUPAPLEX ? 3 : 2);
863 int phase = ExplodePhase[last_jx][last_jy] - 1;
864 int frame = getGraphicAnimationFrame(graphic, phase - delay);
867 DrawGraphicThruMask(SCREENX(last_jx), SCREENY(last_jy), graphic, frame);
870 /* ----------------------------------------------------------------------- */
871 /* draw elements the player is just walking/passing through/under */
872 /* ----------------------------------------------------------------------- */
874 /* handle the field the player is leaving ... */
875 if (player_is_moving && IS_ACCESSIBLE_INSIDE(last_element))
876 DrawLevelField(last_jx, last_jy);
877 else if (player_is_moving && IS_ACCESSIBLE_UNDER(last_element))
878 DrawLevelFieldThruMask(last_jx, last_jy);
880 /* ... and the field the player is entering */
881 if (IS_ACCESSIBLE_INSIDE(element))
882 DrawLevelField(jx, jy);
883 else if (IS_ACCESSIBLE_UNDER(element))
884 DrawLevelFieldThruMask(jx, jy);
886 if (setup.direct_draw)
888 int dest_x = SX + SCREENX(MIN(jx, last_jx)) * TILEX;
889 int dest_y = SY + SCREENY(MIN(jy, last_jy)) * TILEY;
890 int x_size = TILEX * (1 + ABS(jx - last_jx));
891 int y_size = TILEY * (1 + ABS(jy - last_jy));
893 BlitBitmap(drawto_field, window,
894 dest_x, dest_y, x_size, y_size, dest_x, dest_y);
895 SetDrawtoField(DRAW_DIRECT);
898 MarkTileDirty(sx, sy);
901 void getGraphicSource(int graphic, int frame, Bitmap **bitmap, int *x, int *y)
903 struct GraphicInfo *g = &graphic_info[graphic];
907 if (g->offset_y == 0) /* frames are ordered horizontally */
909 int max_width = g->anim_frames_per_line * g->width;
911 *x = (g->src_x + frame * g->offset_x) % max_width;
912 *y = g->src_y + (g->src_x + frame * g->offset_x) / max_width * g->height;
914 else if (g->offset_x == 0) /* frames are ordered vertically */
916 int max_height = g->anim_frames_per_line * g->height;
918 *x = g->src_x + (g->src_y + frame * g->offset_y) / max_height * g->width;
919 *y = (g->src_y + frame * g->offset_y) % max_height;
921 else /* frames are ordered diagonally */
923 *x = g->src_x + frame * g->offset_x;
924 *y = g->src_y + frame * g->offset_y;
928 void DrawGraphic(int x, int y, int graphic, int frame)
931 if (!IN_SCR_FIELD(x, y))
933 printf("DrawGraphic(): x = %d, y = %d, graphic = %d\n", x, y, graphic);
934 printf("DrawGraphic(): This should never happen!\n");
939 DrawGraphicExt(drawto_field, FX + x * TILEX, FY + y * TILEY, graphic, frame);
943 void DrawGraphicExt(DrawBuffer *dst_bitmap, int x, int y, int graphic,
949 getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
950 BlitBitmap(src_bitmap, dst_bitmap, src_x, src_y, TILEX, TILEY, x, y);
953 void DrawGraphicThruMask(int x, int y, int graphic, int frame)
956 if (!IN_SCR_FIELD(x, y))
958 printf("DrawGraphicThruMask(): x = %d,y = %d, graphic = %d\n",x,y,graphic);
959 printf("DrawGraphicThruMask(): This should never happen!\n");
964 DrawGraphicThruMaskExt(drawto_field, FX + x * TILEX, FY + y *TILEY, graphic,
969 void DrawGraphicThruMaskExt(DrawBuffer *d, int dest_x, int dest_y, int graphic,
977 getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
978 drawing_gc = src_bitmap->stored_clip_gc;
980 GC drawing_gc = src_bitmap->stored_clip_gc;
981 Bitmap *src_bitmap = graphic_info[graphic].bitmap;
982 int src_x = graphic_info[graphic].src_x;
983 int src_y = graphic_info[graphic].src_y;
984 int offset_x = graphic_info[graphic].offset_x;
985 int offset_y = graphic_info[graphic].offset_y;
987 src_x += frame * offset_x;
988 src_y += frame * offset_y;
992 SetClipOrigin(src_bitmap, drawing_gc, dest_x - src_x, dest_y - src_y);
993 BlitBitmapMasked(src_bitmap, d, src_x, src_y, TILEX, TILEY, dest_x, dest_y);
996 void DrawMiniGraphic(int x, int y, int graphic)
998 DrawMiniGraphicExt(drawto, SX + x * MINI_TILEX,SY + y * MINI_TILEY, graphic);
999 MarkTileDirty(x / 2, y / 2);
1002 void getMiniGraphicSource(int graphic, Bitmap **bitmap, int *x, int *y)
1004 struct GraphicInfo *g = &graphic_info[graphic];
1005 int mini_startx = 0;
1006 int mini_starty = g->bitmap->height * 2 / 3;
1008 *bitmap = g->bitmap;
1009 *x = mini_startx + g->src_x / 2;
1010 *y = mini_starty + g->src_y / 2;
1013 void DrawMiniGraphicExt(DrawBuffer *d, int x, int y, int graphic)
1018 getMiniGraphicSource(graphic, &src_bitmap, &src_x, &src_y);
1019 BlitBitmap(src_bitmap, d, src_x, src_y, MINI_TILEX, MINI_TILEY, x, y);
1022 void DrawGraphicShifted(int x, int y, int dx, int dy, int graphic, int frame,
1023 int cut_mode, int mask_mode)
1028 int width = TILEX, height = TILEY;
1034 DrawGraphic(x, y, graphic, frame);
1038 if (dx || dy) /* shifted graphic */
1040 if (x < BX1) /* object enters playfield from the left */
1047 else if (x > BX2) /* object enters playfield from the right */
1053 else if (x==BX1 && dx < 0) /* object leaves playfield to the left */
1059 else if (x==BX2 && dx > 0) /* object leaves playfield to the right */
1061 else if (dx) /* general horizontal movement */
1062 MarkTileDirty(x + SIGN(dx), y);
1064 if (y < BY1) /* object enters playfield from the top */
1066 if (cut_mode==CUT_BELOW) /* object completely above top border */
1074 else if (y > BY2) /* object enters playfield from the bottom */
1080 else if (y==BY1 && dy < 0) /* object leaves playfield to the top */
1086 else if (dy > 0 && cut_mode == CUT_ABOVE)
1088 if (y == BY2) /* object completely above bottom border */
1094 MarkTileDirty(x, y + 1);
1095 } /* object leaves playfield to the bottom */
1096 else if (dy > 0 && (y == BY2 || cut_mode == CUT_BELOW))
1098 else if (dy) /* general vertical movement */
1099 MarkTileDirty(x, y + SIGN(dy));
1103 getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
1105 src_bitmap = graphic_info[graphic].bitmap;
1106 src_x = graphic_info[graphic].src_x;
1107 src_y = graphic_info[graphic].src_y;
1108 offset_x = graphic_info[graphic].offset_x;
1109 offset_y = graphic_info[graphic].offset_y;
1111 src_x += frame * offset_x;
1112 src_y += frame * offset_y;
1115 drawing_gc = src_bitmap->stored_clip_gc;
1120 dest_x = FX + x * TILEX + dx;
1121 dest_y = FY + y * TILEY + dy;
1124 if (!IN_SCR_FIELD(x,y))
1126 printf("DrawGraphicShifted(): x = %d, y = %d, graphic = %d\n",x,y,graphic);
1127 printf("DrawGraphicShifted(): This should never happen!\n");
1132 if (mask_mode == USE_MASKING)
1134 SetClipOrigin(src_bitmap, drawing_gc, dest_x - src_x, dest_y - src_y);
1135 BlitBitmapMasked(src_bitmap, drawto_field, src_x, src_y, width, height,
1139 BlitBitmap(src_bitmap, drawto_field, src_x, src_y, width, height,
1142 MarkTileDirty(x, y);
1145 void DrawGraphicShiftedThruMask(int x, int y, int dx, int dy, int graphic,
1146 int frame, int cut_mode)
1148 DrawGraphicShifted(x, y, dx, dy, graphic, frame, cut_mode, USE_MASKING);
1151 void DrawScreenElementExt(int x, int y, int dx, int dy, int element,
1152 int cut_mode, int mask_mode)
1154 int lx = LEVELX(x), ly = LEVELY(y);
1158 if (IN_LEV_FIELD(lx, ly))
1160 SetRandomAnimationValue(lx, ly);
1162 graphic = el_act_dir2img(element, GfxAction[lx][ly], GfxDir[lx][ly]);
1163 frame = getGraphicAnimationFrame(graphic, GfxFrame[lx][ly]);
1165 else /* border element */
1167 graphic = el2img(element);
1168 frame = getGraphicAnimationFrame(graphic, -1);
1171 if (element == EL_EXPANDABLE_WALL)
1173 boolean left_stopped = FALSE, right_stopped = FALSE;
1175 if (!IN_LEV_FIELD(lx - 1, ly) || IS_WALL(Feld[lx - 1][ly]))
1176 left_stopped = TRUE;
1177 if (!IN_LEV_FIELD(lx + 1, ly) || IS_WALL(Feld[lx + 1][ly]))
1178 right_stopped = TRUE;
1180 if (left_stopped && right_stopped)
1182 else if (left_stopped)
1184 graphic = IMG_EXPANDABLE_WALL_GROWING_RIGHT;
1185 frame = graphic_info[graphic].anim_frames - 1;
1187 else if (right_stopped)
1189 graphic = IMG_EXPANDABLE_WALL_GROWING_LEFT;
1190 frame = graphic_info[graphic].anim_frames - 1;
1195 DrawGraphicShifted(x, y, dx, dy, graphic, frame, cut_mode, mask_mode);
1196 else if (mask_mode == USE_MASKING)
1197 DrawGraphicThruMask(x, y, graphic, frame);
1199 DrawGraphic(x, y, graphic, frame);
1202 void DrawLevelElementExt(int x, int y, int dx, int dy, int element,
1203 int cut_mode, int mask_mode)
1205 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1206 DrawScreenElementExt(SCREENX(x), SCREENY(y), dx, dy, element,
1207 cut_mode, mask_mode);
1210 void DrawScreenElementShifted(int x, int y, int dx, int dy, int element,
1213 DrawScreenElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
1216 void DrawLevelElementShifted(int x, int y, int dx, int dy, int element,
1219 DrawLevelElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
1222 void DrawLevelElementThruMask(int x, int y, int element)
1224 DrawLevelElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
1227 void DrawLevelFieldThruMask(int x, int y)
1229 DrawLevelElementExt(x, y, 0, 0, Feld[x][y], NO_CUTTING, USE_MASKING);
1232 #define TILE_GFX_ELEMENT(x, y) \
1233 (GfxElement[x][y] != EL_UNDEFINED && Feld[x][y] != EL_EXPLOSION ? \
1234 GfxElement[x][y] : Feld[x][y])
1236 static void DrawLevelFieldCrumbledSandExt(int x, int y, int graphic, int frame)
1240 int sx = SCREENX(x), sy = SCREENY(y);
1242 int width, height, cx, cy, i;
1244 int crumbled_border_size = graphic_info[graphic].border_size;
1246 int snip = TILEX / 8; /* number of border pixels from "crumbled graphic" */
1248 static int xy[4][2] =
1257 if (x == 0 && y == 7)
1258 printf("::: %d, %d [%d]\n", GfxElement[x][y], Feld[x][y],
1259 crumbled_border_size);
1262 if (!IN_LEV_FIELD(x, y))
1265 element = TILE_GFX_ELEMENT(x, y);
1267 /* crumble field itself */
1268 if (GFX_CRUMBLED(element) && !IS_MOVING(x, y))
1270 if (!IN_SCR_FIELD(sx, sy))
1273 getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
1275 for (i = 0; i < 4; i++)
1277 int xx = x + xy[i][0];
1278 int yy = y + xy[i][1];
1281 element = (IN_LEV_FIELD(xx, yy) ? TILE_GFX_ELEMENT(xx, yy) :
1284 element = (IN_LEV_FIELD(xx, yy) ? Feld[xx][yy] : BorderElement);
1287 /* check if neighbour field is of same type */
1288 if (GFX_CRUMBLED(element) && !IS_MOVING(xx, yy))
1292 if (Feld[x][y] == EL_CUSTOM_START + 123)
1293 printf("::: crumble [%d] THE CHAOS ENGINE (%d, %d): %d, %d\n",
1294 i, Feld[x][y], element,
1295 GFX_CRUMBLED(element), IS_MOVING(x, y));
1298 if (i == 1 || i == 2)
1300 width = crumbled_border_size;
1302 cx = (i == 2 ? TILEX - crumbled_border_size : 0);
1308 height = crumbled_border_size;
1310 cy = (i == 3 ? TILEY - crumbled_border_size : 0);
1313 BlitBitmap(src_bitmap, drawto_field, src_x + cx, src_y + cy,
1314 width, height, FX + sx * TILEX + cx, FY + sy * TILEY + cy);
1317 MarkTileDirty(sx, sy);
1319 else /* crumble neighbour fields */
1322 getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
1325 for (i = 0; i < 4; i++)
1327 int xx = x + xy[i][0];
1328 int yy = y + xy[i][1];
1329 int sxx = sx + xy[i][0];
1330 int syy = sy + xy[i][1];
1333 if (!IN_LEV_FIELD(xx, yy) ||
1334 !IN_SCR_FIELD(sxx, syy) ||
1338 element = TILE_GFX_ELEMENT(xx, yy);
1340 if (!GFX_CRUMBLED(element))
1343 if (!IN_LEV_FIELD(xx, yy) ||
1344 !IN_SCR_FIELD(sxx, syy) ||
1345 !GFX_CRUMBLED(Feld[xx][yy]) ||
1351 graphic = el_act2crm(Feld[xx][yy], ACTION_DEFAULT);
1352 crumbled_border_size = graphic_info[graphic].border_size;
1354 getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
1357 if (i == 1 || i == 2)
1359 width = crumbled_border_size;
1361 cx = (i == 1 ? TILEX - crumbled_border_size : 0);
1367 height = crumbled_border_size;
1369 cy = (i == 0 ? TILEY - crumbled_border_size : 0);
1372 BlitBitmap(src_bitmap, drawto_field, src_x + cx, src_y + cy,
1373 width, height, FX + sxx * TILEX + cx, FY + syy * TILEY + cy);
1375 MarkTileDirty(sxx, syy);
1380 void DrawLevelFieldCrumbledSand(int x, int y)
1385 if (!IN_LEV_FIELD(x, y))
1388 graphic = el_act2crm(Feld[x][y], ACTION_DEFAULT);
1390 DrawLevelFieldCrumbledSandExt(x, y, graphic, 0);
1392 DrawLevelFieldCrumbledSandExt(x, y, IMG_SAND_CRUMBLED, 0);
1396 void DrawLevelFieldCrumbledSandDigging(int x, int y, int direction,
1400 int graphic1 = el_act_dir2img(GfxElement[x][y], ACTION_DIGGING, direction);
1401 int graphic2 = el_act_dir2crm(GfxElement[x][y], ACTION_DIGGING, direction);
1403 int graphic1 = el_act_dir2img(EL_SAND, ACTION_DIGGING, direction);
1404 int graphic2 = el_act_dir2img(EL_SAND_CRUMBLED, ACTION_DIGGING, direction);
1406 int frame1 = getGraphicAnimationFrame(graphic1, step_frame);
1407 int frame2 = getGraphicAnimationFrame(graphic2, step_frame);
1408 int sx = SCREENX(x), sy = SCREENY(y);
1410 DrawGraphic(sx, sy, graphic1, frame1);
1411 DrawLevelFieldCrumbledSandExt(x, y, graphic2, frame2);
1414 void DrawLevelFieldCrumbledSandNeighbours(int x, int y)
1416 int sx = SCREENX(x), sy = SCREENY(y);
1417 static int xy[4][2] =
1426 for (i = 0; i < 4; i++)
1428 int xx = x + xy[i][0];
1429 int yy = y + xy[i][1];
1430 int sxx = sx + xy[i][0];
1431 int syy = sy + xy[i][1];
1433 if (!IN_LEV_FIELD(xx, yy) ||
1434 !IN_SCR_FIELD(sxx, syy) ||
1435 !GFX_CRUMBLED(Feld[xx][yy]) ||
1439 DrawLevelField(xx, yy);
1443 static int getBorderElement(int x, int y)
1447 { EL_STEELWALL_TOPLEFT, EL_INVISIBLE_STEELWALL_TOPLEFT },
1448 { EL_STEELWALL_TOPRIGHT, EL_INVISIBLE_STEELWALL_TOPRIGHT },
1449 { EL_STEELWALL_BOTTOMLEFT, EL_INVISIBLE_STEELWALL_BOTTOMLEFT },
1450 { EL_STEELWALL_BOTTOMRIGHT, EL_INVISIBLE_STEELWALL_BOTTOMRIGHT },
1451 { EL_STEELWALL_VERTICAL, EL_INVISIBLE_STEELWALL_VERTICAL },
1452 { EL_STEELWALL_HORIZONTAL, EL_INVISIBLE_STEELWALL_HORIZONTAL },
1453 { EL_STEELWALL, EL_INVISIBLE_STEELWALL }
1455 int steel_type = (BorderElement == EL_STEELWALL ? 0 : 1);
1456 int steel_position = (x == -1 && y == -1 ? 0 :
1457 x == lev_fieldx && y == -1 ? 1 :
1458 x == -1 && y == lev_fieldy ? 2 :
1459 x == lev_fieldx && y == lev_fieldy ? 3 :
1460 x == -1 || x == lev_fieldx ? 4 :
1461 y == -1 || y == lev_fieldy ? 5 : 6);
1463 return border[steel_position][steel_type];
1466 void DrawScreenElement(int x, int y, int element)
1468 DrawScreenElementExt(x, y, 0, 0, element, NO_CUTTING, NO_MASKING);
1469 DrawLevelFieldCrumbledSand(LEVELX(x), LEVELY(y));
1472 void DrawLevelElement(int x, int y, int element)
1474 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1475 DrawScreenElement(SCREENX(x), SCREENY(y), element);
1478 void DrawScreenField(int x, int y)
1480 int lx = LEVELX(x), ly = LEVELY(y);
1481 int element, content;
1483 if (!IN_LEV_FIELD(lx, ly))
1485 if (lx < -1 || lx > lev_fieldx || ly < -1 || ly > lev_fieldy)
1488 element = getBorderElement(lx, ly);
1490 DrawScreenElement(x, y, element);
1494 element = Feld[lx][ly];
1495 content = Store[lx][ly];
1497 if (IS_MOVING(lx, ly))
1499 int horiz_move = (MovDir[lx][ly] == MV_LEFT || MovDir[lx][ly] == MV_RIGHT);
1500 boolean cut_mode = NO_CUTTING;
1502 if (element == EL_QUICKSAND_EMPTYING ||
1503 element == EL_MAGIC_WALL_EMPTYING ||
1504 element == EL_BD_MAGIC_WALL_EMPTYING ||
1505 element == EL_AMOEBA_DROPPING)
1506 cut_mode = CUT_ABOVE;
1507 else if (element == EL_QUICKSAND_FILLING ||
1508 element == EL_MAGIC_WALL_FILLING ||
1509 element == EL_BD_MAGIC_WALL_FILLING)
1510 cut_mode = CUT_BELOW;
1512 if (cut_mode == CUT_ABOVE)
1513 DrawScreenElementShifted(x, y, 0, 0, element, NO_CUTTING);
1515 DrawScreenElement(x, y, EL_EMPTY);
1518 DrawScreenElementShifted(x, y, MovPos[lx][ly], 0, element, NO_CUTTING);
1519 else if (cut_mode == NO_CUTTING)
1520 DrawScreenElementShifted(x, y, 0, MovPos[lx][ly], element, cut_mode);
1522 DrawScreenElementShifted(x, y, 0, MovPos[lx][ly], content, cut_mode);
1524 if (content == EL_ACID)
1526 int dir = MovDir[lx][ly];
1527 int newlx = lx + (dir == MV_LEFT ? -1 : dir == MV_RIGHT ? +1 : 0);
1528 int newly = ly + (dir == MV_UP ? -1 : dir == MV_DOWN ? +1 : 0);
1530 DrawLevelElementThruMask(newlx, newly, EL_ACID);
1533 else if (IS_BLOCKED(lx, ly))
1538 boolean cut_mode = NO_CUTTING;
1539 int element_old, content_old;
1541 Blocked2Moving(lx, ly, &oldx, &oldy);
1544 horiz_move = (MovDir[oldx][oldy] == MV_LEFT ||
1545 MovDir[oldx][oldy] == MV_RIGHT);
1547 element_old = Feld[oldx][oldy];
1548 content_old = Store[oldx][oldy];
1550 if (element_old == EL_QUICKSAND_EMPTYING ||
1551 element_old == EL_MAGIC_WALL_EMPTYING ||
1552 element_old == EL_BD_MAGIC_WALL_EMPTYING ||
1553 element_old == EL_AMOEBA_DROPPING)
1554 cut_mode = CUT_ABOVE;
1556 DrawScreenElement(x, y, EL_EMPTY);
1559 DrawScreenElementShifted(sx, sy, MovPos[oldx][oldy], 0, element_old,
1561 else if (cut_mode == NO_CUTTING)
1562 DrawScreenElementShifted(sx, sy, 0, MovPos[oldx][oldy], element_old,
1565 DrawScreenElementShifted(sx, sy, 0, MovPos[oldx][oldy], content_old,
1568 else if (IS_DRAWABLE(element))
1569 DrawScreenElement(x, y, element);
1571 DrawScreenElement(x, y, EL_EMPTY);
1574 void DrawLevelField(int x, int y)
1576 if (IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1577 DrawScreenField(SCREENX(x), SCREENY(y));
1578 else if (IS_MOVING(x, y))
1582 Moving2Blocked(x, y, &newx, &newy);
1583 if (IN_SCR_FIELD(SCREENX(newx), SCREENY(newy)))
1584 DrawScreenField(SCREENX(newx), SCREENY(newy));
1586 else if (IS_BLOCKED(x, y))
1590 Blocked2Moving(x, y, &oldx, &oldy);
1591 if (IN_SCR_FIELD(SCREENX(oldx), SCREENY(oldy)))
1592 DrawScreenField(SCREENX(oldx), SCREENY(oldy));
1596 void DrawMiniElement(int x, int y, int element)
1600 graphic = el2edimg(element);
1601 DrawMiniGraphic(x, y, graphic);
1604 void DrawMiniElementOrWall(int sx, int sy, int scroll_x, int scroll_y)
1606 int x = sx + scroll_x, y = sy + scroll_y;
1608 if (x < -1 || x > lev_fieldx || y < -1 || y > lev_fieldy)
1609 DrawMiniElement(sx, sy, EL_EMPTY);
1610 else if (x > -1 && x < lev_fieldx && y > -1 && y < lev_fieldy)
1611 DrawMiniElement(sx, sy, Feld[x][y]);
1613 DrawMiniGraphic(sx, sy, el2edimg(getBorderElement(x, y)));
1616 void DrawEnvelopeBackground(int envelope_nr, int startx, int starty,
1617 int x, int y, int xsize, int ysize, int font_nr)
1619 int font_width = getFontWidth(font_nr);
1620 int font_height = getFontHeight(font_nr);
1621 int graphic = IMG_BACKGROUND_ENVELOPE_1 + envelope_nr;
1624 int dst_x = SX + startx + x * font_width;
1625 int dst_y = SY + starty + y * font_height;
1626 int width = graphic_info[graphic].width;
1627 int height = graphic_info[graphic].height;
1628 int inner_width = MAX(width - 2 * font_width, font_width);
1629 int inner_height = MAX(height - 2 * font_height, font_height);
1630 int inner_sx = (width >= 3 * font_width ? font_width : 0);
1631 int inner_sy = (height >= 3 * font_height ? font_height : 0);
1632 boolean draw_masked = graphic_info[graphic].draw_masked;
1634 getGraphicSource(graphic, 0, &src_bitmap, &src_x, &src_y);
1636 if (src_bitmap == NULL || width < font_width || height < font_height)
1638 ClearRectangle(drawto, dst_x, dst_y, font_width, font_height);
1642 src_x += (x == 0 ? 0 : x == xsize - 1 ? width - font_width :
1643 inner_sx + (x - 1) * font_width % inner_width);
1644 src_y += (y == 0 ? 0 : y == ysize - 1 ? height - font_height :
1645 inner_sy + (y - 1) * font_height % inner_height);
1649 SetClipOrigin(src_bitmap, src_bitmap->stored_clip_gc,
1650 dst_x - src_x, dst_y - src_y);
1651 BlitBitmapMasked(src_bitmap, drawto, src_x, src_y, font_width, font_height,
1655 BlitBitmap(src_bitmap, drawto, src_x, src_y, font_width, font_height,
1659 void AnimateEnvelope(int envelope_nr, int anim_mode, int action)
1661 int graphic = IMG_BACKGROUND_ENVELOPE_1 + envelope_nr;
1662 boolean draw_masked = graphic_info[graphic].draw_masked;
1663 int mask_mode = (draw_masked ? BLIT_MASKED : BLIT_ON_BACKGROUND);
1664 boolean ffwd_delay = (tape.playing && tape.fast_forward);
1665 boolean no_delay = (tape.warp_forward);
1666 unsigned long anim_delay = 0;
1667 int frame_delay_value = (ffwd_delay ? FfwdFrameDelay : GameFrameDelay);
1668 int anim_delay_value = (no_delay ? 0 : frame_delay_value);
1669 int font_nr = FONT_ENVELOPE_1 + envelope_nr;
1670 int font_width = getFontWidth(font_nr);
1671 int font_height = getFontHeight(font_nr);
1672 int max_xsize = level.envelope_xsize[envelope_nr];
1673 int max_ysize = level.envelope_ysize[envelope_nr];
1674 int xstart = (anim_mode & ANIM_VERTICAL ? max_xsize : 0);
1675 int ystart = (anim_mode & ANIM_HORIZONTAL ? max_ysize : 0);
1676 int xend = max_xsize;
1677 int yend = (anim_mode != ANIM_DEFAULT ? max_ysize : 0);
1678 int xstep = (xstart < xend ? 1 : 0);
1679 int ystep = (ystart < yend || xstep == 0 ? 1 : 0);
1682 for (x = xstart, y = ystart; x <= xend && y <= yend; x += xstep, y += ystep)
1684 int xsize = (action == ACTION_CLOSING ? xend - (x - xstart) : x) + 2;
1685 int ysize = (action == ACTION_CLOSING ? yend - (y - ystart) : y) + 2;
1686 int sx = (SXSIZE - xsize * font_width) / 2;
1687 int sy = (SYSIZE - ysize * font_height) / 2;
1690 SetDrawtoField(DRAW_BUFFERED);
1692 BlitBitmap(fieldbuffer, backbuffer, FX, FY, SXSIZE, SYSIZE, SX, SY);
1694 SetDrawtoField(DRAW_BACKBUFFER);
1696 for (yy = 0; yy < ysize; yy++) for (xx = 0; xx < xsize; xx++)
1697 DrawEnvelopeBackground(envelope_nr, sx,sy, xx,yy, xsize, ysize, font_nr);
1699 DrawTextToTextArea(SX + sx + font_width, SY + sy + font_height,
1700 level.envelope_text[envelope_nr], font_nr, max_xsize,
1701 xsize - 2, ysize - 2, mask_mode);
1703 redraw_mask |= REDRAW_FIELD | REDRAW_FROM_BACKBUFFER;
1706 WaitUntilDelayReached(&anim_delay, anim_delay_value / 2);
1710 void ShowEnvelope(int envelope_nr)
1712 int element = EL_ENVELOPE_1 + envelope_nr;
1713 int graphic = IMG_BACKGROUND_ENVELOPE_1 + envelope_nr;
1714 int sound_opening = element_info[element].sound[ACTION_OPENING];
1715 int sound_closing = element_info[element].sound[ACTION_CLOSING];
1716 boolean ffwd_delay = (tape.playing && tape.fast_forward);
1717 boolean no_delay = (tape.warp_forward);
1718 int normal_delay_value = ONE_SECOND_DELAY / (ffwd_delay ? 2 : 1);
1719 int wait_delay_value = (no_delay ? 0 : normal_delay_value);
1720 int anim_mode = graphic_info[graphic].anim_mode;
1721 int main_anim_mode = (anim_mode == ANIM_NONE ? ANIM_VERTICAL|ANIM_HORIZONTAL:
1722 anim_mode == ANIM_DEFAULT ? ANIM_VERTICAL : anim_mode);
1724 game.envelope_active = TRUE; /* needed for RedrawPlayfield() events */
1726 PlaySoundStereo(sound_opening, SOUND_MIDDLE);
1728 if (anim_mode == ANIM_DEFAULT)
1729 AnimateEnvelope(envelope_nr, ANIM_DEFAULT, ACTION_OPENING);
1731 AnimateEnvelope(envelope_nr, main_anim_mode, ACTION_OPENING);
1734 Delay(wait_delay_value);
1736 WaitForEventToContinue();
1738 PlaySoundStereo(sound_closing, SOUND_MIDDLE);
1740 if (anim_mode != ANIM_NONE)
1741 AnimateEnvelope(envelope_nr, main_anim_mode, ACTION_CLOSING);
1743 if (anim_mode == ANIM_DEFAULT)
1744 AnimateEnvelope(envelope_nr, ANIM_DEFAULT, ACTION_CLOSING);
1746 game.envelope_active = FALSE;
1748 SetDrawtoField(DRAW_BUFFERED);
1750 redraw_mask |= REDRAW_FIELD;
1754 void getMicroGraphicSource(int graphic, Bitmap **bitmap, int *x, int *y)
1756 Bitmap *src_bitmap = graphic_info[graphic].bitmap;
1757 int mini_startx = src_bitmap->width * 3 / 4;
1758 int mini_starty = src_bitmap->height * 2 / 3;
1759 int src_x = mini_startx + graphic_info[graphic].src_x / 8;
1760 int src_y = mini_starty + graphic_info[graphic].src_y / 8;
1762 *bitmap = src_bitmap;
1767 void DrawMicroElement(int xpos, int ypos, int element)
1771 int graphic = el2preimg(element);
1773 getMicroGraphicSource(graphic, &src_bitmap, &src_x, &src_y);
1774 BlitBitmap(src_bitmap, drawto, src_x, src_y, MICRO_TILEX, MICRO_TILEY,
1782 SetDrawBackgroundMask(REDRAW_NONE);
1785 for (x = BX1; x <= BX2; x++)
1786 for (y = BY1; y <= BY2; y++)
1787 DrawScreenField(x, y);
1789 redraw_mask |= REDRAW_FIELD;
1792 void DrawMiniLevel(int size_x, int size_y, int scroll_x, int scroll_y)
1796 for (x = 0; x < size_x; x++)
1797 for (y = 0; y < size_y; y++)
1798 DrawMiniElementOrWall(x, y, scroll_x, scroll_y);
1800 redraw_mask |= REDRAW_FIELD;
1803 static void DrawMicroLevelExt(int xpos, int ypos, int from_x, int from_y)
1807 DrawBackground(xpos, ypos, MICROLEV_XSIZE, MICROLEV_YSIZE);
1809 if (lev_fieldx < STD_LEV_FIELDX)
1810 xpos += (STD_LEV_FIELDX - lev_fieldx) / 2 * MICRO_TILEX;
1811 if (lev_fieldy < STD_LEV_FIELDY)
1812 ypos += (STD_LEV_FIELDY - lev_fieldy) / 2 * MICRO_TILEY;
1814 xpos += MICRO_TILEX;
1815 ypos += MICRO_TILEY;
1817 for (x = -1; x <= STD_LEV_FIELDX; x++)
1819 for (y = -1; y <= STD_LEV_FIELDY; y++)
1821 int lx = from_x + x, ly = from_y + y;
1823 if (lx >= 0 && lx < lev_fieldx && ly >= 0 && ly < lev_fieldy)
1824 DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
1825 level.field[lx][ly]);
1826 else if (lx >= -1 && lx < lev_fieldx+1 && ly >= -1 && ly < lev_fieldy+1
1827 && BorderElement != EL_EMPTY)
1828 DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
1829 getBorderElement(lx, ly));
1833 redraw_mask |= REDRAW_MICROLEVEL;
1836 #define MICROLABEL_EMPTY 0
1837 #define MICROLABEL_LEVEL_NAME 1
1838 #define MICROLABEL_CREATED_BY 2
1839 #define MICROLABEL_LEVEL_AUTHOR 3
1840 #define MICROLABEL_IMPORTED_FROM 4
1841 #define MICROLABEL_LEVEL_IMPORT_INFO 5
1843 static void DrawMicroLevelLabelExt(int mode)
1845 char label_text[MAX_OUTPUT_LINESIZE + 1];
1846 int max_len_label_text;
1847 int font_nr = FONT_TEXT_2;
1849 if (mode == MICROLABEL_CREATED_BY || mode == MICROLABEL_IMPORTED_FROM)
1850 font_nr = FONT_TEXT_3;
1852 max_len_label_text = SXSIZE / getFontWidth(font_nr);
1854 DrawBackground(SX, MICROLABEL_YPOS, SXSIZE, getFontHeight(font_nr));
1856 strncpy(label_text, (mode == MICROLABEL_LEVEL_NAME ? level.name :
1857 mode == MICROLABEL_CREATED_BY ? "created by" :
1858 mode == MICROLABEL_LEVEL_AUTHOR ? level.author :
1859 mode == MICROLABEL_IMPORTED_FROM ? "imported from" :
1860 mode == MICROLABEL_LEVEL_IMPORT_INFO ?
1861 leveldir_current->imported_from : ""),
1862 max_len_label_text);
1863 label_text[max_len_label_text] = '\0';
1865 if (strlen(label_text) > 0)
1867 int lxpos = SX + (SXSIZE - getTextWidth(label_text, font_nr)) / 2;
1868 int lypos = MICROLABEL_YPOS;
1870 DrawText(lxpos, lypos, label_text, font_nr);
1873 redraw_mask |= REDRAW_MICROLEVEL;
1876 void DrawMicroLevel(int xpos, int ypos, boolean restart)
1878 static unsigned long scroll_delay = 0;
1879 static unsigned long label_delay = 0;
1880 static int from_x, from_y, scroll_direction;
1881 static int label_state, label_counter;
1882 int last_game_status = game_status; /* save current game status */
1884 /* force PREVIEW font on preview level */
1885 game_status = GAME_MODE_PSEUDO_PREVIEW;
1889 from_x = from_y = 0;
1890 scroll_direction = MV_RIGHT;
1894 DrawMicroLevelExt(xpos, ypos, from_x, from_y);
1895 DrawMicroLevelLabelExt(label_state);
1897 /* initialize delay counters */
1898 DelayReached(&scroll_delay, 0);
1899 DelayReached(&label_delay, 0);
1901 if (leveldir_current->name)
1903 int text_width = getTextWidth(leveldir_current->name, FONT_TEXT_1);
1904 int lxpos = SX + (SXSIZE - text_width) / 2;
1905 int lypos = SY + 352;
1907 DrawText(lxpos, lypos, leveldir_current->name, FONT_TEXT_1);
1910 game_status = last_game_status; /* restore current game status */
1915 /* scroll micro level, if needed */
1916 if ((lev_fieldx > STD_LEV_FIELDX || lev_fieldy > STD_LEV_FIELDY) &&
1917 DelayReached(&scroll_delay, MICROLEVEL_SCROLL_DELAY))
1919 switch (scroll_direction)
1925 scroll_direction = MV_UP;
1929 if (from_x < lev_fieldx - STD_LEV_FIELDX)
1932 scroll_direction = MV_DOWN;
1939 scroll_direction = MV_RIGHT;
1943 if (from_y < lev_fieldy - STD_LEV_FIELDY)
1946 scroll_direction = MV_LEFT;
1953 DrawMicroLevelExt(xpos, ypos, from_x, from_y);
1956 /* redraw micro level label, if needed */
1957 if (strcmp(level.name, NAMELESS_LEVEL_NAME) != 0 &&
1958 strcmp(level.author, ANONYMOUS_NAME) != 0 &&
1959 strcmp(level.author, leveldir_current->name) != 0 &&
1960 DelayReached(&label_delay, MICROLEVEL_LABEL_DELAY))
1962 int max_label_counter = 23;
1964 if (leveldir_current->imported_from != NULL)
1965 max_label_counter += 14;
1967 label_counter = (label_counter + 1) % max_label_counter;
1968 label_state = (label_counter >= 0 && label_counter <= 7 ?
1969 MICROLABEL_LEVEL_NAME :
1970 label_counter >= 9 && label_counter <= 12 ?
1971 MICROLABEL_CREATED_BY :
1972 label_counter >= 14 && label_counter <= 21 ?
1973 MICROLABEL_LEVEL_AUTHOR :
1974 label_counter >= 23 && label_counter <= 26 ?
1975 MICROLABEL_IMPORTED_FROM :
1976 label_counter >= 28 && label_counter <= 35 ?
1977 MICROLABEL_LEVEL_IMPORT_INFO : MICROLABEL_EMPTY);
1978 DrawMicroLevelLabelExt(label_state);
1981 game_status = last_game_status; /* restore current game status */
1984 void WaitForEventToContinue()
1986 boolean still_wait = TRUE;
1988 /* simulate releasing mouse button over last gadget, if still pressed */
1990 HandleGadgets(-1, -1, 0);
1992 button_status = MB_RELEASED;
2004 case EVENT_BUTTONPRESS:
2005 case EVENT_KEYPRESS:
2009 case EVENT_KEYRELEASE:
2010 ClearPlayerAction();
2014 HandleOtherEvents(&event);
2018 else if (AnyJoystickButton() == JOY_BUTTON_NEW_PRESSED)
2025 /* don't eat all CPU time */
2030 #define MAX_REQUEST_LINES 13
2031 #define MAX_REQUEST_LINE_FONT1_LEN 7
2032 #define MAX_REQUEST_LINE_FONT2_LEN 10
2034 boolean Request(char *text, unsigned int req_state)
2036 int mx, my, ty, result = -1;
2037 unsigned int old_door_state;
2038 int last_game_status = game_status; /* save current game status */
2039 int max_request_line_len = MAX_REQUEST_LINE_FONT1_LEN;
2040 int font_nr = FONT_TEXT_2;
2041 int max_word_len = 0;
2044 for (text_ptr = text; *text_ptr; text_ptr++)
2046 max_word_len = (*text_ptr != ' ' ? max_word_len + 1 : 0);
2048 if (max_word_len > MAX_REQUEST_LINE_FONT1_LEN)
2050 max_request_line_len = MAX_REQUEST_LINE_FONT2_LEN;
2051 font_nr = FONT_LEVEL_NUMBER;
2058 /* disable deactivated drawing when quick-loading level tape recording */
2059 if (tape.playing && tape.deactivate_display)
2060 TapeDeactivateDisplayOff(TRUE);
2064 SetMouseCursor(CURSOR_DEFAULT);
2067 #if defined(PLATFORM_UNIX)
2068 /* pause network game while waiting for request to answer */
2069 if (options.network &&
2070 game_status == GAME_MODE_PLAYING &&
2071 req_state & REQUEST_WAIT_FOR)
2072 SendToServer_PausePlaying();
2075 old_door_state = GetDoorState();
2077 /* simulate releasing mouse button over last gadget, if still pressed */
2079 HandleGadgets(-1, -1, 0);
2083 CloseDoor(DOOR_CLOSE_1);
2085 /* save old door content */
2086 BlitBitmap(bitmap_db_door, bitmap_db_door,
2087 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE,
2088 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1);
2090 SetDrawBackgroundMask(REDRAW_FIELD | REDRAW_DOOR_1);
2092 /* clear door drawing field */
2093 DrawBackground(DX, DY, DXSIZE, DYSIZE);
2095 /* force DOOR font on preview level */
2096 game_status = GAME_MODE_PSEUDO_DOOR;
2098 /* write text for request */
2099 for (ty = 0; ty < MAX_REQUEST_LINES; ty++)
2101 char text_line[max_request_line_len + 1];
2107 for (tl = 0, tx = 0; tx < max_request_line_len; tl++, tx++)
2110 if (!tc || tc == ' ')
2121 strncpy(text_line, text, tl);
2124 DrawText(DX + (DXSIZE - tl * getFontWidth(font_nr)) / 2,
2125 DY + 8 + ty * (getFontHeight(font_nr) + 2),
2126 text_line, font_nr);
2128 text += tl + (tc == ' ' ? 1 : 0);
2131 game_status = last_game_status; /* restore current game status */
2133 if (req_state & REQ_ASK)
2135 MapGadget(tool_gadget[TOOL_CTRL_ID_YES]);
2136 MapGadget(tool_gadget[TOOL_CTRL_ID_NO]);
2138 else if (req_state & REQ_CONFIRM)
2140 MapGadget(tool_gadget[TOOL_CTRL_ID_CONFIRM]);
2142 else if (req_state & REQ_PLAYER)
2144 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_1]);
2145 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_2]);
2146 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_3]);
2147 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_4]);
2150 /* copy request gadgets to door backbuffer */
2151 BlitBitmap(drawto, bitmap_db_door,
2152 DX, DY, DXSIZE, DYSIZE,
2153 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
2155 OpenDoor(DOOR_OPEN_1);
2161 if (!(req_state & REQUEST_WAIT_FOR))
2163 SetDrawBackgroundMask(REDRAW_FIELD);
2168 if (game_status != GAME_MODE_MAIN)
2171 button_status = MB_RELEASED;
2173 request_gadget_id = -1;
2175 SetDrawBackgroundMask(REDRAW_FIELD | REDRAW_DOOR_1);
2178 SetMouseCursor(CURSOR_DEFAULT);
2191 case EVENT_BUTTONPRESS:
2192 case EVENT_BUTTONRELEASE:
2193 case EVENT_MOTIONNOTIFY:
2195 if (event.type == EVENT_MOTIONNOTIFY)
2197 if (!PointerInWindow(window))
2198 continue; /* window and pointer are on different screens */
2203 motion_status = TRUE;
2204 mx = ((MotionEvent *) &event)->x;
2205 my = ((MotionEvent *) &event)->y;
2209 motion_status = FALSE;
2210 mx = ((ButtonEvent *) &event)->x;
2211 my = ((ButtonEvent *) &event)->y;
2212 if (event.type == EVENT_BUTTONPRESS)
2213 button_status = ((ButtonEvent *) &event)->button;
2215 button_status = MB_RELEASED;
2218 /* this sets 'request_gadget_id' */
2219 HandleGadgets(mx, my, button_status);
2221 switch(request_gadget_id)
2223 case TOOL_CTRL_ID_YES:
2226 case TOOL_CTRL_ID_NO:
2229 case TOOL_CTRL_ID_CONFIRM:
2230 result = TRUE | FALSE;
2233 case TOOL_CTRL_ID_PLAYER_1:
2236 case TOOL_CTRL_ID_PLAYER_2:
2239 case TOOL_CTRL_ID_PLAYER_3:
2242 case TOOL_CTRL_ID_PLAYER_4:
2253 case EVENT_KEYPRESS:
2254 switch(GetEventKey((KeyEvent *)&event, TRUE))
2267 if (req_state & REQ_PLAYER)
2271 case EVENT_KEYRELEASE:
2272 ClearPlayerAction();
2276 HandleOtherEvents(&event);
2280 else if (AnyJoystickButton() == JOY_BUTTON_NEW_PRESSED)
2282 int joy = AnyJoystick();
2284 if (joy & JOY_BUTTON_1)
2286 else if (joy & JOY_BUTTON_2)
2292 /* don't eat all CPU time */
2296 if (game_status != GAME_MODE_MAIN)
2301 if (!(req_state & REQ_STAY_OPEN))
2303 CloseDoor(DOOR_CLOSE_1);
2305 if (!(req_state & REQ_STAY_CLOSED) && (old_door_state & DOOR_OPEN_1))
2307 BlitBitmap(bitmap_db_door, bitmap_db_door,
2308 DOOR_GFX_PAGEX2,DOOR_GFX_PAGEY1, DXSIZE,DYSIZE,
2309 DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY1);
2310 OpenDoor(DOOR_OPEN_1);
2316 SetDrawBackgroundMask(REDRAW_FIELD);
2318 #if defined(PLATFORM_UNIX)
2319 /* continue network game after request */
2320 if (options.network &&
2321 game_status == GAME_MODE_PLAYING &&
2322 req_state & REQUEST_WAIT_FOR)
2323 SendToServer_ContinuePlaying();
2327 /* restore deactivated drawing when quick-loading level tape recording */
2328 if (tape.playing && tape.deactivate_display)
2329 TapeDeactivateDisplayOn();
2335 unsigned int OpenDoor(unsigned int door_state)
2337 unsigned int new_door_state;
2339 if (door_state & DOOR_COPY_BACK)
2341 BlitBitmap(bitmap_db_door, bitmap_db_door,
2342 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE + VYSIZE,
2343 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
2344 door_state &= ~DOOR_COPY_BACK;
2347 new_door_state = MoveDoor(door_state);
2349 return(new_door_state);
2352 unsigned int CloseDoor(unsigned int door_state)
2354 unsigned int new_door_state;
2356 BlitBitmap(backbuffer, bitmap_db_door,
2357 DX, DY, DXSIZE, DYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
2358 BlitBitmap(backbuffer, bitmap_db_door,
2359 VX, VY, VXSIZE, VYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2);
2361 new_door_state = MoveDoor(door_state);
2363 return(new_door_state);
2366 unsigned int GetDoorState()
2368 return MoveDoor(DOOR_GET_STATE);
2371 unsigned int SetDoorState(unsigned int door_state)
2373 return MoveDoor(door_state | DOOR_SET_STATE);
2376 unsigned int MoveDoor(unsigned int door_state)
2378 static int door1 = DOOR_OPEN_1;
2379 static int door2 = DOOR_CLOSE_2;
2380 unsigned long door_delay = 0;
2381 unsigned long door_delay_value;
2384 if (door_state == DOOR_GET_STATE)
2385 return(door1 | door2);
2387 if (door_state & DOOR_SET_STATE)
2389 if (door_state & DOOR_ACTION_1)
2390 door1 = door_state & DOOR_ACTION_1;
2391 if (door_state & DOOR_ACTION_2)
2392 door2 = door_state & DOOR_ACTION_2;
2394 return(door1 | door2);
2397 if (door1 == DOOR_OPEN_1 && door_state & DOOR_OPEN_1)
2398 door_state &= ~DOOR_OPEN_1;
2399 else if (door1 == DOOR_CLOSE_1 && door_state & DOOR_CLOSE_1)
2400 door_state &= ~DOOR_CLOSE_1;
2401 if (door2 == DOOR_OPEN_2 && door_state & DOOR_OPEN_2)
2402 door_state &= ~DOOR_OPEN_2;
2403 else if (door2 == DOOR_CLOSE_2 && door_state & DOOR_CLOSE_2)
2404 door_state &= ~DOOR_CLOSE_2;
2406 door_delay_value = (door_state & DOOR_ACTION_1 ? door_1.step_delay :
2409 if (setup.quick_doors)
2411 stepsize = 20; /* must be choosen to always draw last frame */
2412 door_delay_value = 0;
2415 StopSound(SND_DOOR_OPENING);
2416 StopSound(SND_DOOR_CLOSING);
2420 if (global.autoplay_leveldir)
2422 door_state |= DOOR_NO_DELAY;
2423 door_state &= ~DOOR_CLOSE_ALL;
2426 if (door_state & DOOR_ACTION)
2428 boolean door_1_done = !(door_state & DOOR_ACTION_1);
2429 boolean door_2_done = !(door_state & DOOR_ACTION_2);
2430 int start = ((door_state & DOOR_NO_DELAY) ? DXSIZE : 0);
2431 int end = (door_state & DOOR_ACTION_1 &&
2432 door_1.anim_mode == ANIM_VERTICAL ? DYSIZE : DXSIZE);
2435 if (!(door_state & DOOR_NO_DELAY) && !setup.quick_doors)
2437 /* opening door sound has priority over simultaneously closing door */
2438 if (door_state & (DOOR_OPEN_1 | DOOR_OPEN_2))
2439 PlaySoundStereo(SND_DOOR_OPENING, SOUND_MIDDLE);
2440 else if (door_state & (DOOR_CLOSE_1 | DOOR_CLOSE_2))
2441 PlaySoundStereo(SND_DOOR_CLOSING, SOUND_MIDDLE);
2444 for (x = start; x <= end && !(door_1_done && door_2_done); x += stepsize)
2446 Bitmap *bitmap = graphic_info[IMG_GLOBAL_DOOR].bitmap;
2447 GC gc = bitmap->stored_clip_gc;
2449 if (door_state & DOOR_ACTION_1)
2451 int a = MIN(x * door_1.step_offset, end);
2452 int i = (door_state & DOOR_OPEN_1 ? end - a : a);
2456 BlitBitmap(bitmap_db_door, drawto,
2457 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1 + i / 2,
2458 DXSIZE,DYSIZE - i / 2, DX, DY);
2460 ClearRectangle(drawto, DX, DY + DYSIZE - i / 2, DXSIZE, i / 2);
2463 if (door_1.anim_mode == ANIM_HORIZONTAL && x <= DXSIZE)
2465 int src1_x = DXSIZE, src1_y = DOOR_GFX_PAGEY1;
2466 int dst1_x = DX + DXSIZE - i, dst1_y = DY;
2467 int src2_x = DXSIZE - i, src2_y = DOOR_GFX_PAGEY1;
2468 int dst2_x = DX, dst2_y = DY;
2469 int width = i, height = DYSIZE;
2471 SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y);
2472 BlitBitmapMasked(bitmap, drawto, src1_x, src1_y, width, height,
2475 SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y);
2476 BlitBitmapMasked(bitmap, drawto, src2_x, src2_y, width, height,
2479 else if (door_1.anim_mode == ANIM_VERTICAL && x <= DYSIZE)
2481 int src1_x = DXSIZE, src1_y = DOOR_GFX_PAGEY1;
2482 int dst1_x = DX, dst1_y = DY + DYSIZE - i;
2483 int src2_x = 0, src2_y = DOOR_GFX_PAGEY1 + DYSIZE - i;
2484 int dst2_x = DX, dst2_y = DY;
2485 int width = DXSIZE, height = i;
2487 SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y);
2488 BlitBitmapMasked(bitmap, drawto, src1_x, src1_y, width, height,
2491 SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y);
2492 BlitBitmapMasked(bitmap, drawto, src2_x, src2_y, width, height,
2495 else if (x <= DXSIZE) /* ANIM_DEFAULT */
2497 int j = (door_1.anim_mode == ANIM_DEFAULT ? (DXSIZE - i) / 3 : 0);
2499 SetClipOrigin(bitmap, gc, DX - i, (DY + j) - DOOR_GFX_PAGEY1);
2500 BlitBitmapMasked(bitmap, drawto,
2501 DXSIZE, DOOR_GFX_PAGEY1, i, 77,
2502 DX + DXSIZE - i, DY + j);
2503 BlitBitmapMasked(bitmap, drawto,
2504 DXSIZE, DOOR_GFX_PAGEY1 + 140, i, 63,
2505 DX + DXSIZE - i, DY + 140 + j);
2506 SetClipOrigin(bitmap, gc, DX - DXSIZE + i,
2507 DY - (DOOR_GFX_PAGEY1 + j));
2508 BlitBitmapMasked(bitmap, drawto,
2509 DXSIZE - i, DOOR_GFX_PAGEY1 + j, i, 77 - j,
2511 BlitBitmapMasked(bitmap, drawto,
2512 DXSIZE-i, DOOR_GFX_PAGEY1 + 140, i, 63,
2515 BlitBitmapMasked(bitmap, drawto,
2516 DXSIZE - i, DOOR_GFX_PAGEY1 + 77, i, 63,
2518 BlitBitmapMasked(bitmap, drawto,
2519 DXSIZE - i, DOOR_GFX_PAGEY1 + 203, i, 77,
2521 SetClipOrigin(bitmap, gc, DX - i, (DY + j) - DOOR_GFX_PAGEY1);
2522 BlitBitmapMasked(bitmap, drawto,
2523 DXSIZE, DOOR_GFX_PAGEY1 + 77, i, 63,
2524 DX + DXSIZE - i, DY + 77 + j);
2525 BlitBitmapMasked(bitmap, drawto,
2526 DXSIZE, DOOR_GFX_PAGEY1 + 203, i, 77 - j,
2527 DX + DXSIZE - i, DY + 203 + j);
2530 redraw_mask |= REDRAW_DOOR_1;
2531 door_1_done = (a == end);
2534 if (door_state & DOOR_ACTION_2)
2536 int a = MIN(x * door_2.step_offset, VXSIZE);
2537 int i = (door_state & DOOR_OPEN_2 ? VXSIZE - a : a);
2541 BlitBitmap(bitmap_db_door, drawto,
2542 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2 + i / 2,
2543 VXSIZE, VYSIZE - i / 2, VX, VY);
2545 ClearRectangle(drawto, VX, VY + VYSIZE - i / 2, VXSIZE, i / 2);
2548 if (door_2.anim_mode == ANIM_HORIZONTAL && x <= VXSIZE)
2550 int src1_x = VXSIZE, src1_y = DOOR_GFX_PAGEY2;
2551 int dst1_x = VX + VXSIZE - i, dst1_y = VY;
2552 int src2_x = VXSIZE - i, src2_y = DOOR_GFX_PAGEY2;
2553 int dst2_x = VX, dst2_y = VY;
2554 int width = i, height = VYSIZE;
2556 SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y);
2557 BlitBitmapMasked(bitmap, drawto, src1_x, src1_y, width, height,
2560 SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y);
2561 BlitBitmapMasked(bitmap, drawto, src2_x, src2_y, width, height,
2564 else if (door_2.anim_mode == ANIM_VERTICAL && x <= VYSIZE)
2566 int src1_x = VXSIZE, src1_y = DOOR_GFX_PAGEY2;
2567 int dst1_x = VX, dst1_y = VY + VYSIZE - i;
2568 int src2_x = 0, src2_y = DOOR_GFX_PAGEY2 + VYSIZE - i;
2569 int dst2_x = VX, dst2_y = VY;
2570 int width = VXSIZE, height = i;
2572 SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y);
2573 BlitBitmapMasked(bitmap, drawto, src1_x, src1_y, width, height,
2576 SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y);
2577 BlitBitmapMasked(bitmap, drawto, src2_x, src2_y, width, height,
2580 else if (x <= VXSIZE) /* ANIM_DEFAULT */
2582 int j = (door_2.anim_mode == ANIM_DEFAULT ? (VXSIZE - i) / 3 : 0);
2584 SetClipOrigin(bitmap, gc, VX - i, (VY + j) - DOOR_GFX_PAGEY2);
2585 BlitBitmapMasked(bitmap, drawto,
2586 VXSIZE, DOOR_GFX_PAGEY2, i, VYSIZE / 2,
2587 VX + VXSIZE - i, VY + j);
2588 SetClipOrigin(bitmap, gc,
2589 VX - VXSIZE + i, VY - (DOOR_GFX_PAGEY2 + j));
2590 BlitBitmapMasked(bitmap, drawto,
2591 VXSIZE - i, DOOR_GFX_PAGEY2 + j, i, VYSIZE / 2 - j,
2594 BlitBitmapMasked(bitmap, drawto,
2595 VXSIZE - i, DOOR_GFX_PAGEY2 + VYSIZE / 2,
2596 i, VYSIZE / 2, VX, VY + VYSIZE / 2 - j);
2597 SetClipOrigin(bitmap, gc, VX - i, (VY + j) - DOOR_GFX_PAGEY2);
2598 BlitBitmapMasked(bitmap, drawto,
2599 VXSIZE, DOOR_GFX_PAGEY2 + VYSIZE / 2,
2601 VX + VXSIZE - i, VY + VYSIZE / 2 + j);
2604 redraw_mask |= REDRAW_DOOR_2;
2605 door_2_done = (a == VXSIZE);
2610 if (game_status == GAME_MODE_MAIN)
2613 if (!(door_state & DOOR_NO_DELAY))
2614 WaitUntilDelayReached(&door_delay, door_delay_value);
2619 if (setup.quick_doors)
2621 StopSound(SND_DOOR_OPENING);
2622 StopSound(SND_DOOR_CLOSING);
2626 if (door_state & DOOR_ACTION_1)
2627 door1 = door_state & DOOR_ACTION_1;
2628 if (door_state & DOOR_ACTION_2)
2629 door2 = door_state & DOOR_ACTION_2;
2631 return (door1 | door2);
2634 void DrawSpecialEditorDoor()
2636 /* draw bigger toolbox window */
2637 BlitBitmap(graphic_info[IMG_GLOBAL_DOOR].bitmap, drawto,
2638 DOOR_GFX_PAGEX7, 0, EXSIZE + 8, 8,
2640 BlitBitmap(graphic_info[IMG_GLOBAL_BORDER].bitmap, drawto,
2641 EX - 4, VY - 4, EXSIZE + 8, EYSIZE - VYSIZE + 4,
2644 redraw_mask |= REDRAW_ALL;
2647 void UndrawSpecialEditorDoor()
2649 /* draw normal tape recorder window */
2650 BlitBitmap(graphic_info[IMG_GLOBAL_BORDER].bitmap, drawto,
2651 EX - 4, EY - 12, EXSIZE + 8, EYSIZE - VYSIZE + 12,
2654 redraw_mask |= REDRAW_ALL;
2658 /* ---------- new tool button stuff ---------------------------------------- */
2660 /* graphic position values for tool buttons */
2661 #define TOOL_BUTTON_YES_XPOS 2
2662 #define TOOL_BUTTON_YES_YPOS 250
2663 #define TOOL_BUTTON_YES_GFX_YPOS 0
2664 #define TOOL_BUTTON_YES_XSIZE 46
2665 #define TOOL_BUTTON_YES_YSIZE 28
2666 #define TOOL_BUTTON_NO_XPOS 52
2667 #define TOOL_BUTTON_NO_YPOS TOOL_BUTTON_YES_YPOS
2668 #define TOOL_BUTTON_NO_GFX_YPOS TOOL_BUTTON_YES_GFX_YPOS
2669 #define TOOL_BUTTON_NO_XSIZE TOOL_BUTTON_YES_XSIZE
2670 #define TOOL_BUTTON_NO_YSIZE TOOL_BUTTON_YES_YSIZE
2671 #define TOOL_BUTTON_CONFIRM_XPOS TOOL_BUTTON_YES_XPOS
2672 #define TOOL_BUTTON_CONFIRM_YPOS TOOL_BUTTON_YES_YPOS
2673 #define TOOL_BUTTON_CONFIRM_GFX_YPOS 30
2674 #define TOOL_BUTTON_CONFIRM_XSIZE 96
2675 #define TOOL_BUTTON_CONFIRM_YSIZE TOOL_BUTTON_YES_YSIZE
2676 #define TOOL_BUTTON_PLAYER_XSIZE 30
2677 #define TOOL_BUTTON_PLAYER_YSIZE 30
2678 #define TOOL_BUTTON_PLAYER_GFX_XPOS 5
2679 #define TOOL_BUTTON_PLAYER_GFX_YPOS 185
2680 #define TOOL_BUTTON_PLAYER_XPOS (5 + TOOL_BUTTON_PLAYER_XSIZE / 2)
2681 #define TOOL_BUTTON_PLAYER_YPOS (215 - TOOL_BUTTON_PLAYER_YSIZE / 2)
2682 #define TOOL_BUTTON_PLAYER1_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2683 + 0 * TOOL_BUTTON_PLAYER_XSIZE)
2684 #define TOOL_BUTTON_PLAYER2_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2685 + 1 * TOOL_BUTTON_PLAYER_XSIZE)
2686 #define TOOL_BUTTON_PLAYER3_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2687 + 0 * TOOL_BUTTON_PLAYER_XSIZE)
2688 #define TOOL_BUTTON_PLAYER4_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2689 + 1 * TOOL_BUTTON_PLAYER_XSIZE)
2690 #define TOOL_BUTTON_PLAYER1_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2691 + 0 * TOOL_BUTTON_PLAYER_YSIZE)
2692 #define TOOL_BUTTON_PLAYER2_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2693 + 0 * TOOL_BUTTON_PLAYER_YSIZE)
2694 #define TOOL_BUTTON_PLAYER3_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2695 + 1 * TOOL_BUTTON_PLAYER_YSIZE)
2696 #define TOOL_BUTTON_PLAYER4_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2697 + 1 * TOOL_BUTTON_PLAYER_YSIZE)
2706 } toolbutton_info[NUM_TOOL_BUTTONS] =
2709 TOOL_BUTTON_YES_XPOS, TOOL_BUTTON_YES_GFX_YPOS,
2710 TOOL_BUTTON_YES_XPOS, TOOL_BUTTON_YES_YPOS,
2711 TOOL_BUTTON_YES_XSIZE, TOOL_BUTTON_YES_YSIZE,
2716 TOOL_BUTTON_NO_XPOS, TOOL_BUTTON_NO_GFX_YPOS,
2717 TOOL_BUTTON_NO_XPOS, TOOL_BUTTON_NO_YPOS,
2718 TOOL_BUTTON_NO_XSIZE, TOOL_BUTTON_NO_YSIZE,
2723 TOOL_BUTTON_CONFIRM_XPOS, TOOL_BUTTON_CONFIRM_GFX_YPOS,
2724 TOOL_BUTTON_CONFIRM_XPOS, TOOL_BUTTON_CONFIRM_YPOS,
2725 TOOL_BUTTON_CONFIRM_XSIZE, TOOL_BUTTON_CONFIRM_YSIZE,
2726 TOOL_CTRL_ID_CONFIRM,
2730 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2731 TOOL_BUTTON_PLAYER1_XPOS, TOOL_BUTTON_PLAYER1_YPOS,
2732 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2733 TOOL_CTRL_ID_PLAYER_1,
2737 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2738 TOOL_BUTTON_PLAYER2_XPOS, TOOL_BUTTON_PLAYER2_YPOS,
2739 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2740 TOOL_CTRL_ID_PLAYER_2,
2744 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2745 TOOL_BUTTON_PLAYER3_XPOS, TOOL_BUTTON_PLAYER3_YPOS,
2746 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2747 TOOL_CTRL_ID_PLAYER_3,
2751 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2752 TOOL_BUTTON_PLAYER4_XPOS, TOOL_BUTTON_PLAYER4_YPOS,
2753 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2754 TOOL_CTRL_ID_PLAYER_4,
2759 void CreateToolButtons()
2763 for (i = 0; i < NUM_TOOL_BUTTONS; i++)
2765 Bitmap *gd_bitmap = graphic_info[IMG_GLOBAL_DOOR].bitmap;
2766 Bitmap *deco_bitmap = None;
2767 int deco_x = 0, deco_y = 0, deco_xpos = 0, deco_ypos = 0;
2768 struct GadgetInfo *gi;
2769 unsigned long event_mask;
2770 int gd_xoffset, gd_yoffset;
2771 int gd_x1, gd_x2, gd_y;
2774 event_mask = GD_EVENT_RELEASED;
2776 gd_xoffset = toolbutton_info[i].xpos;
2777 gd_yoffset = toolbutton_info[i].ypos;
2778 gd_x1 = DOOR_GFX_PAGEX4 + gd_xoffset;
2779 gd_x2 = DOOR_GFX_PAGEX3 + gd_xoffset;
2780 gd_y = DOOR_GFX_PAGEY1 + gd_yoffset;
2782 if (id >= TOOL_CTRL_ID_PLAYER_1 && id <= TOOL_CTRL_ID_PLAYER_4)
2784 int player_nr = id - TOOL_CTRL_ID_PLAYER_1;
2786 getMiniGraphicSource(PLAYER_NR_GFX(IMG_PLAYER_1, player_nr),
2787 &deco_bitmap, &deco_x, &deco_y);
2788 deco_xpos = (toolbutton_info[i].width - MINI_TILEX) / 2;
2789 deco_ypos = (toolbutton_info[i].height - MINI_TILEY) / 2;
2792 gi = CreateGadget(GDI_CUSTOM_ID, id,
2793 GDI_INFO_TEXT, toolbutton_info[i].infotext,
2794 GDI_X, DX + toolbutton_info[i].x,
2795 GDI_Y, DY + toolbutton_info[i].y,
2796 GDI_WIDTH, toolbutton_info[i].width,
2797 GDI_HEIGHT, toolbutton_info[i].height,
2798 GDI_TYPE, GD_TYPE_NORMAL_BUTTON,
2799 GDI_STATE, GD_BUTTON_UNPRESSED,
2800 GDI_DESIGN_UNPRESSED, gd_bitmap, gd_x1, gd_y,
2801 GDI_DESIGN_PRESSED, gd_bitmap, gd_x2, gd_y,
2802 GDI_DECORATION_DESIGN, deco_bitmap, deco_x, deco_y,
2803 GDI_DECORATION_POSITION, deco_xpos, deco_ypos,
2804 GDI_DECORATION_SIZE, MINI_TILEX, MINI_TILEY,
2805 GDI_DECORATION_SHIFTING, 1, 1,
2806 GDI_EVENT_MASK, event_mask,
2807 GDI_CALLBACK_ACTION, HandleToolButtons,
2811 Error(ERR_EXIT, "cannot create gadget");
2813 tool_gadget[id] = gi;
2817 void FreeToolButtons()
2821 for (i = 0; i < NUM_TOOL_BUTTONS; i++)
2822 FreeGadget(tool_gadget[i]);
2825 static void UnmapToolButtons()
2829 for (i = 0; i < NUM_TOOL_BUTTONS; i++)
2830 UnmapGadget(tool_gadget[i]);
2833 static void HandleToolButtons(struct GadgetInfo *gi)
2835 request_gadget_id = gi->custom_id;
2838 int get_next_element(int element)
2842 case EL_QUICKSAND_FILLING: return EL_QUICKSAND_FULL;
2843 case EL_QUICKSAND_EMPTYING: return EL_QUICKSAND_EMPTY;
2844 case EL_MAGIC_WALL_FILLING: return EL_MAGIC_WALL_FULL;
2845 case EL_MAGIC_WALL_EMPTYING: return EL_MAGIC_WALL_ACTIVE;
2846 case EL_BD_MAGIC_WALL_FILLING: return EL_BD_MAGIC_WALL_FULL;
2847 case EL_BD_MAGIC_WALL_EMPTYING: return EL_BD_MAGIC_WALL_ACTIVE;
2848 case EL_AMOEBA_DROPPING: return EL_AMOEBA_WET;
2850 default: return element;
2854 int el_act_dir2img(int element, int action, int direction)
2856 element = GFX_ELEMENT(element);
2857 direction = MV_DIR_BIT(direction);
2859 return element_info[element].direction_graphic[action][direction];
2862 static int el_act_dir2crm(int element, int action, int direction)
2864 element = GFX_ELEMENT(element);
2865 direction = MV_DIR_BIT(direction);
2867 return element_info[element].direction_crumbled[action][direction];
2870 int el_act2img(int element, int action)
2872 element = GFX_ELEMENT(element);
2874 return element_info[element].graphic[action];
2877 int el_act2crm(int element, int action)
2879 element = GFX_ELEMENT(element);
2881 return element_info[element].crumbled[action];
2884 int el_dir2img(int element, int direction)
2886 element = GFX_ELEMENT(element);
2888 return el_act_dir2img(element, ACTION_DEFAULT, direction);
2891 int el2img(int element)
2893 element = GFX_ELEMENT(element);
2895 return element_info[element].graphic[ACTION_DEFAULT];
2898 int el2edimg(int element)
2900 element = GFX_ELEMENT(element);
2902 return element_info[element].special_graphic[GFX_SPECIAL_ARG_EDITOR];
2905 int el2preimg(int element)
2907 element = GFX_ELEMENT(element);
2909 return element_info[element].special_graphic[GFX_SPECIAL_ARG_PREVIEW];