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 SetDrawtoField(int mode)
45 if (mode == DRAW_BUFFERED && setup.soft_scrolling)
56 drawto_field = fieldbuffer;
58 else /* DRAW_DIRECT, DRAW_BACKBUFFER */
69 drawto_field = (mode == DRAW_DIRECT ? window : backbuffer);
73 void RedrawPlayfield(boolean force_redraw, int x, int y, int width, int height)
75 if (game_status == GAME_MODE_PLAYING && !game.envelope_active)
81 width = gfx.sxsize + 2 * TILEX;
82 height = gfx.sysize + 2 * TILEY;
85 if (force_redraw || setup.direct_draw)
88 int x1 = (x - SX) / TILEX, y1 = (y - SY) / TILEY;
89 int x2 = (x - SX + width) / TILEX, y2 = (y - SY + height) / TILEY;
91 if (setup.direct_draw)
92 SetDrawtoField(DRAW_BACKBUFFER);
94 for (xx = BX1; xx <= BX2; xx++)
95 for (yy = BY1; yy <= BY2; yy++)
96 if (xx >= x1 && xx <= x2 && yy >= y1 && yy <= y2)
97 DrawScreenField(xx, yy);
100 if (setup.direct_draw)
101 SetDrawtoField(DRAW_DIRECT);
104 if (setup.soft_scrolling)
106 int fx = FX, fy = FY;
108 fx += (ScreenMovDir & (MV_LEFT|MV_RIGHT) ? ScreenGfxPos : 0);
109 fy += (ScreenMovDir & (MV_UP|MV_DOWN) ? ScreenGfxPos : 0);
111 BlitBitmap(fieldbuffer, backbuffer, fx,fy, SXSIZE,SYSIZE, SX,SY);
115 BlitBitmap(drawto, window, x, y, width, height, x, y);
121 DrawBuffer *buffer = (drawto_field == window ? backbuffer : drawto_field);
123 if (setup.direct_draw && game_status == GAME_MODE_PLAYING)
124 redraw_mask &= ~REDRAW_MAIN;
126 if (redraw_mask & REDRAW_TILES && redraw_tiles > REDRAWTILES_THRESHOLD)
127 redraw_mask |= REDRAW_FIELD;
129 if (redraw_mask & REDRAW_FIELD)
130 redraw_mask &= ~REDRAW_TILES;
132 if (redraw_mask == REDRAW_NONE)
135 if (global.fps_slowdown && game_status == GAME_MODE_PLAYING)
137 static boolean last_frame_skipped = FALSE;
138 boolean skip_even_when_not_scrolling = TRUE;
139 boolean just_scrolling = (ScreenMovDir != 0);
140 boolean verbose = FALSE;
142 if (global.fps_slowdown_factor > 1 &&
143 (FrameCounter % global.fps_slowdown_factor) &&
144 (just_scrolling || skip_even_when_not_scrolling))
146 redraw_mask &= ~REDRAW_MAIN;
148 last_frame_skipped = TRUE;
151 printf("FRAME SKIPPED\n");
155 if (last_frame_skipped)
156 redraw_mask |= REDRAW_FIELD;
158 last_frame_skipped = FALSE;
161 printf("frame not skipped\n");
165 /* synchronize X11 graphics at this point; if we would synchronize the
166 display immediately after the buffer switching (after the XFlush),
167 this could mean that we have to wait for the graphics to complete,
168 although we could go on doing calculations for the next frame */
172 if (redraw_mask & REDRAW_ALL)
174 BlitBitmap(backbuffer, window, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
178 if (redraw_mask & REDRAW_FIELD)
180 if (game_status != GAME_MODE_PLAYING ||
181 redraw_mask & REDRAW_FROM_BACKBUFFER)
183 BlitBitmap(backbuffer, window,
184 REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE, REAL_SX, REAL_SY);
188 int fx = FX, fy = FY;
190 if (setup.soft_scrolling)
192 fx += (ScreenMovDir & (MV_LEFT | MV_RIGHT) ? ScreenGfxPos : 0);
193 fy += (ScreenMovDir & (MV_UP | MV_DOWN) ? ScreenGfxPos : 0);
196 if (setup.soft_scrolling ||
197 ABS(ScreenMovPos) + ScrollStepSize == TILEX ||
198 ABS(ScreenMovPos) == ScrollStepSize ||
199 redraw_tiles > REDRAWTILES_THRESHOLD)
201 BlitBitmap(buffer, window, fx, fy, SXSIZE, SYSIZE, SX, SY);
205 printf("redrawing all (ScreenGfxPos == %d) because %s\n",
207 (setup.soft_scrolling ?
208 "setup.soft_scrolling" :
209 ABS(ScreenGfxPos) + ScrollStepSize == TILEX ?
210 "ABS(ScreenGfxPos) + ScrollStepSize == TILEX" :
211 ABS(ScreenGfxPos) == ScrollStepSize ?
212 "ABS(ScreenGfxPos) == ScrollStepSize" :
213 "redraw_tiles > REDRAWTILES_THRESHOLD"));
219 redraw_mask &= ~REDRAW_MAIN;
222 if (redraw_mask & REDRAW_DOORS)
224 if (redraw_mask & REDRAW_DOOR_1)
225 BlitBitmap(backbuffer, window, DX, DY, DXSIZE, DYSIZE, DX, DY);
226 if (redraw_mask & REDRAW_DOOR_2)
228 if ((redraw_mask & REDRAW_DOOR_2) == REDRAW_DOOR_2)
229 BlitBitmap(backbuffer, window, VX,VY, VXSIZE,VYSIZE, VX,VY);
232 if (redraw_mask & REDRAW_VIDEO_1)
233 BlitBitmap(backbuffer, window,
234 VX+VIDEO_DISPLAY1_XPOS,VY+VIDEO_DISPLAY1_YPOS,
235 VIDEO_DISPLAY_XSIZE,VIDEO_DISPLAY_YSIZE,
236 VX+VIDEO_DISPLAY1_XPOS,VY+VIDEO_DISPLAY1_YPOS);
237 if (redraw_mask & REDRAW_VIDEO_2)
238 BlitBitmap(backbuffer, window,
239 VX+VIDEO_DISPLAY2_XPOS,VY+VIDEO_DISPLAY2_YPOS,
240 VIDEO_DISPLAY_XSIZE,VIDEO_DISPLAY_YSIZE,
241 VX+VIDEO_DISPLAY2_XPOS,VY+VIDEO_DISPLAY2_YPOS);
242 if (redraw_mask & REDRAW_VIDEO_3)
243 BlitBitmap(backbuffer, window,
244 VX+VIDEO_CONTROL_XPOS,VY+VIDEO_CONTROL_YPOS,
245 VIDEO_CONTROL_XSIZE,VIDEO_CONTROL_YSIZE,
246 VX+VIDEO_CONTROL_XPOS,VY+VIDEO_CONTROL_YPOS);
250 if (redraw_mask & REDRAW_DOOR_3)
251 BlitBitmap(backbuffer, window, EX, EY, EXSIZE, EYSIZE, EX, EY);
253 redraw_mask &= ~REDRAW_DOORS;
256 if (redraw_mask & REDRAW_MICROLEVEL)
258 BlitBitmap(backbuffer, window, SX, SY + 10 * TILEY, SXSIZE, 7 * TILEY,
259 SX, SY + 10 * TILEY);
261 redraw_mask &= ~REDRAW_MICROLEVEL;
264 if (redraw_mask & REDRAW_TILES)
266 for (x = 0; x < SCR_FIELDX; x++)
267 for (y =0 ; y < SCR_FIELDY; y++)
268 if (redraw[redraw_x1 + x][redraw_y1 + y])
269 BlitBitmap(buffer, window,
270 FX + x * TILEX, FX + y * TILEY, TILEX, TILEY,
271 SX + x * TILEX, SY + y * TILEY);
274 if (redraw_mask & REDRAW_FPS) /* display frames per second */
279 sprintf(info1, " (only every %d. frame)", global.fps_slowdown_factor);
280 if (!global.fps_slowdown)
283 sprintf(text, "%.1f fps%s", global.frames_per_second, info1);
284 DrawTextExt(window, SX, SY, text, FONT_TEXT_2, BLIT_OPAQUE);
289 for (x = 0; x < MAX_BUF_XSIZE; x++)
290 for (y = 0; y < MAX_BUF_YSIZE; y++)
293 redraw_mask = REDRAW_NONE;
299 long fading_delay = 300;
301 if (setup.fading && (redraw_mask & REDRAW_FIELD))
308 ClearRectangle(window, REAL_SX,REAL_SY,FULL_SXSIZE,FULL_SYSIZE);
311 for (i = 0; i < 2 * FULL_SYSIZE; i++)
313 for (y = 0; y < FULL_SYSIZE; y++)
315 BlitBitmap(backbuffer, window,
316 REAL_SX,REAL_SY+i, FULL_SXSIZE,1, REAL_SX,REAL_SY+i);
324 for (i = 1; i < FULL_SYSIZE; i+=2)
325 BlitBitmap(backbuffer, window,
326 REAL_SX,REAL_SY+i, FULL_SXSIZE,1, REAL_SX,REAL_SY+i);
332 SetClipOrigin(clip_gc[PIX_FADEMASK], 0, 0);
333 BlitBitmapMasked(backbuffer, window,
334 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE,
339 SetClipOrigin(clip_gc[PIX_FADEMASK], -1, -1);
340 BlitBitmapMasked(backbuffer, window,
341 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE,
346 SetClipOrigin(clip_gc[PIX_FADEMASK], 0, -1);
347 BlitBitmapMasked(backbuffer, window,
348 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE,
353 SetClipOrigin(clip_gc[PIX_FADEMASK], -1, 0);
354 BlitBitmapMasked(backbuffer, window,
355 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE,
360 redraw_mask &= ~REDRAW_MAIN;
367 void SetMainBackgroundImage(int graphic)
369 SetMainBackgroundBitmap(graphic == IMG_UNDEFINED ? NULL :
370 graphic_info[graphic].bitmap ?
371 graphic_info[graphic].bitmap :
372 graphic_info[IMG_BACKGROUND].bitmap);
375 void SetDoorBackgroundImage(int graphic)
377 SetDoorBackgroundBitmap(graphic == IMG_UNDEFINED ? NULL :
378 graphic_info[graphic].bitmap ?
379 graphic_info[graphic].bitmap :
380 graphic_info[IMG_BACKGROUND].bitmap);
383 void DrawBackground(int dest_x, int dest_y, int width, int height)
385 ClearRectangleOnBackground(backbuffer, dest_x, dest_y, width, height);
387 redraw_mask |= REDRAW_FIELD;
392 DrawBackground(REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE);
394 if (setup.soft_scrolling && game_status == GAME_MODE_PLAYING)
396 ClearRectangle(fieldbuffer, 0, 0, FXSIZE, FYSIZE);
397 SetDrawtoField(DRAW_BUFFERED);
400 SetDrawtoField(DRAW_BACKBUFFER);
402 if (setup.direct_draw && game_status == GAME_MODE_PLAYING)
404 ClearRectangle(window, REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE);
405 SetDrawtoField(DRAW_DIRECT);
409 void MarkTileDirty(int x, int y)
411 int xx = redraw_x1 + x;
412 int yy = redraw_y1 + y;
417 redraw[xx][yy] = TRUE;
418 redraw_mask |= REDRAW_TILES;
421 void SetBorderElement()
425 BorderElement = EL_EMPTY;
427 for (y = 0; y < lev_fieldy && BorderElement == EL_EMPTY; y++)
429 for (x = 0; x < lev_fieldx; x++)
431 if (!IS_INDESTRUCTIBLE(Feld[x][y]))
432 BorderElement = EL_STEELWALL;
434 if (y != 0 && y != lev_fieldy - 1 && x != lev_fieldx - 1)
440 void SetRandomAnimationValue(int x, int y)
442 gfx.anim_random_frame = GfxRandom[x][y];
445 inline int getGraphicAnimationFrame(int graphic, int sync_frame)
447 /* animation synchronized with global frame counter, not move position */
448 if (graphic_info[graphic].anim_global_sync || sync_frame < 0)
449 sync_frame = FrameCounter;
451 return getAnimationFrame(graphic_info[graphic].anim_frames,
452 graphic_info[graphic].anim_delay,
453 graphic_info[graphic].anim_mode,
454 graphic_info[graphic].anim_start_frame,
458 inline void DrawGraphicAnimationExt(DrawBuffer *dst_bitmap, int x, int y,
459 int graphic, int sync_frame, int mask_mode)
461 int frame = getGraphicAnimationFrame(graphic, sync_frame);
463 if (mask_mode == USE_MASKING)
464 DrawGraphicThruMaskExt(dst_bitmap, x, y, graphic, frame);
466 DrawGraphicExt(dst_bitmap, x, y, graphic, frame);
469 inline void DrawGraphicAnimation(int x, int y, int graphic)
471 int lx = LEVELX(x), ly = LEVELY(y);
473 if (!IN_SCR_FIELD(x, y))
476 DrawGraphicAnimationExt(drawto_field, FX + x * TILEX, FY + y * TILEY,
477 graphic, GfxFrame[lx][ly], NO_MASKING);
481 void DrawLevelGraphicAnimation(int x, int y, int graphic)
483 DrawGraphicAnimation(SCREENX(x), SCREENY(y), graphic);
486 void DrawLevelElementAnimation(int x, int y, int element)
489 int graphic = el_act_dir2img(element, GfxAction[x][y], GfxDir[x][y]);
491 DrawGraphicAnimation(SCREENX(x), SCREENY(y), graphic);
493 DrawGraphicAnimation(SCREENX(x), SCREENY(y), el2img(element));
497 inline void DrawLevelGraphicAnimationIfNeeded(int x, int y, int graphic)
499 int sx = SCREENX(x), sy = SCREENY(y);
501 if (!IN_LEV_FIELD(x, y) || !IN_SCR_FIELD(sx, sy))
504 if (!IS_NEW_FRAME(GfxFrame[x][y], graphic))
507 DrawGraphicAnimation(sx, sy, graphic);
509 if (GFX_CRUMBLED(Feld[x][y]))
510 DrawLevelFieldCrumbledSand(x, y);
513 void DrawLevelElementAnimationIfNeeded(int x, int y, int element)
515 int sx = SCREENX(x), sy = SCREENY(y);
518 if (!IN_LEV_FIELD(x, y) || !IN_SCR_FIELD(sx, sy))
521 graphic = el_act_dir2img(element, GfxAction[x][y], GfxDir[x][y]);
523 if (!IS_NEW_FRAME(GfxFrame[x][y], graphic))
526 DrawGraphicAnimation(sx, sy, graphic);
528 if (GFX_CRUMBLED(element))
529 DrawLevelFieldCrumbledSand(x, y);
532 static int getPlayerAction(struct PlayerInfo *player, int move_dir)
534 int action = (player->is_pushing ? ACTION_PUSHING :
535 player->is_digging ? ACTION_DIGGING :
536 player->is_collecting ? ACTION_COLLECTING :
537 player->is_moving ? ACTION_MOVING :
538 player->is_snapping ? ACTION_SNAPPING :
539 player->is_sleeping ? ACTION_SLEEPING :
540 player->is_bored ? ACTION_BORING :
541 player->is_waiting ? ACTION_WAITING : ACTION_DEFAULT);
543 if (player->is_sleeping)
545 if (player->num_special_action_sleeping > 0)
547 if (player->anim_delay_counter == 0 && player->post_delay_counter == 0)
549 int last_special_action = player->special_action_sleeping;
550 int num_special_action = player->num_special_action_sleeping;
552 (last_special_action == ACTION_DEFAULT ? ACTION_SLEEPING_1 :
553 last_special_action == ACTION_SLEEPING ? ACTION_SLEEPING :
554 last_special_action < ACTION_SLEEPING_1 + num_special_action - 1 ?
555 last_special_action + 1 : ACTION_SLEEPING);
556 int special_graphic =
557 el_act_dir2img(player->element_nr, special_action, move_dir);
559 player->anim_delay_counter =
560 graphic_info[special_graphic].anim_delay_fixed +
561 SimpleRND(graphic_info[special_graphic].anim_delay_random);
562 player->post_delay_counter =
563 graphic_info[special_graphic].post_delay_fixed +
564 SimpleRND(graphic_info[special_graphic].post_delay_random);
566 player->special_action_sleeping = special_action;
569 if (player->anim_delay_counter > 0)
571 action = player->special_action_sleeping;
572 player->anim_delay_counter--;
574 else if (player->post_delay_counter > 0)
576 player->post_delay_counter--;
580 else if (player->is_bored)
582 if (player->num_special_action_bored > 0)
584 if (player->anim_delay_counter == 0 && player->post_delay_counter == 0)
587 ACTION_BORING_1 + SimpleRND(player->num_special_action_bored);
588 int special_graphic =
589 el_act_dir2img(player->element_nr, special_action, move_dir);
591 player->anim_delay_counter =
592 graphic_info[special_graphic].anim_delay_fixed +
593 SimpleRND(graphic_info[special_graphic].anim_delay_random);
594 player->post_delay_counter =
595 graphic_info[special_graphic].post_delay_fixed +
596 SimpleRND(graphic_info[special_graphic].post_delay_random);
598 player->special_action_bored = special_action;
601 if (player->anim_delay_counter > 0)
603 action = player->special_action_bored;
604 player->anim_delay_counter--;
606 else if (player->post_delay_counter > 0)
608 player->post_delay_counter--;
616 static int getPlayerGraphic(struct PlayerInfo *player, int move_dir)
618 if (player->use_murphy_graphic)
620 /* this works only because currently only one player can be "murphy" ... */
621 static int last_horizontal_dir = MV_LEFT;
622 int graphic = el_act_dir2img(EL_SP_MURPHY, player->GfxAction, move_dir);
624 if (move_dir == MV_LEFT || move_dir == MV_RIGHT)
625 last_horizontal_dir = move_dir;
627 if (graphic == IMG_SP_MURPHY) /* undefined => use special graphic */
629 int direction = (player->is_snapping ? move_dir : last_horizontal_dir);
631 graphic = el_act_dir2img(EL_SP_MURPHY, player->GfxAction, direction);
637 return el_act_dir2img(player->element_nr, player->GfxAction, move_dir);
640 static boolean equalGraphics(int graphic1, int graphic2)
642 struct GraphicInfo *g1 = &graphic_info[graphic1];
643 struct GraphicInfo *g2 = &graphic_info[graphic2];
645 return (g1->bitmap == g2->bitmap &&
646 g1->src_x == g2->src_x &&
647 g1->src_y == g2->src_y &&
648 g1->anim_frames == g2->anim_frames &&
649 g1->anim_delay == g2->anim_delay &&
650 g1->anim_mode == g2->anim_mode);
653 void DrawAllPlayers()
657 for (i = 0; i < MAX_PLAYERS; i++)
658 if (stored_player[i].active)
659 DrawPlayer(&stored_player[i]);
662 void DrawPlayerField(int x, int y)
664 if (!IS_PLAYER(x, y))
667 DrawPlayer(PLAYERINFO(x, y));
670 void DrawPlayer(struct PlayerInfo *player)
674 int move_dir = player->MovDir;
676 int last_jx = player->last_jx;
677 int last_jy = player->last_jy;
678 int next_jx = jx + (jx - last_jx);
679 int next_jy = jy + (jy - last_jy);
680 boolean player_is_moving = (last_jx != jx || last_jy != jy ? TRUE : FALSE);
682 int dx = (move_dir == MV_LEFT ? -1 : move_dir == MV_RIGHT ? +1 : 0);
683 int dy = (move_dir == MV_UP ? -1 : move_dir == MV_DOWN ? +1 : 0);
684 int last_jx = (player->is_moving ? jx - dx : jx);
685 int last_jy = (player->is_moving ? jy - dy : jy);
686 int next_jx = jx + dx;
687 int next_jy = jy + dy;
688 boolean player_is_moving = (player->MovPos ? TRUE : FALSE);
690 int sx = SCREENX(jx), sy = SCREENY(jy);
691 int sxx = 0, syy = 0;
692 int element = Feld[jx][jy], last_element = Feld[last_jx][last_jy];
694 int action = ACTION_DEFAULT;
695 int last_player_graphic = getPlayerGraphic(player, move_dir);
696 int last_player_frame = player->Frame;
699 if (!player->active || !IN_SCR_FIELD(SCREENX(last_jx), SCREENY(last_jy)))
703 if (!IN_LEV_FIELD(jx, jy))
705 printf("DrawPlayerField(): x = %d, y = %d\n",jx,jy);
706 printf("DrawPlayerField(): sx = %d, sy = %d\n",sx,sy);
707 printf("DrawPlayerField(): This should never happen!\n");
712 if (element == EL_EXPLOSION)
717 action = getPlayerAction(player, move_dir);
721 action = (player->is_pushing ? ACTION_PUSHING :
722 player->is_digging ? ACTION_DIGGING :
723 player->is_collecting ? ACTION_COLLECTING :
724 player->is_moving ? ACTION_MOVING :
725 player->is_snapping ? ACTION_SNAPPING :
726 player->is_sleeping ? ACTION_SLEEPING :
727 player->is_bored ? ACTION_BORING :
728 player->is_waiting ? ACTION_WAITING : ACTION_DEFAULT);
730 if (player->is_bored && player->num_special_action_bored > 0)
732 if (player->anim_delay_counter == 0 && player->post_delay_counter == 0)
736 action = ACTION_BORING_1 + SimpleRND(player->num_special_action_bored);
737 special_graphic = el_act_dir2img(EL_SP_MURPHY, action, move_dir);
739 player->anim_delay_counter =
740 graphic_info[special_graphic].anim_delay_fixed +
741 SimpleRND(graphic_info[special_graphic].anim_delay_random);
742 player->post_delay_counter =
743 graphic_info[special_graphic].post_delay_fixed +
744 SimpleRND(graphic_info[special_graphic].post_delay_random);
745 player->special_action_bored = action;
748 if (player->anim_delay_counter > 0)
750 action = player->special_action_bored;
751 player->anim_delay_counter--;
754 if (player->post_delay_counter > 0)
756 player->post_delay_counter--;
762 printf("::: '%s'\n", element_action_info[action].suffix);
765 InitPlayerGfxAnimation(player, action, move_dir);
767 /* ----------------------------------------------------------------------- */
768 /* draw things in the field the player is leaving, if needed */
769 /* ----------------------------------------------------------------------- */
772 if (player->is_moving)
774 if (player_is_moving)
777 if (Back[last_jx][last_jy] && IS_DRAWABLE(last_element))
779 DrawLevelElement(last_jx, last_jy, Back[last_jx][last_jy]);
781 if (last_element == EL_DYNAMITE_ACTIVE ||
782 last_element == EL_SP_DISK_RED_ACTIVE)
783 DrawDynamite(last_jx, last_jy);
785 DrawLevelFieldThruMask(last_jx, last_jy);
787 else if (last_element == EL_DYNAMITE_ACTIVE ||
788 last_element == EL_SP_DISK_RED_ACTIVE)
789 DrawDynamite(last_jx, last_jy);
791 DrawLevelField(last_jx, last_jy);
793 if (player->is_pushing && IN_SCR_FIELD(SCREENX(next_jx), SCREENY(next_jy)))
794 DrawLevelElement(next_jx, next_jy, EL_EMPTY);
797 if (!IN_SCR_FIELD(sx, sy))
800 if (setup.direct_draw)
801 SetDrawtoField(DRAW_BUFFERED);
803 /* ----------------------------------------------------------------------- */
804 /* draw things behind the player, if needed */
805 /* ----------------------------------------------------------------------- */
808 DrawLevelElement(jx, jy, Back[jx][jy]);
809 else if (IS_ACTIVE_BOMB(element))
810 DrawLevelElement(jx, jy, EL_EMPTY);
813 if (player_is_moving && GfxElement[jx][jy] != EL_UNDEFINED)
815 if (GFX_CRUMBLED(GfxElement[jx][jy]))
816 DrawLevelFieldCrumbledSandDigging(jx, jy, move_dir, player->StepFrame);
819 int old_element = GfxElement[jx][jy];
820 int old_graphic = el_act_dir2img(old_element, action, move_dir);
821 int frame = getGraphicAnimationFrame(old_graphic, player->StepFrame);
823 DrawGraphic(sx, sy, old_graphic, frame);
828 GfxElement[jx][jy] = EL_UNDEFINED;
830 DrawLevelField(jx, jy);
834 /* ----------------------------------------------------------------------- */
835 /* draw player himself */
836 /* ----------------------------------------------------------------------- */
840 graphic = getPlayerGraphic(player, move_dir);
842 /* in the case of changed player action or direction, prevent the current
843 animation frame from being restarted for identical animations */
844 if (player->Frame == 0 && equalGraphics(graphic, last_player_graphic))
845 player->Frame = last_player_frame;
849 if (player->use_murphy_graphic)
851 static int last_horizontal_dir = MV_LEFT;
853 if (move_dir == MV_LEFT || move_dir == MV_RIGHT)
854 last_horizontal_dir = move_dir;
856 graphic = el_act_dir2img(EL_SP_MURPHY, player->GfxAction, move_dir);
858 if (graphic == IMG_SP_MURPHY) /* undefined => use special graphic */
860 int direction = (player->is_snapping ? move_dir : last_horizontal_dir);
862 graphic = el_act_dir2img(EL_SP_MURPHY, player->GfxAction, direction);
866 graphic = el_act_dir2img(player->element_nr, player->GfxAction, move_dir);
870 frame = getGraphicAnimationFrame(graphic, player->Frame);
874 if (move_dir == MV_LEFT || move_dir == MV_RIGHT)
875 sxx = player->GfxPos;
877 syy = player->GfxPos;
880 if (!setup.soft_scrolling && ScreenMovPos)
883 DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, frame, NO_CUTTING);
885 if (SHIELD_ON(player))
887 int graphic = (player->shield_deadly_time_left ? IMG_SHIELD_DEADLY_ACTIVE :
888 IMG_SHIELD_NORMAL_ACTIVE);
889 int frame = getGraphicAnimationFrame(graphic, -1);
891 DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, frame, NO_CUTTING);
894 /* ----------------------------------------------------------------------- */
895 /* draw things the player is pushing, if needed */
896 /* ----------------------------------------------------------------------- */
899 printf("::: %d, %d [%d, %d] [%d]\n",
900 player->is_pushing, player_is_moving, player->GfxAction,
901 player->is_moving, player_is_moving);
905 if (player->is_pushing && player->is_moving)
907 if (player->is_pushing && player_is_moving)
910 int px = SCREENX(next_jx), py = SCREENY(next_jy);
912 if (Back[next_jx][next_jy])
913 DrawLevelElement(next_jx, next_jy, Back[next_jx][next_jy]);
915 if ((sxx || syy) && element == EL_SOKOBAN_OBJECT)
916 DrawGraphicShiftedThruMask(px, py, sxx, syy, IMG_SOKOBAN_OBJECT, 0,
920 int element = MovingOrBlocked2Element(next_jx, next_jy);
921 int graphic = el_act_dir2img(element, ACTION_PUSHING, move_dir);
923 int frame = getGraphicAnimationFrame(graphic, player->StepFrame);
925 int frame = getGraphicAnimationFrame(graphic, player->Frame);
928 DrawGraphicShifted(px, py, sxx, syy, graphic, frame,
929 NO_CUTTING, NO_MASKING);
933 /* ----------------------------------------------------------------------- */
934 /* draw things in front of player (active dynamite or dynabombs) */
935 /* ----------------------------------------------------------------------- */
937 if (IS_ACTIVE_BOMB(element))
939 graphic = el2img(element);
940 frame = getGraphicAnimationFrame(graphic, GfxFrame[jx][jy]);
942 if (game.emulation == EMU_SUPAPLEX)
943 DrawGraphic(sx, sy, IMG_SP_DISK_RED, frame);
945 DrawGraphicThruMask(sx, sy, graphic, frame);
948 if (player_is_moving && last_element == EL_EXPLOSION)
950 int graphic = el_act2img(GfxElement[last_jx][last_jy], ACTION_EXPLODING);
951 int delay = (game.emulation == EMU_SUPAPLEX ? 3 : 2);
952 int phase = ExplodePhase[last_jx][last_jy] - 1;
953 int frame = getGraphicAnimationFrame(graphic, phase - delay);
956 DrawGraphicThruMask(SCREENX(last_jx), SCREENY(last_jy), graphic, frame);
959 /* ----------------------------------------------------------------------- */
960 /* draw elements the player is just walking/passing through/under */
961 /* ----------------------------------------------------------------------- */
963 /* handle the field the player is leaving ... */
964 if (player_is_moving && IS_ACCESSIBLE_INSIDE(last_element))
965 DrawLevelField(last_jx, last_jy);
966 else if (player_is_moving && IS_ACCESSIBLE_UNDER(last_element))
967 DrawLevelFieldThruMask(last_jx, last_jy);
969 /* ... and the field the player is entering */
970 if (IS_ACCESSIBLE_INSIDE(element))
971 DrawLevelField(jx, jy);
972 else if (IS_ACCESSIBLE_UNDER(element))
973 DrawLevelFieldThruMask(jx, jy);
975 if (setup.direct_draw)
977 int dest_x = SX + SCREENX(MIN(jx, last_jx)) * TILEX;
978 int dest_y = SY + SCREENY(MIN(jy, last_jy)) * TILEY;
979 int x_size = TILEX * (1 + ABS(jx - last_jx));
980 int y_size = TILEY * (1 + ABS(jy - last_jy));
982 BlitBitmap(drawto_field, window,
983 dest_x, dest_y, x_size, y_size, dest_x, dest_y);
984 SetDrawtoField(DRAW_DIRECT);
987 MarkTileDirty(sx,sy);
990 void getGraphicSource(int graphic, int frame, Bitmap **bitmap, int *x, int *y)
992 struct GraphicInfo *g = &graphic_info[graphic];
996 if (g->offset_y == 0) /* frames are ordered horizontally */
998 int max_width = g->anim_frames_per_line * g->width;
1000 *x = (g->src_x + frame * g->offset_x) % max_width;
1001 *y = g->src_y + (g->src_x + frame * g->offset_x) / max_width * g->height;
1003 else if (g->offset_x == 0) /* frames are ordered vertically */
1005 int max_height = g->anim_frames_per_line * g->height;
1007 *x = g->src_x + (g->src_y + frame * g->offset_y) / max_height * g->width;
1008 *y = (g->src_y + frame * g->offset_y) % max_height;
1010 else /* frames are ordered diagonally */
1012 *x = g->src_x + frame * g->offset_x;
1013 *y = g->src_y + frame * g->offset_y;
1017 void DrawGraphic(int x, int y, int graphic, int frame)
1020 if (!IN_SCR_FIELD(x, y))
1022 printf("DrawGraphic(): x = %d, y = %d, graphic = %d\n", x, y, graphic);
1023 printf("DrawGraphic(): This should never happen!\n");
1028 DrawGraphicExt(drawto_field, FX + x * TILEX, FY + y * TILEY, graphic, frame);
1029 MarkTileDirty(x, y);
1032 void DrawGraphicExt(DrawBuffer *dst_bitmap, int x, int y, int graphic,
1038 getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
1039 BlitBitmap(src_bitmap, dst_bitmap, src_x, src_y, TILEX, TILEY, x, y);
1042 void DrawGraphicThruMask(int x, int y, int graphic, int frame)
1045 if (!IN_SCR_FIELD(x, y))
1047 printf("DrawGraphicThruMask(): x = %d,y = %d, graphic = %d\n",x,y,graphic);
1048 printf("DrawGraphicThruMask(): This should never happen!\n");
1053 DrawGraphicThruMaskExt(drawto_field, FX + x * TILEX, FY + y *TILEY, graphic,
1055 MarkTileDirty(x, y);
1058 void DrawGraphicThruMaskExt(DrawBuffer *d, int dest_x, int dest_y, int graphic,
1066 getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
1067 drawing_gc = src_bitmap->stored_clip_gc;
1069 GC drawing_gc = src_bitmap->stored_clip_gc;
1070 Bitmap *src_bitmap = graphic_info[graphic].bitmap;
1071 int src_x = graphic_info[graphic].src_x;
1072 int src_y = graphic_info[graphic].src_y;
1073 int offset_x = graphic_info[graphic].offset_x;
1074 int offset_y = graphic_info[graphic].offset_y;
1076 src_x += frame * offset_x;
1077 src_y += frame * offset_y;
1081 SetClipOrigin(src_bitmap, drawing_gc, dest_x - src_x, dest_y - src_y);
1082 BlitBitmapMasked(src_bitmap, d, src_x, src_y, TILEX, TILEY, dest_x, dest_y);
1085 void DrawMiniGraphic(int x, int y, int graphic)
1087 DrawMiniGraphicExt(drawto, SX + x * MINI_TILEX,SY + y * MINI_TILEY, graphic);
1088 MarkTileDirty(x / 2, y / 2);
1091 void getMiniGraphicSource(int graphic, Bitmap **bitmap, int *x, int *y)
1093 struct GraphicInfo *g = &graphic_info[graphic];
1094 int mini_startx = 0;
1095 int mini_starty = g->bitmap->height * 2 / 3;
1097 *bitmap = g->bitmap;
1098 *x = mini_startx + g->src_x / 2;
1099 *y = mini_starty + g->src_y / 2;
1102 void DrawMiniGraphicExt(DrawBuffer *d, int x, int y, int graphic)
1107 getMiniGraphicSource(graphic, &src_bitmap, &src_x, &src_y);
1108 BlitBitmap(src_bitmap, d, src_x, src_y, MINI_TILEX, MINI_TILEY, x, y);
1111 void DrawGraphicShifted(int x,int y, int dx,int dy, int graphic, int frame,
1112 int cut_mode, int mask_mode)
1117 int width = TILEX, height = TILEY;
1123 DrawGraphic(x, y, graphic, frame);
1127 if (dx || dy) /* shifted graphic */
1129 if (x < BX1) /* object enters playfield from the left */
1136 else if (x > BX2) /* object enters playfield from the right */
1142 else if (x==BX1 && dx < 0) /* object leaves playfield to the left */
1148 else if (x==BX2 && dx > 0) /* object leaves playfield to the right */
1150 else if (dx) /* general horizontal movement */
1151 MarkTileDirty(x + SIGN(dx), y);
1153 if (y < BY1) /* object enters playfield from the top */
1155 if (cut_mode==CUT_BELOW) /* object completely above top border */
1163 else if (y > BY2) /* object enters playfield from the bottom */
1169 else if (y==BY1 && dy < 0) /* object leaves playfield to the top */
1175 else if (dy > 0 && cut_mode == CUT_ABOVE)
1177 if (y == BY2) /* object completely above bottom border */
1183 MarkTileDirty(x, y + 1);
1184 } /* object leaves playfield to the bottom */
1185 else if (dy > 0 && (y == BY2 || cut_mode == CUT_BELOW))
1187 else if (dy) /* general vertical movement */
1188 MarkTileDirty(x, y + SIGN(dy));
1192 getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
1194 src_bitmap = graphic_info[graphic].bitmap;
1195 src_x = graphic_info[graphic].src_x;
1196 src_y = graphic_info[graphic].src_y;
1197 offset_x = graphic_info[graphic].offset_x;
1198 offset_y = graphic_info[graphic].offset_y;
1200 src_x += frame * offset_x;
1201 src_y += frame * offset_y;
1204 drawing_gc = src_bitmap->stored_clip_gc;
1209 dest_x = FX + x * TILEX + dx;
1210 dest_y = FY + y * TILEY + dy;
1213 if (!IN_SCR_FIELD(x,y))
1215 printf("DrawGraphicShifted(): x = %d, y = %d, graphic = %d\n",x,y,graphic);
1216 printf("DrawGraphicShifted(): This should never happen!\n");
1221 if (mask_mode == USE_MASKING)
1223 SetClipOrigin(src_bitmap, drawing_gc, dest_x - src_x, dest_y - src_y);
1224 BlitBitmapMasked(src_bitmap, drawto_field, src_x, src_y, width, height,
1228 BlitBitmap(src_bitmap, drawto_field, src_x, src_y, width, height,
1234 void DrawGraphicShiftedThruMask(int x, int y, int dx, int dy, int graphic,
1235 int frame, int cut_mode)
1237 DrawGraphicShifted(x,y, dx,dy, graphic, frame, cut_mode, USE_MASKING);
1240 void DrawScreenElementExt(int x, int y, int dx, int dy, int element,
1241 int cut_mode, int mask_mode)
1243 int lx = LEVELX(x), ly = LEVELY(y);
1247 if (IN_LEV_FIELD(lx, ly))
1249 SetRandomAnimationValue(lx, ly);
1251 graphic = el_act_dir2img(element, GfxAction[lx][ly], GfxDir[lx][ly]);
1252 frame = getGraphicAnimationFrame(graphic, GfxFrame[lx][ly]);
1254 else /* border element */
1256 graphic = el2img(element);
1257 frame = getGraphicAnimationFrame(graphic, -1);
1260 if (element == EL_EXPANDABLE_WALL)
1262 boolean left_stopped = FALSE, right_stopped = FALSE;
1264 if (!IN_LEV_FIELD(lx - 1, ly) || IS_WALL(Feld[lx - 1][ly]))
1265 left_stopped = TRUE;
1266 if (!IN_LEV_FIELD(lx + 1, ly) || IS_WALL(Feld[lx + 1][ly]))
1267 right_stopped = TRUE;
1269 if (left_stopped && right_stopped)
1271 else if (left_stopped)
1273 graphic = IMG_EXPANDABLE_WALL_GROWING_RIGHT;
1274 frame = graphic_info[graphic].anim_frames - 1;
1276 else if (right_stopped)
1278 graphic = IMG_EXPANDABLE_WALL_GROWING_LEFT;
1279 frame = graphic_info[graphic].anim_frames - 1;
1284 DrawGraphicShifted(x, y, dx, dy, graphic, frame, cut_mode, mask_mode);
1285 else if (mask_mode == USE_MASKING)
1286 DrawGraphicThruMask(x, y, graphic, frame);
1288 DrawGraphic(x, y, graphic, frame);
1291 void DrawLevelElementExt(int x, int y, int dx, int dy, int element,
1292 int cut_mode, int mask_mode)
1294 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1295 DrawScreenElementExt(SCREENX(x), SCREENY(y), dx, dy, element,
1296 cut_mode, mask_mode);
1299 void DrawScreenElementShifted(int x, int y, int dx, int dy, int element,
1302 DrawScreenElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
1305 void DrawLevelElementShifted(int x, int y, int dx, int dy, int element,
1308 DrawLevelElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
1311 void DrawLevelElementThruMask(int x, int y, int element)
1313 DrawLevelElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
1316 void DrawLevelFieldThruMask(int x, int y)
1318 DrawLevelElementExt(x, y, 0, 0, Feld[x][y], NO_CUTTING, USE_MASKING);
1321 static void DrawLevelFieldCrumbledSandExt(int x, int y, int graphic, int frame)
1325 int sx = SCREENX(x), sy = SCREENY(y);
1327 int width, height, cx, cy, i;
1329 int crumbled_border_size = graphic_info[graphic].border_size;
1331 int snip = TILEX / 8; /* number of border pixels from "crumbled graphic" */
1333 static int xy[4][2] =
1342 if (x == 0 && y == 7)
1343 printf("::: %d, %d [%d]\n", GfxElement[x][y], Feld[x][y],
1344 crumbled_border_size);
1347 if (!IN_LEV_FIELD(x, y))
1350 element = (GfxElement[x][y] != EL_UNDEFINED && Feld[x][y] != EL_EXPLOSION ?
1351 GfxElement[x][y] : Feld[x][y]);
1353 /* crumble field itself */
1354 if (GFX_CRUMBLED(element) && !IS_MOVING(x, y))
1356 if (!IN_SCR_FIELD(sx, sy))
1359 getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
1361 for (i = 0; i < 4; i++)
1363 int xx = x + xy[i][0];
1364 int yy = y + xy[i][1];
1366 element = (IN_LEV_FIELD(xx, yy) ? Feld[xx][yy] : BorderElement);
1368 /* check if neighbour field is of same type */
1369 if (GFX_CRUMBLED(element) && !IS_MOVING(xx, yy))
1373 if (Feld[x][y] == EL_CUSTOM_START + 123)
1374 printf("::: crumble [%d] THE CHAOS ENGINE (%d, %d): %d, %d\n",
1375 i, Feld[x][y], element,
1376 GFX_CRUMBLED(element), IS_MOVING(x, y));
1379 if (i == 1 || i == 2)
1381 width = crumbled_border_size;
1383 cx = (i == 2 ? TILEX - crumbled_border_size : 0);
1389 height = crumbled_border_size;
1391 cy = (i == 3 ? TILEY - crumbled_border_size : 0);
1394 BlitBitmap(src_bitmap, drawto_field, src_x + cx, src_y + cy,
1395 width, height, FX + sx * TILEX + cx, FY + sy * TILEY + cy);
1398 MarkTileDirty(sx, sy);
1400 else /* crumble neighbour fields */
1403 getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
1406 for (i = 0; i < 4; i++)
1408 int xx = x + xy[i][0];
1409 int yy = y + xy[i][1];
1410 int sxx = sx + xy[i][0];
1411 int syy = sy + xy[i][1];
1413 if (!IN_LEV_FIELD(xx, yy) ||
1414 !IN_SCR_FIELD(sxx, syy) ||
1415 !GFX_CRUMBLED(Feld[xx][yy]) ||
1420 graphic = el_act2crm(Feld[xx][yy], ACTION_DEFAULT);
1421 crumbled_border_size = graphic_info[graphic].border_size;
1423 getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
1426 if (i == 1 || i == 2)
1428 width = crumbled_border_size;
1430 cx = (i == 1 ? TILEX - crumbled_border_size : 0);
1436 height = crumbled_border_size;
1438 cy = (i == 0 ? TILEY - crumbled_border_size : 0);
1441 BlitBitmap(src_bitmap, drawto_field, src_x + cx, src_y + cy,
1442 width, height, FX + sxx * TILEX + cx, FY + syy * TILEY + cy);
1444 MarkTileDirty(sxx, syy);
1449 void DrawLevelFieldCrumbledSand(int x, int y)
1454 if (!IN_LEV_FIELD(x, y))
1457 graphic = el_act2crm(Feld[x][y], ACTION_DEFAULT);
1459 DrawLevelFieldCrumbledSandExt(x, y, graphic, 0);
1461 DrawLevelFieldCrumbledSandExt(x, y, IMG_SAND_CRUMBLED, 0);
1465 void DrawLevelFieldCrumbledSandDigging(int x, int y, int direction,
1469 int graphic1 = el_act_dir2img(GfxElement[x][y], ACTION_DIGGING, direction);
1470 int graphic2 = el_act_dir2crm(GfxElement[x][y], ACTION_DIGGING, direction);
1472 int graphic1 = el_act_dir2img(EL_SAND, ACTION_DIGGING, direction);
1473 int graphic2 = el_act_dir2img(EL_SAND_CRUMBLED, ACTION_DIGGING, direction);
1475 int frame1 = getGraphicAnimationFrame(graphic1, step_frame);
1476 int frame2 = getGraphicAnimationFrame(graphic2, step_frame);
1477 int sx = SCREENX(x), sy = SCREENY(y);
1479 DrawGraphic(sx, sy, graphic1, frame1);
1480 DrawLevelFieldCrumbledSandExt(x, y, graphic2, frame2);
1483 void DrawLevelFieldCrumbledSandNeighbours(int x, int y)
1485 int sx = SCREENX(x), sy = SCREENY(y);
1486 static int xy[4][2] =
1495 for (i = 0; i < 4; i++)
1497 int xx = x + xy[i][0];
1498 int yy = y + xy[i][1];
1499 int sxx = sx + xy[i][0];
1500 int syy = sy + xy[i][1];
1502 if (!IN_LEV_FIELD(xx, yy) ||
1503 !IN_SCR_FIELD(sxx, syy) ||
1504 !GFX_CRUMBLED(Feld[xx][yy]) ||
1508 DrawLevelField(xx, yy);
1512 static int getBorderElement(int x, int y)
1516 { EL_STEELWALL_TOPLEFT, EL_INVISIBLE_STEELWALL_TOPLEFT },
1517 { EL_STEELWALL_TOPRIGHT, EL_INVISIBLE_STEELWALL_TOPRIGHT },
1518 { EL_STEELWALL_BOTTOMLEFT, EL_INVISIBLE_STEELWALL_BOTTOMLEFT },
1519 { EL_STEELWALL_BOTTOMRIGHT, EL_INVISIBLE_STEELWALL_BOTTOMRIGHT },
1520 { EL_STEELWALL_VERTICAL, EL_INVISIBLE_STEELWALL_VERTICAL },
1521 { EL_STEELWALL_HORIZONTAL, EL_INVISIBLE_STEELWALL_HORIZONTAL },
1522 { EL_STEELWALL, EL_INVISIBLE_STEELWALL }
1524 int steel_type = (BorderElement == EL_STEELWALL ? 0 : 1);
1525 int steel_position = (x == -1 && y == -1 ? 0 :
1526 x == lev_fieldx && y == -1 ? 1 :
1527 x == -1 && y == lev_fieldy ? 2 :
1528 x == lev_fieldx && y == lev_fieldy ? 3 :
1529 x == -1 || x == lev_fieldx ? 4 :
1530 y == -1 || y == lev_fieldy ? 5 : 6);
1532 return border[steel_position][steel_type];
1535 void DrawScreenElement(int x, int y, int element)
1537 DrawScreenElementExt(x, y, 0, 0, element, NO_CUTTING, NO_MASKING);
1538 DrawLevelFieldCrumbledSand(LEVELX(x), LEVELY(y));
1541 void DrawLevelElement(int x, int y, int element)
1543 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1544 DrawScreenElement(SCREENX(x), SCREENY(y), element);
1547 void DrawScreenField(int x, int y)
1549 int lx = LEVELX(x), ly = LEVELY(y);
1550 int element, content;
1552 if (!IN_LEV_FIELD(lx, ly))
1554 if (lx < -1 || lx > lev_fieldx || ly < -1 || ly > lev_fieldy)
1557 element = getBorderElement(lx, ly);
1559 DrawScreenElement(x, y, element);
1563 element = Feld[lx][ly];
1564 content = Store[lx][ly];
1566 if (IS_MOVING(lx, ly))
1568 int horiz_move = (MovDir[lx][ly] == MV_LEFT || MovDir[lx][ly] == MV_RIGHT);
1569 boolean cut_mode = NO_CUTTING;
1571 if (element == EL_QUICKSAND_EMPTYING ||
1572 element == EL_MAGIC_WALL_EMPTYING ||
1573 element == EL_BD_MAGIC_WALL_EMPTYING ||
1574 element == EL_AMOEBA_DROPPING)
1575 cut_mode = CUT_ABOVE;
1576 else if (element == EL_QUICKSAND_FILLING ||
1577 element == EL_MAGIC_WALL_FILLING ||
1578 element == EL_BD_MAGIC_WALL_FILLING)
1579 cut_mode = CUT_BELOW;
1581 if (cut_mode == CUT_ABOVE)
1582 DrawScreenElementShifted(x, y, 0, 0, element, NO_CUTTING);
1584 DrawScreenElement(x, y, EL_EMPTY);
1587 DrawScreenElementShifted(x, y, MovPos[lx][ly], 0, element, NO_CUTTING);
1588 else if (cut_mode == NO_CUTTING)
1589 DrawScreenElementShifted(x, y, 0, MovPos[lx][ly], element, cut_mode);
1591 DrawScreenElementShifted(x, y, 0, MovPos[lx][ly], content, cut_mode);
1593 if (content == EL_ACID)
1594 DrawLevelElementThruMask(lx, ly + 1, EL_ACID);
1596 else if (IS_BLOCKED(lx, ly))
1601 boolean cut_mode = NO_CUTTING;
1602 int element_old, content_old;
1604 Blocked2Moving(lx, ly, &oldx, &oldy);
1607 horiz_move = (MovDir[oldx][oldy] == MV_LEFT ||
1608 MovDir[oldx][oldy] == MV_RIGHT);
1610 element_old = Feld[oldx][oldy];
1611 content_old = Store[oldx][oldy];
1613 if (element_old == EL_QUICKSAND_EMPTYING ||
1614 element_old == EL_MAGIC_WALL_EMPTYING ||
1615 element_old == EL_BD_MAGIC_WALL_EMPTYING ||
1616 element_old == EL_AMOEBA_DROPPING)
1617 cut_mode = CUT_ABOVE;
1619 DrawScreenElement(x, y, EL_EMPTY);
1622 DrawScreenElementShifted(sx, sy, MovPos[oldx][oldy], 0, element_old,
1624 else if (cut_mode == NO_CUTTING)
1625 DrawScreenElementShifted(sx, sy, 0, MovPos[oldx][oldy], element_old,
1628 DrawScreenElementShifted(sx, sy, 0, MovPos[oldx][oldy], content_old,
1631 else if (IS_DRAWABLE(element))
1632 DrawScreenElement(x, y, element);
1634 DrawScreenElement(x, y, EL_EMPTY);
1637 void DrawLevelField(int x, int y)
1639 if (IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1640 DrawScreenField(SCREENX(x), SCREENY(y));
1641 else if (IS_MOVING(x, y))
1645 Moving2Blocked(x, y, &newx, &newy);
1646 if (IN_SCR_FIELD(SCREENX(newx), SCREENY(newy)))
1647 DrawScreenField(SCREENX(newx), SCREENY(newy));
1649 else if (IS_BLOCKED(x, y))
1653 Blocked2Moving(x, y, &oldx, &oldy);
1654 if (IN_SCR_FIELD(SCREENX(oldx), SCREENY(oldy)))
1655 DrawScreenField(SCREENX(oldx), SCREENY(oldy));
1659 void DrawMiniElement(int x, int y, int element)
1663 graphic = el2edimg(element);
1664 DrawMiniGraphic(x, y, graphic);
1667 void DrawMiniElementOrWall(int sx, int sy, int scroll_x, int scroll_y)
1669 int x = sx + scroll_x, y = sy + scroll_y;
1671 if (x < -1 || x > lev_fieldx || y < -1 || y > lev_fieldy)
1672 DrawMiniElement(sx, sy, EL_EMPTY);
1673 else if (x > -1 && x < lev_fieldx && y > -1 && y < lev_fieldy)
1674 DrawMiniElement(sx, sy, Feld[x][y]);
1676 DrawMiniGraphic(sx, sy, el2edimg(getBorderElement(x, y)));
1679 void DrawEnvelopeBackground(int envelope_nr, int startx, int starty,
1680 int x, int y, int xsize, int ysize, int font_nr)
1682 int font_width = getFontWidth(font_nr);
1683 int font_height = getFontHeight(font_nr);
1684 int graphic = IMG_BACKGROUND_ENVELOPE_1 + envelope_nr;
1687 int dst_x = SX + startx + x * font_width;
1688 int dst_y = SY + starty + y * font_height;
1689 int width = graphic_info[graphic].width;
1690 int height = graphic_info[graphic].height;
1691 int inner_width = MAX(width - 2 * font_width, font_width);
1692 int inner_height = MAX(height - 2 * font_height, font_height);
1693 int inner_sx = (width >= 3 * font_width ? font_width : 0);
1694 int inner_sy = (height >= 3 * font_height ? font_height : 0);
1695 boolean draw_masked = graphic_info[graphic].draw_masked;
1697 getGraphicSource(graphic, 0, &src_bitmap, &src_x, &src_y);
1699 if (src_bitmap == NULL || width < font_width || height < font_height)
1701 ClearRectangle(drawto, dst_x, dst_y, font_width, font_height);
1705 src_x += (x == 0 ? 0 : x == xsize - 1 ? width - font_width :
1706 inner_sx + (x - 1) * font_width % inner_width);
1707 src_y += (y == 0 ? 0 : y == ysize - 1 ? height - font_height :
1708 inner_sy + (y - 1) * font_height % inner_height);
1712 SetClipOrigin(src_bitmap, src_bitmap->stored_clip_gc,
1713 dst_x - src_x, dst_y - src_y);
1714 BlitBitmapMasked(src_bitmap, drawto, src_x, src_y, font_width, font_height,
1718 BlitBitmap(src_bitmap, drawto, src_x, src_y, font_width, font_height,
1722 void AnimateEnvelope(int envelope_nr, int anim_mode, int action)
1724 int graphic = IMG_BACKGROUND_ENVELOPE_1 + envelope_nr;
1725 boolean draw_masked = graphic_info[graphic].draw_masked;
1726 int mask_mode = (draw_masked ? BLIT_MASKED : BLIT_ON_BACKGROUND);
1727 boolean ffwd_delay = (tape.playing && tape.fast_forward);
1728 unsigned long anim_delay = 0;
1729 int anim_delay_value = (ffwd_delay ? FfwdFrameDelay : GameFrameDelay);
1730 int font_nr = FONT_ENVELOPE_1 + envelope_nr;
1731 int font_width = getFontWidth(font_nr);
1732 int font_height = getFontHeight(font_nr);
1733 int max_xsize = level.envelope_xsize[envelope_nr];
1734 int max_ysize = level.envelope_ysize[envelope_nr];
1735 int xstart = (anim_mode & ANIM_VERTICAL ? max_xsize : 0);
1736 int ystart = (anim_mode & ANIM_HORIZONTAL ? max_ysize : 0);
1737 int xend = max_xsize;
1738 int yend = (anim_mode != ANIM_DEFAULT ? max_ysize : 0);
1739 int xstep = (xstart < xend ? 1 : 0);
1740 int ystep = (ystart < yend || xstep == 0 ? 1 : 0);
1743 for (x = xstart, y = ystart; x <= xend && y <= yend; x += xstep, y += ystep)
1745 int xsize = (action == ACTION_CLOSING ? xend - (x - xstart) : x) + 2;
1746 int ysize = (action == ACTION_CLOSING ? yend - (y - ystart) : y) + 2;
1747 int sx = (SXSIZE - xsize * font_width) / 2;
1748 int sy = (SYSIZE - ysize * font_height) / 2;
1751 SetDrawtoField(DRAW_BUFFERED);
1753 BlitBitmap(fieldbuffer, backbuffer, FX, FY, SXSIZE, SYSIZE, SX, SY);
1755 SetDrawtoField(DRAW_BACKBUFFER);
1757 for (yy = 0; yy < ysize; yy++) for (xx = 0; xx < xsize; xx++)
1758 DrawEnvelopeBackground(envelope_nr, sx,sy, xx,yy, xsize, ysize, font_nr);
1760 DrawTextToTextArea(SX + sx + font_width, SY + sy + font_height,
1761 level.envelope_text[envelope_nr], font_nr, max_xsize,
1762 xsize - 2, ysize - 2, mask_mode);
1764 redraw_mask |= REDRAW_FIELD | REDRAW_FROM_BACKBUFFER;
1767 WaitUntilDelayReached(&anim_delay, anim_delay_value / 2);
1771 void ShowEnvelope(int envelope_nr)
1773 int element = EL_ENVELOPE_1 + envelope_nr;
1774 int graphic = IMG_BACKGROUND_ENVELOPE_1 + envelope_nr;
1775 int sound_opening = element_info[element].sound[ACTION_OPENING];
1776 int sound_closing = element_info[element].sound[ACTION_CLOSING];
1777 boolean ffwd_delay = (tape.playing && tape.fast_forward);
1778 int wait_delay_value = (ffwd_delay ? 500 : 1000);
1779 int anim_mode = graphic_info[graphic].anim_mode;
1780 int main_anim_mode = (anim_mode == ANIM_NONE ? ANIM_VERTICAL|ANIM_HORIZONTAL:
1781 anim_mode == ANIM_DEFAULT ? ANIM_VERTICAL : anim_mode);
1783 game.envelope_active = TRUE; /* needed for RedrawPlayfield() events */
1785 PlaySoundStereo(sound_opening, SOUND_MIDDLE);
1787 if (anim_mode == ANIM_DEFAULT)
1788 AnimateEnvelope(envelope_nr, ANIM_DEFAULT, ACTION_OPENING);
1790 AnimateEnvelope(envelope_nr, main_anim_mode, ACTION_OPENING);
1793 Delay(wait_delay_value);
1795 WaitForEventToContinue();
1797 PlaySoundStereo(sound_closing, SOUND_MIDDLE);
1799 if (anim_mode != ANIM_NONE)
1800 AnimateEnvelope(envelope_nr, main_anim_mode, ACTION_CLOSING);
1802 if (anim_mode == ANIM_DEFAULT)
1803 AnimateEnvelope(envelope_nr, ANIM_DEFAULT, ACTION_CLOSING);
1805 game.envelope_active = FALSE;
1807 SetDrawtoField(DRAW_BUFFERED);
1809 redraw_mask |= REDRAW_FIELD;
1813 void getMicroGraphicSource(int graphic, Bitmap **bitmap, int *x, int *y)
1815 Bitmap *src_bitmap = graphic_info[graphic].bitmap;
1816 int mini_startx = src_bitmap->width * 3 / 4;
1817 int mini_starty = src_bitmap->height * 2 / 3;
1818 int src_x = mini_startx + graphic_info[graphic].src_x / 8;
1819 int src_y = mini_starty + graphic_info[graphic].src_y / 8;
1821 *bitmap = src_bitmap;
1826 void DrawMicroElement(int xpos, int ypos, int element)
1830 int graphic = el2preimg(element);
1832 getMicroGraphicSource(graphic, &src_bitmap, &src_x, &src_y);
1833 BlitBitmap(src_bitmap, drawto, src_x, src_y, MICRO_TILEX, MICRO_TILEY,
1841 SetDrawBackgroundMask(REDRAW_NONE);
1844 for (x = BX1; x <= BX2; x++)
1845 for (y = BY1; y <= BY2; y++)
1846 DrawScreenField(x, y);
1848 redraw_mask |= REDRAW_FIELD;
1851 void DrawMiniLevel(int size_x, int size_y, int scroll_x, int scroll_y)
1855 for (x = 0; x < size_x; x++)
1856 for (y = 0; y < size_y; y++)
1857 DrawMiniElementOrWall(x, y, scroll_x, scroll_y);
1859 redraw_mask |= REDRAW_FIELD;
1862 static void DrawMicroLevelExt(int xpos, int ypos, int from_x, int from_y)
1866 DrawBackground(xpos, ypos, MICROLEV_XSIZE, MICROLEV_YSIZE);
1868 if (lev_fieldx < STD_LEV_FIELDX)
1869 xpos += (STD_LEV_FIELDX - lev_fieldx) / 2 * MICRO_TILEX;
1870 if (lev_fieldy < STD_LEV_FIELDY)
1871 ypos += (STD_LEV_FIELDY - lev_fieldy) / 2 * MICRO_TILEY;
1873 xpos += MICRO_TILEX;
1874 ypos += MICRO_TILEY;
1876 for (x = -1; x <= STD_LEV_FIELDX; x++)
1878 for (y = -1; y <= STD_LEV_FIELDY; y++)
1880 int lx = from_x + x, ly = from_y + y;
1882 if (lx >= 0 && lx < lev_fieldx && ly >= 0 && ly < lev_fieldy)
1883 DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
1884 level.field[lx][ly]);
1885 else if (lx >= -1 && lx < lev_fieldx+1 && ly >= -1 && ly < lev_fieldy+1
1886 && BorderElement != EL_EMPTY)
1887 DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
1888 getBorderElement(lx, ly));
1892 redraw_mask |= REDRAW_MICROLEVEL;
1895 #define MICROLABEL_EMPTY 0
1896 #define MICROLABEL_LEVEL_NAME 1
1897 #define MICROLABEL_CREATED_BY 2
1898 #define MICROLABEL_LEVEL_AUTHOR 3
1899 #define MICROLABEL_IMPORTED_FROM 4
1900 #define MICROLABEL_LEVEL_IMPORT_INFO 5
1902 static void DrawMicroLevelLabelExt(int mode)
1904 char label_text[MAX_OUTPUT_LINESIZE + 1];
1905 int max_len_label_text;
1906 int font_nr = FONT_TEXT_2;
1908 if (mode == MICROLABEL_CREATED_BY || mode == MICROLABEL_IMPORTED_FROM)
1909 font_nr = FONT_TEXT_3;
1911 max_len_label_text = SXSIZE / getFontWidth(font_nr);
1913 DrawBackground(SX, MICROLABEL_YPOS, SXSIZE, getFontHeight(font_nr));
1915 strncpy(label_text, (mode == MICROLABEL_LEVEL_NAME ? level.name :
1916 mode == MICROLABEL_CREATED_BY ? "created by" :
1917 mode == MICROLABEL_LEVEL_AUTHOR ? level.author :
1918 mode == MICROLABEL_IMPORTED_FROM ? "imported from" :
1919 mode == MICROLABEL_LEVEL_IMPORT_INFO ?
1920 leveldir_current->imported_from : ""),
1921 max_len_label_text);
1922 label_text[max_len_label_text] = '\0';
1924 if (strlen(label_text) > 0)
1926 int lxpos = SX + (SXSIZE - getTextWidth(label_text, font_nr)) / 2;
1927 int lypos = MICROLABEL_YPOS;
1929 DrawText(lxpos, lypos, label_text, font_nr);
1932 redraw_mask |= REDRAW_MICROLEVEL;
1935 void DrawMicroLevel(int xpos, int ypos, boolean restart)
1937 static unsigned long scroll_delay = 0;
1938 static unsigned long label_delay = 0;
1939 static int from_x, from_y, scroll_direction;
1940 static int label_state, label_counter;
1941 int last_game_status = game_status; /* save current game status */
1943 /* force PREVIEW font on preview level */
1944 game_status = GAME_MODE_PSEUDO_PREVIEW;
1948 from_x = from_y = 0;
1949 scroll_direction = MV_RIGHT;
1953 DrawMicroLevelExt(xpos, ypos, from_x, from_y);
1954 DrawMicroLevelLabelExt(label_state);
1956 /* initialize delay counters */
1957 DelayReached(&scroll_delay, 0);
1958 DelayReached(&label_delay, 0);
1960 if (leveldir_current->name)
1962 int text_width = getTextWidth(leveldir_current->name, FONT_TEXT_1);
1963 int lxpos = SX + (SXSIZE - text_width) / 2;
1964 int lypos = SY + 352;
1966 DrawText(lxpos, lypos, leveldir_current->name, FONT_TEXT_1);
1969 game_status = last_game_status; /* restore current game status */
1974 /* scroll micro level, if needed */
1975 if ((lev_fieldx > STD_LEV_FIELDX || lev_fieldy > STD_LEV_FIELDY) &&
1976 DelayReached(&scroll_delay, MICROLEVEL_SCROLL_DELAY))
1978 switch (scroll_direction)
1984 scroll_direction = MV_UP;
1988 if (from_x < lev_fieldx - STD_LEV_FIELDX)
1991 scroll_direction = MV_DOWN;
1998 scroll_direction = MV_RIGHT;
2002 if (from_y < lev_fieldy - STD_LEV_FIELDY)
2005 scroll_direction = MV_LEFT;
2012 DrawMicroLevelExt(xpos, ypos, from_x, from_y);
2015 /* redraw micro level label, if needed */
2016 if (strcmp(level.name, NAMELESS_LEVEL_NAME) != 0 &&
2017 strcmp(level.author, ANONYMOUS_NAME) != 0 &&
2018 strcmp(level.author, leveldir_current->name) != 0 &&
2019 DelayReached(&label_delay, MICROLEVEL_LABEL_DELAY))
2021 int max_label_counter = 23;
2023 if (leveldir_current->imported_from != NULL)
2024 max_label_counter += 14;
2026 label_counter = (label_counter + 1) % max_label_counter;
2027 label_state = (label_counter >= 0 && label_counter <= 7 ?
2028 MICROLABEL_LEVEL_NAME :
2029 label_counter >= 9 && label_counter <= 12 ?
2030 MICROLABEL_CREATED_BY :
2031 label_counter >= 14 && label_counter <= 21 ?
2032 MICROLABEL_LEVEL_AUTHOR :
2033 label_counter >= 23 && label_counter <= 26 ?
2034 MICROLABEL_IMPORTED_FROM :
2035 label_counter >= 28 && label_counter <= 35 ?
2036 MICROLABEL_LEVEL_IMPORT_INFO : MICROLABEL_EMPTY);
2037 DrawMicroLevelLabelExt(label_state);
2040 game_status = last_game_status; /* restore current game status */
2043 void WaitForEventToContinue()
2045 boolean still_wait = TRUE;
2047 /* simulate releasing mouse button over last gadget, if still pressed */
2049 HandleGadgets(-1, -1, 0);
2051 button_status = MB_RELEASED;
2063 case EVENT_BUTTONPRESS:
2064 case EVENT_KEYPRESS:
2068 case EVENT_KEYRELEASE:
2069 ClearPlayerAction();
2073 HandleOtherEvents(&event);
2077 else if (AnyJoystickButton() == JOY_BUTTON_NEW_PRESSED)
2084 /* don't eat all CPU time */
2089 #define MAX_REQUEST_LINES 13
2090 #define MAX_REQUEST_LINE_LEN 7
2092 boolean Request(char *text, unsigned int req_state)
2094 int mx, my, ty, result = -1;
2095 unsigned int old_door_state;
2096 int last_game_status = game_status; /* save current game status */
2099 SetMouseCursor(CURSOR_DEFAULT);
2102 #if defined(PLATFORM_UNIX)
2103 /* pause network game while waiting for request to answer */
2104 if (options.network &&
2105 game_status == GAME_MODE_PLAYING &&
2106 req_state & REQUEST_WAIT_FOR)
2107 SendToServer_PausePlaying();
2110 old_door_state = GetDoorState();
2112 /* simulate releasing mouse button over last gadget, if still pressed */
2114 HandleGadgets(-1, -1, 0);
2118 CloseDoor(DOOR_CLOSE_1);
2120 /* save old door content */
2121 BlitBitmap(bitmap_db_door, bitmap_db_door,
2122 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE,
2123 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1);
2125 SetDrawBackgroundMask(REDRAW_FIELD | REDRAW_DOOR_1);
2127 /* clear door drawing field */
2128 DrawBackground(DX, DY, DXSIZE, DYSIZE);
2130 /* force DOOR font on preview level */
2131 game_status = GAME_MODE_PSEUDO_DOOR;
2133 /* write text for request */
2134 for (ty = 0; ty < MAX_REQUEST_LINES; ty++)
2136 char text_line[MAX_REQUEST_LINE_LEN + 1];
2142 for (tl = 0, tx = 0; tx < MAX_REQUEST_LINE_LEN; tl++, tx++)
2145 if (!tc || tc == ' ')
2156 strncpy(text_line, text, tl);
2159 DrawText(DX + (DXSIZE - tl * getFontWidth(FONT_TEXT_2)) / 2,
2160 DY + 8 + ty * (getFontHeight(FONT_TEXT_2) + 2),
2161 text_line, FONT_TEXT_2);
2163 text += tl + (tc == ' ' ? 1 : 0);
2166 game_status = last_game_status; /* restore current game status */
2168 if (req_state & REQ_ASK)
2170 MapGadget(tool_gadget[TOOL_CTRL_ID_YES]);
2171 MapGadget(tool_gadget[TOOL_CTRL_ID_NO]);
2173 else if (req_state & REQ_CONFIRM)
2175 MapGadget(tool_gadget[TOOL_CTRL_ID_CONFIRM]);
2177 else if (req_state & REQ_PLAYER)
2179 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_1]);
2180 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_2]);
2181 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_3]);
2182 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_4]);
2185 /* copy request gadgets to door backbuffer */
2186 BlitBitmap(drawto, bitmap_db_door,
2187 DX, DY, DXSIZE, DYSIZE,
2188 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
2190 OpenDoor(DOOR_OPEN_1);
2196 if (!(req_state & REQUEST_WAIT_FOR))
2198 SetDrawBackgroundMask(REDRAW_FIELD);
2203 if (game_status != GAME_MODE_MAIN)
2206 button_status = MB_RELEASED;
2208 request_gadget_id = -1;
2210 SetDrawBackgroundMask(REDRAW_FIELD | REDRAW_DOOR_1);
2213 SetMouseCursor(CURSOR_DEFAULT);
2226 case EVENT_BUTTONPRESS:
2227 case EVENT_BUTTONRELEASE:
2228 case EVENT_MOTIONNOTIFY:
2230 if (event.type == EVENT_MOTIONNOTIFY)
2232 if (!PointerInWindow(window))
2233 continue; /* window and pointer are on different screens */
2238 motion_status = TRUE;
2239 mx = ((MotionEvent *) &event)->x;
2240 my = ((MotionEvent *) &event)->y;
2244 motion_status = FALSE;
2245 mx = ((ButtonEvent *) &event)->x;
2246 my = ((ButtonEvent *) &event)->y;
2247 if (event.type == EVENT_BUTTONPRESS)
2248 button_status = ((ButtonEvent *) &event)->button;
2250 button_status = MB_RELEASED;
2253 /* this sets 'request_gadget_id' */
2254 HandleGadgets(mx, my, button_status);
2256 switch(request_gadget_id)
2258 case TOOL_CTRL_ID_YES:
2261 case TOOL_CTRL_ID_NO:
2264 case TOOL_CTRL_ID_CONFIRM:
2265 result = TRUE | FALSE;
2268 case TOOL_CTRL_ID_PLAYER_1:
2271 case TOOL_CTRL_ID_PLAYER_2:
2274 case TOOL_CTRL_ID_PLAYER_3:
2277 case TOOL_CTRL_ID_PLAYER_4:
2288 case EVENT_KEYPRESS:
2289 switch(GetEventKey((KeyEvent *)&event, TRUE))
2302 if (req_state & REQ_PLAYER)
2306 case EVENT_KEYRELEASE:
2307 ClearPlayerAction();
2311 HandleOtherEvents(&event);
2315 else if (AnyJoystickButton() == JOY_BUTTON_NEW_PRESSED)
2317 int joy = AnyJoystick();
2319 if (joy & JOY_BUTTON_1)
2321 else if (joy & JOY_BUTTON_2)
2327 /* don't eat all CPU time */
2331 if (game_status != GAME_MODE_MAIN)
2336 if (!(req_state & REQ_STAY_OPEN))
2338 CloseDoor(DOOR_CLOSE_1);
2340 if (!(req_state & REQ_STAY_CLOSED) && (old_door_state & DOOR_OPEN_1))
2342 BlitBitmap(bitmap_db_door, bitmap_db_door,
2343 DOOR_GFX_PAGEX2,DOOR_GFX_PAGEY1, DXSIZE,DYSIZE,
2344 DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY1);
2345 OpenDoor(DOOR_OPEN_1);
2351 SetDrawBackgroundMask(REDRAW_FIELD);
2353 #if defined(PLATFORM_UNIX)
2354 /* continue network game after request */
2355 if (options.network &&
2356 game_status == GAME_MODE_PLAYING &&
2357 req_state & REQUEST_WAIT_FOR)
2358 SendToServer_ContinuePlaying();
2364 unsigned int OpenDoor(unsigned int door_state)
2366 unsigned int new_door_state;
2368 if (door_state & DOOR_COPY_BACK)
2370 BlitBitmap(bitmap_db_door, bitmap_db_door,
2371 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE + VYSIZE,
2372 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
2373 door_state &= ~DOOR_COPY_BACK;
2376 new_door_state = MoveDoor(door_state);
2378 return(new_door_state);
2381 unsigned int CloseDoor(unsigned int door_state)
2383 unsigned int new_door_state;
2385 BlitBitmap(backbuffer, bitmap_db_door,
2386 DX, DY, DXSIZE, DYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
2387 BlitBitmap(backbuffer, bitmap_db_door,
2388 VX, VY, VXSIZE, VYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2);
2390 new_door_state = MoveDoor(door_state);
2392 return(new_door_state);
2395 unsigned int GetDoorState()
2397 return MoveDoor(DOOR_GET_STATE);
2400 unsigned int SetDoorState(unsigned int door_state)
2402 return MoveDoor(door_state | DOOR_SET_STATE);
2405 unsigned int MoveDoor(unsigned int door_state)
2407 static int door1 = DOOR_OPEN_1;
2408 static int door2 = DOOR_CLOSE_2;
2409 unsigned long door_delay = 0;
2410 unsigned long door_delay_value;
2413 if (door_state == DOOR_GET_STATE)
2414 return(door1 | door2);
2416 if (door_state & DOOR_SET_STATE)
2418 if (door_state & DOOR_ACTION_1)
2419 door1 = door_state & DOOR_ACTION_1;
2420 if (door_state & DOOR_ACTION_2)
2421 door2 = door_state & DOOR_ACTION_2;
2423 return(door1 | door2);
2426 if (door1 == DOOR_OPEN_1 && door_state & DOOR_OPEN_1)
2427 door_state &= ~DOOR_OPEN_1;
2428 else if (door1 == DOOR_CLOSE_1 && door_state & DOOR_CLOSE_1)
2429 door_state &= ~DOOR_CLOSE_1;
2430 if (door2 == DOOR_OPEN_2 && door_state & DOOR_OPEN_2)
2431 door_state &= ~DOOR_OPEN_2;
2432 else if (door2 == DOOR_CLOSE_2 && door_state & DOOR_CLOSE_2)
2433 door_state &= ~DOOR_CLOSE_2;
2435 door_delay_value = (door_state & DOOR_ACTION_1 ? door_1.step_delay :
2438 if (setup.quick_doors)
2440 stepsize = 20; /* must be choosen to always draw last frame */
2441 door_delay_value = 0;
2443 StopSound(SND_DOOR_OPENING);
2444 StopSound(SND_DOOR_CLOSING);
2447 if (global.autoplay_leveldir)
2449 door_state |= DOOR_NO_DELAY;
2450 door_state &= ~DOOR_CLOSE_ALL;
2453 if (door_state & DOOR_ACTION)
2455 boolean door_1_done = !(door_state & DOOR_ACTION_1);
2456 boolean door_2_done = !(door_state & DOOR_ACTION_2);
2457 int start = ((door_state & DOOR_NO_DELAY) ? DXSIZE : 0);
2458 int end = (door_state & DOOR_ACTION_1 &&
2459 door_1.anim_mode == ANIM_VERTICAL ? DYSIZE : DXSIZE);
2462 if (!(door_state & DOOR_NO_DELAY))
2464 /* opening door sound has priority over simultaneously closing door */
2465 if (door_state & (DOOR_OPEN_1 | DOOR_OPEN_2))
2466 PlaySoundStereo(SND_DOOR_OPENING, SOUND_MIDDLE);
2467 else if (door_state & (DOOR_CLOSE_1 | DOOR_CLOSE_2))
2468 PlaySoundStereo(SND_DOOR_CLOSING, SOUND_MIDDLE);
2471 for (x = start; x <= end && !(door_1_done && door_2_done); x += stepsize)
2473 Bitmap *bitmap = graphic_info[IMG_GLOBAL_DOOR].bitmap;
2474 GC gc = bitmap->stored_clip_gc;
2476 if (door_state & DOOR_ACTION_1)
2478 int a = MIN(x * door_1.step_offset, end);
2479 int i = (door_state & DOOR_OPEN_1 ? end - a : a);
2483 BlitBitmap(bitmap_db_door, drawto,
2484 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1 + i / 2,
2485 DXSIZE,DYSIZE - i / 2, DX, DY);
2487 ClearRectangle(drawto, DX, DY + DYSIZE - i / 2, DXSIZE, i / 2);
2490 if (door_1.anim_mode == ANIM_HORIZONTAL && x <= DXSIZE)
2492 int src1_x = DXSIZE, src1_y = DOOR_GFX_PAGEY1;
2493 int dst1_x = DX + DXSIZE - i, dst1_y = DY;
2494 int src2_x = DXSIZE - i, src2_y = DOOR_GFX_PAGEY1;
2495 int dst2_x = DX, dst2_y = DY;
2496 int width = i, height = DYSIZE;
2498 SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y);
2499 BlitBitmapMasked(bitmap, drawto, src1_x, src1_y, width, height,
2502 SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y);
2503 BlitBitmapMasked(bitmap, drawto, src2_x, src2_y, width, height,
2506 else if (door_1.anim_mode == ANIM_VERTICAL && x <= DYSIZE)
2508 int src1_x = DXSIZE, src1_y = DOOR_GFX_PAGEY1;
2509 int dst1_x = DX, dst1_y = DY + DYSIZE - i;
2510 int src2_x = 0, src2_y = DOOR_GFX_PAGEY1 + DYSIZE - i;
2511 int dst2_x = DX, dst2_y = DY;
2512 int width = DXSIZE, height = i;
2514 SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y);
2515 BlitBitmapMasked(bitmap, drawto, src1_x, src1_y, width, height,
2518 SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y);
2519 BlitBitmapMasked(bitmap, drawto, src2_x, src2_y, width, height,
2522 else if (x <= DXSIZE) /* ANIM_DEFAULT */
2524 int j = (door_1.anim_mode == ANIM_DEFAULT ? (DXSIZE - i) / 3 : 0);
2526 SetClipOrigin(bitmap, gc, DX - i, (DY + j) - DOOR_GFX_PAGEY1);
2527 BlitBitmapMasked(bitmap, drawto,
2528 DXSIZE, DOOR_GFX_PAGEY1, i, 77,
2529 DX + DXSIZE - i, DY + j);
2530 BlitBitmapMasked(bitmap, drawto,
2531 DXSIZE, DOOR_GFX_PAGEY1 + 140, i, 63,
2532 DX + DXSIZE - i, DY + 140 + j);
2533 SetClipOrigin(bitmap, gc, DX - DXSIZE + i,
2534 DY - (DOOR_GFX_PAGEY1 + j));
2535 BlitBitmapMasked(bitmap, drawto,
2536 DXSIZE - i, DOOR_GFX_PAGEY1 + j, i, 77 - j,
2538 BlitBitmapMasked(bitmap, drawto,
2539 DXSIZE-i, DOOR_GFX_PAGEY1 + 140, i, 63,
2542 BlitBitmapMasked(bitmap, drawto,
2543 DXSIZE - i, DOOR_GFX_PAGEY1 + 77, i, 63,
2545 BlitBitmapMasked(bitmap, drawto,
2546 DXSIZE - i, DOOR_GFX_PAGEY1 + 203, i, 77,
2548 SetClipOrigin(bitmap, gc, DX - i, (DY + j) - DOOR_GFX_PAGEY1);
2549 BlitBitmapMasked(bitmap, drawto,
2550 DXSIZE, DOOR_GFX_PAGEY1 + 77, i, 63,
2551 DX + DXSIZE - i, DY + 77 + j);
2552 BlitBitmapMasked(bitmap, drawto,
2553 DXSIZE, DOOR_GFX_PAGEY1 + 203, i, 77 - j,
2554 DX + DXSIZE - i, DY + 203 + j);
2557 redraw_mask |= REDRAW_DOOR_1;
2558 door_1_done = (a == end);
2561 if (door_state & DOOR_ACTION_2)
2563 int a = MIN(x * door_2.step_offset, VXSIZE);
2564 int i = (door_state & DOOR_OPEN_2 ? VXSIZE - a : a);
2568 BlitBitmap(bitmap_db_door, drawto,
2569 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2 + i / 2,
2570 VXSIZE, VYSIZE - i / 2, VX, VY);
2572 ClearRectangle(drawto, VX, VY + VYSIZE - i / 2, VXSIZE, i / 2);
2575 if (door_2.anim_mode == ANIM_HORIZONTAL && x <= VXSIZE)
2577 int src1_x = VXSIZE, src1_y = DOOR_GFX_PAGEY2;
2578 int dst1_x = VX + VXSIZE - i, dst1_y = VY;
2579 int src2_x = VXSIZE - i, src2_y = DOOR_GFX_PAGEY2;
2580 int dst2_x = VX, dst2_y = VY;
2581 int width = i, height = VYSIZE;
2583 SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y);
2584 BlitBitmapMasked(bitmap, drawto, src1_x, src1_y, width, height,
2587 SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y);
2588 BlitBitmapMasked(bitmap, drawto, src2_x, src2_y, width, height,
2591 else if (door_2.anim_mode == ANIM_VERTICAL && x <= VYSIZE)
2593 int src1_x = VXSIZE, src1_y = DOOR_GFX_PAGEY2;
2594 int dst1_x = VX, dst1_y = VY + VYSIZE - i;
2595 int src2_x = 0, src2_y = DOOR_GFX_PAGEY2 + VYSIZE - i;
2596 int dst2_x = VX, dst2_y = VY;
2597 int width = VXSIZE, height = i;
2599 SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y);
2600 BlitBitmapMasked(bitmap, drawto, src1_x, src1_y, width, height,
2603 SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y);
2604 BlitBitmapMasked(bitmap, drawto, src2_x, src2_y, width, height,
2607 else if (x <= VXSIZE) /* ANIM_DEFAULT */
2609 int j = (door_2.anim_mode == ANIM_DEFAULT ? (VXSIZE - i) / 3 : 0);
2611 SetClipOrigin(bitmap, gc, VX - i, (VY + j) - DOOR_GFX_PAGEY2);
2612 BlitBitmapMasked(bitmap, drawto,
2613 VXSIZE, DOOR_GFX_PAGEY2, i, VYSIZE / 2,
2614 VX + VXSIZE - i, VY + j);
2615 SetClipOrigin(bitmap, gc,
2616 VX - VXSIZE + i, VY - (DOOR_GFX_PAGEY2 + j));
2617 BlitBitmapMasked(bitmap, drawto,
2618 VXSIZE - i, DOOR_GFX_PAGEY2 + j, i, VYSIZE / 2 - j,
2621 BlitBitmapMasked(bitmap, drawto,
2622 VXSIZE - i, DOOR_GFX_PAGEY2 + VYSIZE / 2,
2623 i, VYSIZE / 2, VX, VY + VYSIZE / 2 - j);
2624 SetClipOrigin(bitmap, gc, VX - i, (VY + j) - DOOR_GFX_PAGEY2);
2625 BlitBitmapMasked(bitmap, drawto,
2626 VXSIZE, DOOR_GFX_PAGEY2 + VYSIZE / 2,
2628 VX + VXSIZE - i, VY + VYSIZE / 2 + j);
2631 redraw_mask |= REDRAW_DOOR_2;
2632 door_2_done = (a == VXSIZE);
2637 if (game_status == GAME_MODE_MAIN)
2640 if (!(door_state & DOOR_NO_DELAY))
2641 WaitUntilDelayReached(&door_delay, door_delay_value);
2645 if (setup.quick_doors)
2647 StopSound(SND_DOOR_OPENING);
2648 StopSound(SND_DOOR_CLOSING);
2651 if (door_state & DOOR_ACTION_1)
2652 door1 = door_state & DOOR_ACTION_1;
2653 if (door_state & DOOR_ACTION_2)
2654 door2 = door_state & DOOR_ACTION_2;
2656 return (door1 | door2);
2659 void DrawSpecialEditorDoor()
2661 /* draw bigger toolbox window */
2662 BlitBitmap(graphic_info[IMG_GLOBAL_DOOR].bitmap, drawto,
2663 DOOR_GFX_PAGEX7, 0, EXSIZE + 8, 8,
2665 BlitBitmap(graphic_info[IMG_GLOBAL_BORDER].bitmap, drawto,
2666 EX - 4, VY - 4, EXSIZE + 8, EYSIZE - VYSIZE + 4,
2669 redraw_mask |= REDRAW_ALL;
2672 void UndrawSpecialEditorDoor()
2674 /* draw normal tape recorder window */
2675 BlitBitmap(graphic_info[IMG_GLOBAL_BORDER].bitmap, drawto,
2676 EX - 4, EY - 12, EXSIZE + 8, EYSIZE - VYSIZE + 12,
2679 redraw_mask |= REDRAW_ALL;
2683 /* ---------- new tool button stuff ---------------------------------------- */
2685 /* graphic position values for tool buttons */
2686 #define TOOL_BUTTON_YES_XPOS 2
2687 #define TOOL_BUTTON_YES_YPOS 250
2688 #define TOOL_BUTTON_YES_GFX_YPOS 0
2689 #define TOOL_BUTTON_YES_XSIZE 46
2690 #define TOOL_BUTTON_YES_YSIZE 28
2691 #define TOOL_BUTTON_NO_XPOS 52
2692 #define TOOL_BUTTON_NO_YPOS TOOL_BUTTON_YES_YPOS
2693 #define TOOL_BUTTON_NO_GFX_YPOS TOOL_BUTTON_YES_GFX_YPOS
2694 #define TOOL_BUTTON_NO_XSIZE TOOL_BUTTON_YES_XSIZE
2695 #define TOOL_BUTTON_NO_YSIZE TOOL_BUTTON_YES_YSIZE
2696 #define TOOL_BUTTON_CONFIRM_XPOS TOOL_BUTTON_YES_XPOS
2697 #define TOOL_BUTTON_CONFIRM_YPOS TOOL_BUTTON_YES_YPOS
2698 #define TOOL_BUTTON_CONFIRM_GFX_YPOS 30
2699 #define TOOL_BUTTON_CONFIRM_XSIZE 96
2700 #define TOOL_BUTTON_CONFIRM_YSIZE TOOL_BUTTON_YES_YSIZE
2701 #define TOOL_BUTTON_PLAYER_XSIZE 30
2702 #define TOOL_BUTTON_PLAYER_YSIZE 30
2703 #define TOOL_BUTTON_PLAYER_GFX_XPOS 5
2704 #define TOOL_BUTTON_PLAYER_GFX_YPOS 185
2705 #define TOOL_BUTTON_PLAYER_XPOS (5 + TOOL_BUTTON_PLAYER_XSIZE / 2)
2706 #define TOOL_BUTTON_PLAYER_YPOS (215 - TOOL_BUTTON_PLAYER_YSIZE / 2)
2707 #define TOOL_BUTTON_PLAYER1_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2708 + 0 * TOOL_BUTTON_PLAYER_XSIZE)
2709 #define TOOL_BUTTON_PLAYER2_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2710 + 1 * TOOL_BUTTON_PLAYER_XSIZE)
2711 #define TOOL_BUTTON_PLAYER3_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2712 + 0 * TOOL_BUTTON_PLAYER_XSIZE)
2713 #define TOOL_BUTTON_PLAYER4_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2714 + 1 * TOOL_BUTTON_PLAYER_XSIZE)
2715 #define TOOL_BUTTON_PLAYER1_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2716 + 0 * TOOL_BUTTON_PLAYER_YSIZE)
2717 #define TOOL_BUTTON_PLAYER2_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2718 + 0 * TOOL_BUTTON_PLAYER_YSIZE)
2719 #define TOOL_BUTTON_PLAYER3_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2720 + 1 * TOOL_BUTTON_PLAYER_YSIZE)
2721 #define TOOL_BUTTON_PLAYER4_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2722 + 1 * TOOL_BUTTON_PLAYER_YSIZE)
2731 } toolbutton_info[NUM_TOOL_BUTTONS] =
2734 TOOL_BUTTON_YES_XPOS, TOOL_BUTTON_YES_GFX_YPOS,
2735 TOOL_BUTTON_YES_XPOS, TOOL_BUTTON_YES_YPOS,
2736 TOOL_BUTTON_YES_XSIZE, TOOL_BUTTON_YES_YSIZE,
2741 TOOL_BUTTON_NO_XPOS, TOOL_BUTTON_NO_GFX_YPOS,
2742 TOOL_BUTTON_NO_XPOS, TOOL_BUTTON_NO_YPOS,
2743 TOOL_BUTTON_NO_XSIZE, TOOL_BUTTON_NO_YSIZE,
2748 TOOL_BUTTON_CONFIRM_XPOS, TOOL_BUTTON_CONFIRM_GFX_YPOS,
2749 TOOL_BUTTON_CONFIRM_XPOS, TOOL_BUTTON_CONFIRM_YPOS,
2750 TOOL_BUTTON_CONFIRM_XSIZE, TOOL_BUTTON_CONFIRM_YSIZE,
2751 TOOL_CTRL_ID_CONFIRM,
2755 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2756 TOOL_BUTTON_PLAYER1_XPOS, TOOL_BUTTON_PLAYER1_YPOS,
2757 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2758 TOOL_CTRL_ID_PLAYER_1,
2762 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2763 TOOL_BUTTON_PLAYER2_XPOS, TOOL_BUTTON_PLAYER2_YPOS,
2764 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2765 TOOL_CTRL_ID_PLAYER_2,
2769 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2770 TOOL_BUTTON_PLAYER3_XPOS, TOOL_BUTTON_PLAYER3_YPOS,
2771 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2772 TOOL_CTRL_ID_PLAYER_3,
2776 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2777 TOOL_BUTTON_PLAYER4_XPOS, TOOL_BUTTON_PLAYER4_YPOS,
2778 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2779 TOOL_CTRL_ID_PLAYER_4,
2784 void CreateToolButtons()
2788 for (i = 0; i < NUM_TOOL_BUTTONS; i++)
2790 Bitmap *gd_bitmap = graphic_info[IMG_GLOBAL_DOOR].bitmap;
2791 Bitmap *deco_bitmap = None;
2792 int deco_x = 0, deco_y = 0, deco_xpos = 0, deco_ypos = 0;
2793 struct GadgetInfo *gi;
2794 unsigned long event_mask;
2795 int gd_xoffset, gd_yoffset;
2796 int gd_x1, gd_x2, gd_y;
2799 event_mask = GD_EVENT_RELEASED;
2801 gd_xoffset = toolbutton_info[i].xpos;
2802 gd_yoffset = toolbutton_info[i].ypos;
2803 gd_x1 = DOOR_GFX_PAGEX4 + gd_xoffset;
2804 gd_x2 = DOOR_GFX_PAGEX3 + gd_xoffset;
2805 gd_y = DOOR_GFX_PAGEY1 + gd_yoffset;
2807 if (id >= TOOL_CTRL_ID_PLAYER_1 && id <= TOOL_CTRL_ID_PLAYER_4)
2809 int player_nr = id - TOOL_CTRL_ID_PLAYER_1;
2811 getMiniGraphicSource(PLAYER_NR_GFX(IMG_PLAYER_1, player_nr),
2812 &deco_bitmap, &deco_x, &deco_y);
2813 deco_xpos = (toolbutton_info[i].width - MINI_TILEX) / 2;
2814 deco_ypos = (toolbutton_info[i].height - MINI_TILEY) / 2;
2817 gi = CreateGadget(GDI_CUSTOM_ID, id,
2818 GDI_INFO_TEXT, toolbutton_info[i].infotext,
2819 GDI_X, DX + toolbutton_info[i].x,
2820 GDI_Y, DY + toolbutton_info[i].y,
2821 GDI_WIDTH, toolbutton_info[i].width,
2822 GDI_HEIGHT, toolbutton_info[i].height,
2823 GDI_TYPE, GD_TYPE_NORMAL_BUTTON,
2824 GDI_STATE, GD_BUTTON_UNPRESSED,
2825 GDI_DESIGN_UNPRESSED, gd_bitmap, gd_x1, gd_y,
2826 GDI_DESIGN_PRESSED, gd_bitmap, gd_x2, gd_y,
2827 GDI_DECORATION_DESIGN, deco_bitmap, deco_x, deco_y,
2828 GDI_DECORATION_POSITION, deco_xpos, deco_ypos,
2829 GDI_DECORATION_SIZE, MINI_TILEX, MINI_TILEY,
2830 GDI_DECORATION_SHIFTING, 1, 1,
2831 GDI_EVENT_MASK, event_mask,
2832 GDI_CALLBACK_ACTION, HandleToolButtons,
2836 Error(ERR_EXIT, "cannot create gadget");
2838 tool_gadget[id] = gi;
2842 void FreeToolButtons()
2846 for (i = 0; i < NUM_TOOL_BUTTONS; i++)
2847 FreeGadget(tool_gadget[i]);
2850 static void UnmapToolButtons()
2854 for (i = 0; i < NUM_TOOL_BUTTONS; i++)
2855 UnmapGadget(tool_gadget[i]);
2858 static void HandleToolButtons(struct GadgetInfo *gi)
2860 request_gadget_id = gi->custom_id;
2863 int get_next_element(int element)
2867 case EL_QUICKSAND_FILLING: return EL_QUICKSAND_FULL;
2868 case EL_QUICKSAND_EMPTYING: return EL_QUICKSAND_EMPTY;
2869 case EL_MAGIC_WALL_FILLING: return EL_MAGIC_WALL_FULL;
2870 case EL_MAGIC_WALL_EMPTYING: return EL_MAGIC_WALL_ACTIVE;
2871 case EL_BD_MAGIC_WALL_FILLING: return EL_BD_MAGIC_WALL_FULL;
2872 case EL_BD_MAGIC_WALL_EMPTYING: return EL_BD_MAGIC_WALL_ACTIVE;
2873 case EL_AMOEBA_DROPPING: return EL_AMOEBA_WET;
2875 default: return element;
2879 int el_act_dir2img(int element, int action, int direction)
2881 element = GFX_ELEMENT(element);
2882 direction = MV_DIR_BIT(direction);
2884 return element_info[element].direction_graphic[action][direction];
2887 static int el_act_dir2crm(int element, int action, int direction)
2889 element = GFX_ELEMENT(element);
2890 direction = MV_DIR_BIT(direction);
2892 return element_info[element].direction_crumbled[action][direction];
2895 int el_act2img(int element, int action)
2897 element = GFX_ELEMENT(element);
2899 return element_info[element].graphic[action];
2902 int el_act2crm(int element, int action)
2904 element = GFX_ELEMENT(element);
2906 return element_info[element].crumbled[action];
2909 int el_dir2img(int element, int direction)
2911 element = GFX_ELEMENT(element);
2913 return el_act_dir2img(element, ACTION_DEFAULT, direction);
2916 int el2img(int element)
2918 element = GFX_ELEMENT(element);
2920 return element_info[element].graphic[ACTION_DEFAULT];
2923 int el2edimg(int element)
2925 element = GFX_ELEMENT(element);
2927 return element_info[element].special_graphic[GFX_SPECIAL_ARG_EDITOR];
2930 int el2preimg(int element)
2932 element = GFX_ELEMENT(element);
2934 return element_info[element].special_graphic[GFX_SPECIAL_ARG_PREVIEW];