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 int getGraphicAnimationPhase(int, int, int);
36 static void DrawGraphicAnimationShiftedThruMask(int, int, int, int, int,
38 static void UnmapToolButtons();
39 static void HandleToolButtons(struct GadgetInfo *);
41 static struct GadgetInfo *tool_gadget[NUM_TOOL_BUTTONS];
42 static int request_gadget_id = -1;
44 void SetDrawtoField(int mode)
46 if (mode == DRAW_BUFFERED && setup.soft_scrolling)
57 drawto_field = fieldbuffer;
59 else /* DRAW_DIRECT, DRAW_BACKBUFFER */
70 drawto_field = (mode == DRAW_DIRECT ? window : backbuffer);
74 void RedrawPlayfield(boolean force_redraw, int x, int y, int width, int height)
76 if (game_status == PLAYING)
82 width = gfx.sxsize + 2 * TILEX;
83 height = gfx.sysize + 2 * TILEY;
86 if (force_redraw || setup.direct_draw)
89 int x1 = (x - SX) / TILEX, y1 = (y - SY) / TILEY;
90 int x2 = (x - SX + width) / TILEX, y2 = (y - SY + height) / TILEY;
92 if (setup.direct_draw)
93 SetDrawtoField(DRAW_BACKBUFFER);
95 for(xx=BX1; xx<=BX2; xx++)
96 for(yy=BY1; yy<=BY2; yy++)
97 if (xx >= x1 && xx <= x2 && yy >= y1 && yy <= y2)
98 DrawScreenField(xx, yy);
101 if (setup.direct_draw)
102 SetDrawtoField(DRAW_DIRECT);
105 if (setup.soft_scrolling)
107 int fx = FX, fy = FY;
109 fx += (ScreenMovDir & (MV_LEFT|MV_RIGHT) ? ScreenGfxPos : 0);
110 fy += (ScreenMovDir & (MV_UP|MV_DOWN) ? ScreenGfxPos : 0);
112 BlitBitmap(fieldbuffer, backbuffer, fx,fy, SXSIZE,SYSIZE, SX,SY);
116 BlitBitmap(drawto, window, x, y, width, height, x, y);
122 DrawBuffer *buffer = (drawto_field == window ? backbuffer : drawto_field);
124 if (setup.direct_draw && game_status == PLAYING)
125 redraw_mask &= ~REDRAW_MAIN;
127 if (redraw_mask & REDRAW_TILES && redraw_tiles > REDRAWTILES_THRESHOLD)
128 redraw_mask |= REDRAW_FIELD;
130 if (redraw_mask & REDRAW_FIELD)
131 redraw_mask &= ~REDRAW_TILES;
133 if (redraw_mask == REDRAW_NONE)
136 if (global.fps_slowdown && game_status == PLAYING)
138 static boolean last_frame_skipped = FALSE;
139 boolean skip_even_when_not_scrolling = TRUE;
140 boolean just_scrolling = (ScreenMovDir != 0);
141 boolean verbose = FALSE;
143 if (global.fps_slowdown_factor > 1 &&
144 (FrameCounter % global.fps_slowdown_factor) &&
145 (just_scrolling || skip_even_when_not_scrolling))
147 redraw_mask &= ~REDRAW_MAIN;
149 last_frame_skipped = TRUE;
152 printf("FRAME SKIPPED\n");
156 if (last_frame_skipped)
157 redraw_mask |= REDRAW_FIELD;
159 last_frame_skipped = FALSE;
162 printf("frame not skipped\n");
166 /* synchronize X11 graphics at this point; if we would synchronize the
167 display immediately after the buffer switching (after the XFlush),
168 this could mean that we have to wait for the graphics to complete,
169 although we could go on doing calculations for the next frame */
173 if (redraw_mask & REDRAW_ALL)
175 BlitBitmap(backbuffer, window, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
179 if (redraw_mask & REDRAW_FIELD)
181 if (game_status != PLAYING || 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);
249 if (redraw_mask & REDRAW_DOOR_3)
250 BlitBitmap(backbuffer, window, EX, EY, EXSIZE, EYSIZE, EX, EY);
251 redraw_mask &= ~REDRAW_DOORS;
254 if (redraw_mask & REDRAW_MICROLEVEL)
256 BlitBitmap(backbuffer, window,
257 MICROLEV_XPOS, MICROLEV_YPOS, MICROLEV_XSIZE, MICROLEV_YSIZE,
258 MICROLEV_XPOS, MICROLEV_YPOS);
259 BlitBitmap(backbuffer, window,
260 SX, MICROLABEL_YPOS, SXSIZE, FONT4_YSIZE,
261 SX, MICROLABEL_YPOS);
262 redraw_mask &= ~REDRAW_MICROLEVEL;
265 if (redraw_mask & REDRAW_TILES)
267 for(x=0; x<SCR_FIELDX; x++)
268 for(y=0; y<SCR_FIELDY; y++)
269 if (redraw[redraw_x1 + x][redraw_y1 + y])
270 BlitBitmap(buffer, window,
271 FX + x * TILEX, FX + y * TILEY, TILEX, TILEY,
272 SX + x * TILEX, SY + y * TILEY);
275 if (redraw_mask & REDRAW_FPS) /* display frames per second */
280 sprintf(info1, " (only every %d. frame)", global.fps_slowdown_factor);
281 if (!global.fps_slowdown)
284 sprintf(text, "%.1f fps%s", global.frames_per_second, info1);
285 DrawTextExt(window, SX, SY, text, FS_SMALL, FC_YELLOW);
290 for(x=0; x<MAX_BUF_XSIZE; x++)
291 for(y=0; y<MAX_BUF_YSIZE; y++)
294 redraw_mask = REDRAW_NONE;
300 long fading_delay = 300;
302 if (setup.fading && (redraw_mask & REDRAW_FIELD))
309 ClearRectangle(window, REAL_SX,REAL_SY,FULL_SXSIZE,FULL_SYSIZE);
312 for(i=0;i<2*FULL_SYSIZE;i++)
314 for(y=0;y<FULL_SYSIZE;y++)
316 BlitBitmap(backbuffer, window,
317 REAL_SX,REAL_SY+i, FULL_SXSIZE,1, REAL_SX,REAL_SY+i);
325 for(i=1;i<FULL_SYSIZE;i+=2)
326 BlitBitmap(backbuffer, window,
327 REAL_SX,REAL_SY+i, FULL_SXSIZE,1, REAL_SX,REAL_SY+i);
333 SetClipOrigin(clip_gc[PIX_FADEMASK], 0, 0);
334 BlitBitmapMasked(backbuffer, window,
335 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE,
340 SetClipOrigin(clip_gc[PIX_FADEMASK], -1, -1);
341 BlitBitmapMasked(backbuffer, window,
342 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE,
347 SetClipOrigin(clip_gc[PIX_FADEMASK], 0, -1);
348 BlitBitmapMasked(backbuffer, window,
349 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE,
354 SetClipOrigin(clip_gc[PIX_FADEMASK], -1, 0);
355 BlitBitmapMasked(backbuffer, window,
356 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE,
361 redraw_mask &= ~REDRAW_MAIN;
370 ClearRectangle(backbuffer, REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE);
372 if (setup.soft_scrolling && game_status == PLAYING)
374 ClearRectangle(fieldbuffer, 0, 0, FXSIZE, FYSIZE);
375 SetDrawtoField(DRAW_BUFFERED);
378 SetDrawtoField(DRAW_BACKBUFFER);
380 if (setup.direct_draw && game_status == PLAYING)
382 ClearRectangle(window, REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE);
383 SetDrawtoField(DRAW_DIRECT);
386 redraw_mask |= REDRAW_FIELD;
389 void MarkTileDirty(int x, int y)
391 int xx = redraw_x1 + x;
392 int yy = redraw_y1 + y;
397 redraw[xx][yy] = TRUE;
398 redraw_mask |= REDRAW_TILES;
401 void SetBorderElement()
405 BorderElement = EL_EMPTY;
407 for(y=0; y<lev_fieldy && BorderElement == EL_EMPTY; y++)
409 for(x=0; x<lev_fieldx; x++)
411 if (!IS_MASSIVE(Feld[x][y]))
412 BorderElement = EL_STEELWALL;
414 if (y != 0 && y != lev_fieldy - 1 && x != lev_fieldx - 1)
420 void DrawAllPlayers()
424 for(i=0; i<MAX_PLAYERS; i++)
425 if (stored_player[i].active)
426 DrawPlayer(&stored_player[i]);
429 void DrawPlayerField(int x, int y)
431 if (!IS_PLAYER(x, y))
434 DrawPlayer(PLAYERINFO(x, y));
437 void DrawPlayer(struct PlayerInfo *player)
439 int jx = player->jx, jy = player->jy;
440 int last_jx = player->last_jx, last_jy = player->last_jy;
441 int next_jx = jx + (jx - last_jx), next_jy = jy + (jy - last_jy);
442 int sx = SCREENX(jx), sy = SCREENY(jy);
443 int sxx = 0, syy = 0;
444 int element = Feld[jx][jy], last_element = Feld[last_jx][last_jy];
446 boolean player_is_moving = (last_jx != jx || last_jy != jy ? TRUE : FALSE);
448 if (!player->active || !IN_SCR_FIELD(SCREENX(last_jx), SCREENY(last_jy)))
452 if (!IN_LEV_FIELD(jx,jy))
454 printf("DrawPlayerField(): x = %d, y = %d\n",jx,jy);
455 printf("DrawPlayerField(): sx = %d, sy = %d\n",sx,sy);
456 printf("DrawPlayerField(): This should never happen!\n");
461 if (element == EL_EXPLOSION)
464 /* draw things in the field the player is leaving, if needed */
466 if (player_is_moving)
468 if (Store[last_jx][last_jy] && IS_DRAWABLE(last_element))
470 DrawLevelElement(last_jx, last_jy, Store[last_jx][last_jy]);
471 if (last_element == EL_DYNAMITE_ACTIVE)
472 DrawDynamite(last_jx, last_jy);
474 DrawLevelFieldThruMask(last_jx, last_jy);
476 else if (last_element == EL_DYNAMITE_ACTIVE)
477 DrawDynamite(last_jx, last_jy);
479 DrawLevelField(last_jx, last_jy);
481 if (player->Pushing && IN_SCR_FIELD(SCREENX(next_jx), SCREENY(next_jy)))
485 if (Feld[next_jx][next_jy] == EL_SOKOBAN_FIELD_FULL)
486 DrawLevelElement(next_jx, next_jy, EL_SOKOBAN_FIELD_EMPTY);
488 DrawLevelElement(next_jx, next_jy, EL_EMPTY);
491 DrawLevelField(next_jx, next_jy);
495 if (!IN_SCR_FIELD(sx, sy))
498 if (setup.direct_draw)
499 SetDrawtoField(DRAW_BUFFERED);
501 /* draw things behind the player, if needed */
504 DrawLevelElement(jx, jy, Store[jx][jy]);
505 else if (!IS_ACTIVE_BOMB(element))
506 DrawLevelField(jx, jy);
508 DrawLevelElement(jx, jy, EL_EMPTY);
510 /* draw player himself */
512 if (game.emulation == EMU_SUPAPLEX)
514 static int last_dir = MV_LEFT;
515 int action = (player->programmed_action ? player->programmed_action :
517 boolean action_moving =
519 ((action & (MV_LEFT | MV_RIGHT | MV_UP | MV_DOWN)) &&
520 !(action & ~(MV_LEFT | MV_RIGHT | MV_UP | MV_DOWN))));
522 graphic = GFX_SP_MURPHY;
526 if (player->MovDir == MV_LEFT)
527 graphic = GFX_MURPHY_PUSH_LEFT;
528 else if (player->MovDir == MV_RIGHT)
529 graphic = GFX_MURPHY_PUSH_RIGHT;
530 else if (player->MovDir & (MV_UP | MV_DOWN) && last_dir == MV_LEFT)
531 graphic = GFX_MURPHY_PUSH_LEFT;
532 else if (player->MovDir & (MV_UP | MV_DOWN) && last_dir == MV_RIGHT)
533 graphic = GFX_MURPHY_PUSH_RIGHT;
535 else if (player->snapped)
537 if (player->MovDir == MV_LEFT)
538 graphic = GFX_MURPHY_SNAP_LEFT;
539 else if (player->MovDir == MV_RIGHT)
540 graphic = GFX_MURPHY_SNAP_RIGHT;
541 else if (player->MovDir == MV_UP)
542 graphic = GFX_MURPHY_SNAP_UP;
543 else if (player->MovDir == MV_DOWN)
544 graphic = GFX_MURPHY_SNAP_DOWN;
546 else if (action_moving)
548 if (player->MovDir == MV_LEFT)
549 graphic = GFX_MURPHY_GO_LEFT;
550 else if (player->MovDir == MV_RIGHT)
551 graphic = GFX_MURPHY_GO_RIGHT;
552 else if (player->MovDir & (MV_UP | MV_DOWN) && last_dir == MV_LEFT)
553 graphic = GFX_MURPHY_GO_LEFT;
554 else if (player->MovDir & (MV_UP | MV_DOWN) && last_dir == MV_RIGHT)
555 graphic = GFX_MURPHY_GO_RIGHT;
557 graphic = GFX_MURPHY_GO_LEFT;
559 graphic += getGraphicAnimationPhase(3, 2, ANIM_PINGPONG);
562 if (player->MovDir == MV_LEFT || player->MovDir == MV_RIGHT)
563 last_dir = player->MovDir;
567 if (player->MovDir == MV_LEFT)
569 (player->Pushing ? GFX_SPIELER1_PUSH_LEFT : GFX_SPIELER1_LEFT);
570 else if (player->MovDir == MV_RIGHT)
572 (player->Pushing ? GFX_SPIELER1_PUSH_RIGHT : GFX_SPIELER1_RIGHT);
573 else if (player->MovDir == MV_UP)
574 graphic = GFX_SPIELER1_UP;
575 else /* MV_DOWN || MV_NO_MOVING */
576 graphic = GFX_SPIELER1_DOWN;
578 graphic += player->index_nr * 3 * HEROES_PER_LINE;
579 graphic += player->Frame;
584 if (player->MovDir == MV_LEFT || player->MovDir == MV_RIGHT)
585 sxx = player->GfxPos;
587 syy = player->GfxPos;
590 if (!setup.soft_scrolling && ScreenMovPos)
593 DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, NO_CUTTING);
595 if (SHIELD_ON(player))
597 int graphic = (player->shield_active_time_left ? GFX2_SHIELD_ACTIVE :
598 GFX2_SHIELD_PASSIVE);
600 DrawGraphicAnimationShiftedThruMask(sx, sy, sxx, syy, graphic,
601 3, 8, ANIM_PINGPONG);
604 if (player->Pushing && player->GfxPos)
606 int px = SCREENX(next_jx), py = SCREENY(next_jy);
608 if (element == EL_SOKOBAN_FIELD_EMPTY ||
609 Feld[next_jx][next_jy] == EL_SOKOBAN_FIELD_FULL)
610 DrawGraphicShiftedThruMask(px, py, sxx, syy, GFX_SOKOBAN_OBJEKT,
614 int element = Feld[next_jx][next_jy];
615 int graphic = el2gfx(element);
617 if ((element == EL_ROCK ||
618 element == EL_SP_ZONK ||
619 element == EL_BD_ROCK) && sxx)
621 int phase = (player->GfxPos / (TILEX / 4));
623 if (player->MovDir == MV_LEFT)
626 graphic += (phase + 4) % 4;
629 DrawGraphicShifted(px, py, sxx, syy, graphic, NO_CUTTING, NO_MASKING);
633 /* draw things in front of player (active dynamite or dynabombs) */
635 if (IS_ACTIVE_BOMB(element))
637 graphic = el2gfx(element);
639 if (element == EL_DYNAMITE_ACTIVE)
641 if ((phase = (96 - MovDelay[jx][jy]) / 12) > 6)
646 if ((phase = ((96 - MovDelay[jx][jy]) / 6) % 8) > 3)
650 if (game.emulation == EMU_SUPAPLEX)
651 DrawGraphic(sx, sy, GFX_SP_DISK_RED);
653 DrawGraphicThruMask(sx, sy, graphic + phase);
656 if (player_is_moving && last_element == EL_EXPLOSION)
658 int phase = Frame[last_jx][last_jy];
662 DrawGraphicThruMask(SCREENX(last_jx), SCREENY(last_jy),
663 GFX_EXPLOSION + ((phase - 1) / delay - 1));
666 /* draw elements that stay over the player */
667 /* handle the field the player is leaving ... */
668 if (player_is_moving && IS_OVER_PLAYER(last_element))
669 DrawLevelField(last_jx, last_jy);
670 /* ... and the field the player is entering */
671 if (IS_OVER_PLAYER(element))
672 DrawLevelField(jx, jy);
674 if (setup.direct_draw)
676 int dest_x = SX + SCREENX(MIN(jx, last_jx)) * TILEX;
677 int dest_y = SY + SCREENY(MIN(jy, last_jy)) * TILEY;
678 int x_size = TILEX * (1 + ABS(jx - last_jx));
679 int y_size = TILEY * (1 + ABS(jy - last_jy));
681 BlitBitmap(drawto_field, window,
682 dest_x, dest_y, x_size, y_size, dest_x, dest_y);
683 SetDrawtoField(DRAW_DIRECT);
686 MarkTileDirty(sx,sy);
689 static int getGraphicAnimationPhase(int frames, int delay, int mode)
693 if (mode & ANIM_PINGPONG)
695 int max_anim_frames = 2 * frames - 2;
697 phase = (FrameCounter % (delay * max_anim_frames)) / delay;
698 phase = (phase < frames ? phase : max_anim_frames - phase);
701 phase = (FrameCounter % (delay * frames)) / delay;
703 if (mode & ANIM_REVERSE)
709 int getNewGraphicAnimationFrame(int graphic, int sync_frame)
711 int num_frames = new_graphic_info[graphic].anim_frames;
712 int delay = new_graphic_info[graphic].anim_delay;
713 int mode = new_graphic_info[graphic].anim_mode;
716 /* animation synchronized with global frame counter, not move position */
717 if (new_graphic_info[graphic].anim_global_sync || sync_frame < 0)
718 sync_frame = FrameCounter;
720 if (mode & ANIM_LOOP) /* normal, looping animation */
722 frame = (sync_frame % (delay * num_frames)) / delay;
724 else if (mode & ANIM_LINEAR) /* normal, non-looping animation */
726 frame = sync_frame / delay;
728 if (frame > num_frames - 1)
729 frame = num_frames - 1;
731 else if (mode & ANIM_PINGPONG) /* use border frames once */
733 int max_anim_frames = 2 * num_frames - 2;
735 frame = (sync_frame % (delay * max_anim_frames)) / delay;
736 frame = (frame < num_frames ? frame : max_anim_frames - frame);
738 else if (mode & ANIM_PINGPONG2) /* use border frames twice */
740 int max_anim_frames = 2 * num_frames;
742 frame = (sync_frame % (delay * max_anim_frames)) / delay;
743 frame = (frame < num_frames ? frame : max_anim_frames - frame - 1);
746 if (mode & ANIM_REVERSE) /* use reverse animation direction */
747 frame = num_frames - frame - 1;
752 void DrawGraphicAnimationExt(int x, int y, int graphic,
753 int frames, int delay, int mode, int mask_mode)
755 int phase = getGraphicAnimationPhase(frames, delay, mode);
757 if (!(FrameCounter % delay) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
759 if (mask_mode == USE_MASKING)
760 DrawGraphicThruMask(SCREENX(x), SCREENY(y), graphic + phase);
762 DrawGraphic(SCREENX(x), SCREENY(y), graphic + phase);
766 void DrawNewGraphicAnimationExt(int x, int y, int graphic, int mask_mode)
769 int delay = new_graphic_info[graphic].anim_delay;
771 if (!(FrameCounter % delay) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
773 if (IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
776 int frame = getNewGraphicAnimationFrame(graphic, -1);
778 if (mask_mode == USE_MASKING)
779 DrawNewGraphicThruMask(SCREENX(x), SCREENY(y), graphic, frame);
781 DrawNewGraphic(SCREENX(x), SCREENY(y), graphic, frame);
785 void DrawGraphicAnimation(int x, int y, int graphic,
786 int frames, int delay, int mode)
788 DrawGraphicAnimationExt(x, y, graphic, frames, delay, mode, NO_MASKING);
791 void DrawNewGraphicAnimation(int x, int y, int graphic)
793 DrawNewGraphicAnimationExt(x, y, graphic, NO_MASKING);
796 void DrawGraphicAnimationThruMask(int x, int y, int graphic,
797 int frames, int delay, int mode)
799 DrawGraphicAnimationExt(x, y, graphic, frames, delay, mode, USE_MASKING);
802 static void DrawGraphicAnimationShiftedThruMask(int sx, int sy,
805 int frames, int delay,
808 int phase = getGraphicAnimationPhase(frames, delay, mode);
810 DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic + phase, NO_CUTTING);
813 void getGraphicSource(int graphic, Bitmap **bitmap, int *x, int *y)
815 if (graphic >= 0 && graphic_info[graphic].bitmap != NULL)
817 *bitmap = graphic_info[graphic].bitmap;
818 *x = graphic_info[graphic].src_x;
819 *y = graphic_info[graphic].src_y;
821 else if (graphic >= GFX_START_ROCKSELEMENTS &&
822 graphic <= GFX_END_ROCKSELEMENTS)
824 graphic -= GFX_START_ROCKSELEMENTS;
825 *bitmap = pix[PIX_ELEMENTS];
826 *x = (graphic % GFX_PER_LINE) * TILEX;
827 *y = (graphic / GFX_PER_LINE) * TILEY;
829 else if (graphic >= GFX_START_ROCKSHEROES && graphic <= GFX_END_ROCKSHEROES)
831 graphic -= GFX_START_ROCKSHEROES;
832 *bitmap = pix[PIX_HEROES];
833 *x = (graphic % HEROES_PER_LINE) * TILEX;
834 *y = (graphic / HEROES_PER_LINE) * TILEY;
836 else if (graphic >= GFX_START_ROCKSSP && graphic <= GFX_END_ROCKSSP)
838 graphic -= GFX_START_ROCKSSP;
839 *bitmap = pix[PIX_SP];
840 *x = (graphic % SP_PER_LINE) * TILEX;
841 *y = (graphic / SP_PER_LINE) * TILEY;
843 else if (graphic >= GFX_START_ROCKSDC && graphic <= GFX_END_ROCKSDC)
845 graphic -= GFX_START_ROCKSDC;
846 *bitmap = pix[PIX_DC];
847 *x = (graphic % DC_PER_LINE) * TILEX;
848 *y = (graphic / DC_PER_LINE) * TILEY;
850 else if (graphic >= GFX_START_ROCKSMORE && graphic <= GFX_END_ROCKSMORE)
852 graphic -= GFX_START_ROCKSMORE;
853 *bitmap = pix[PIX_MORE];
854 *x = (graphic % MORE_PER_LINE) * TILEX;
855 *y = (graphic / MORE_PER_LINE) * TILEY;
857 else if (graphic >= GFX_START_ROCKSFONT && graphic <= GFX_END_ROCKSFONT)
859 graphic -= GFX_START_ROCKSFONT;
860 *bitmap = pix[PIX_FONT_EM];
861 *x = (graphic % FONT_CHARS_PER_LINE) * TILEX;
862 *y = (graphic / FONT_CHARS_PER_LINE) * TILEY;
866 *bitmap = pix[PIX_SP];
872 void DrawGraphic(int x, int y, int graphic)
875 if (!IN_SCR_FIELD(x, y))
877 printf("DrawGraphic(): x = %d, y = %d, graphic = %d\n", x, y, graphic);
878 printf("DrawGraphic(): This should never happen!\n");
883 DrawGraphicExt(drawto_field, FX + x * TILEX, FY + y * TILEY, graphic);
887 void DrawNewGraphic(int x, int y, int graphic, int frame)
890 if (!IN_SCR_FIELD(x, y))
892 printf("DrawNewGraphic(): x = %d, y = %d, graphic = %d\n", x, y, graphic);
893 printf("DrawNewGraphic(): This should never happen!\n");
898 DrawNewGraphicExt(drawto_field, FX + x * TILEX, FY + y * TILEY,
903 void DrawGraphicExt(DrawBuffer *dst_bitmap, int x, int y, int graphic)
908 getGraphicSource(graphic, &src_bitmap, &src_x, &src_y);
909 BlitBitmap(src_bitmap, dst_bitmap, src_x, src_y, TILEX, TILEY, x, y);
912 void DrawNewGraphicExt(DrawBuffer *dst_bitmap, int x, int y, int graphic,
915 Bitmap *src_bitmap = new_graphic_info[graphic].bitmap;
916 int src_x = new_graphic_info[graphic].src_x;
917 int src_y = new_graphic_info[graphic].src_y;
918 int offset_x = new_graphic_info[graphic].offset_x;
919 int offset_y = new_graphic_info[graphic].offset_y;
921 src_x += frame * offset_x;
922 src_y += frame * offset_y;
924 BlitBitmap(src_bitmap, dst_bitmap, src_x, src_y, TILEX, TILEY, x, y);
927 void DrawGraphicThruMask(int x, int y, int graphic)
930 if (!IN_SCR_FIELD(x, y))
932 printf("DrawGraphicThruMask(): x = %d,y = %d, graphic = %d\n",x,y,graphic);
933 printf("DrawGraphicThruMask(): This should never happen!\n");
938 DrawGraphicThruMaskExt(drawto_field, FX + x * TILEX, FY + y *TILEY, graphic);
942 void DrawNewGraphicThruMask(int x, int y, int graphic, int frame)
945 if (!IN_SCR_FIELD(x, y))
947 printf("DrawGraphicThruMask(): x = %d,y = %d, graphic = %d\n",x,y,graphic);
948 printf("DrawGraphicThruMask(): This should never happen!\n");
953 DrawNewGraphicThruMaskExt(drawto_field, FX + x * TILEX, FY + y *TILEY,
958 void DrawGraphicThruMaskExt(DrawBuffer *d, int dest_x, int dest_y, int graphic)
965 if (graphic == GFX_LEERRAUM)
968 getGraphicSource(graphic, &src_bitmap, &src_x, &src_y);
969 drawing_gc = src_bitmap->stored_clip_gc;
971 if (tile_clipmask[tile] != None)
973 SetClipMask(src_bitmap, tile_clip_gc, tile_clipmask[tile]);
974 SetClipOrigin(src_bitmap, tile_clip_gc, dest_x, dest_y);
975 BlitBitmapMasked(src_bitmap, d,
976 src_x, src_y, TILEX, TILEY, dest_x, dest_y);
982 printf("DrawGraphicThruMask(): tile '%d' needs clipping!\n", tile);
986 SetClipOrigin(src_bitmap, drawing_gc, dest_x - src_x, dest_y - src_y);
987 BlitBitmapMasked(src_bitmap, d,
988 src_x, src_y, TILEX, TILEY, dest_x, dest_y);
992 void DrawNewGraphicThruMaskExt(DrawBuffer *d, int dest_x, int dest_y,
993 int graphic, int frame)
995 Bitmap *src_bitmap = new_graphic_info[graphic].bitmap;
996 GC drawing_gc = src_bitmap->stored_clip_gc;
997 int src_x = new_graphic_info[graphic].src_x;
998 int src_y = new_graphic_info[graphic].src_y;
999 int offset_x = new_graphic_info[graphic].offset_x;
1000 int offset_y = new_graphic_info[graphic].offset_y;
1002 src_x += frame * offset_x;
1003 src_y += frame * offset_y;
1005 SetClipOrigin(src_bitmap, drawing_gc, dest_x - src_x, dest_y - src_y);
1006 BlitBitmapMasked(src_bitmap, d, src_x, src_y, TILEX, TILEY, dest_x, dest_y);
1009 void DrawMiniGraphic(int x, int y, int graphic)
1011 DrawMiniGraphicExt(drawto, SX + x*MINI_TILEX, SY + y*MINI_TILEY, graphic);
1012 MarkTileDirty(x/2, y/2);
1015 void getMiniGraphicSource(int graphic, Bitmap **bitmap, int *x, int *y)
1017 if (graphic >= GFX_START_ROCKSELEMENTS && graphic <= GFX_END_ROCKSELEMENTS)
1019 graphic -= GFX_START_ROCKSELEMENTS;
1020 *bitmap = pix[PIX_ELEMENTS];
1021 *x = MINI_GFX_STARTX + (graphic % MINI_GFX_PER_LINE) * MINI_TILEX;
1022 *y = MINI_GFX_STARTY + (graphic / MINI_GFX_PER_LINE) * MINI_TILEY;
1024 else if (graphic >= GFX_START_ROCKSSP && graphic <= GFX_END_ROCKSSP)
1026 graphic -= GFX_START_ROCKSSP;
1027 *bitmap = pix[PIX_SP];
1028 *x = MINI_SP_STARTX + (graphic % MINI_SP_PER_LINE) * MINI_TILEX;
1029 *y = MINI_SP_STARTY + (graphic / MINI_SP_PER_LINE) * MINI_TILEY;
1031 else if (graphic >= GFX_START_ROCKSDC && graphic <= GFX_END_ROCKSDC)
1033 graphic -= GFX_START_ROCKSDC;
1034 *bitmap = pix[PIX_DC];
1035 *x = MINI_DC_STARTX + (graphic % MINI_DC_PER_LINE) * MINI_TILEX;
1036 *y = MINI_DC_STARTY + (graphic / MINI_DC_PER_LINE) * MINI_TILEY;
1038 else if (graphic >= GFX_START_ROCKSMORE && graphic <= GFX_END_ROCKSMORE)
1040 graphic -= GFX_START_ROCKSMORE;
1041 *bitmap = pix[PIX_MORE];
1042 *x = MINI_MORE_STARTX + (graphic % MINI_MORE_PER_LINE) * MINI_TILEX;
1043 *y = MINI_MORE_STARTY + (graphic / MINI_MORE_PER_LINE) * MINI_TILEY;
1045 else if (graphic >= GFX_START_ROCKSFONT && graphic <= GFX_END_ROCKSFONT)
1047 graphic -= GFX_START_ROCKSFONT;
1048 *bitmap = pix[PIX_FONT_EM];
1049 *x = MINI_FONT_STARTX + (graphic % FONT_CHARS_PER_LINE) * FONT4_XSIZE;
1050 *y = MINI_FONT_STARTY + (graphic / FONT_CHARS_PER_LINE) * FONT4_YSIZE;
1054 *bitmap = pix[PIX_SP];
1055 *x = MINI_SP_STARTX;
1056 *y = MINI_SP_STARTY;
1060 void DrawMiniGraphicExt(DrawBuffer *d, int x, int y, int graphic)
1065 getMiniGraphicSource(graphic, &bitmap, &src_x, &src_y);
1066 BlitBitmap(bitmap, d, src_x, src_y, MINI_TILEX, MINI_TILEY, x, y);
1069 void DrawGraphicShifted(int x,int y, int dx,int dy, int graphic,
1070 int cut_mode, int mask_mode)
1072 int width = TILEX, height = TILEY;
1074 int src_x, src_y, dest_x, dest_y;
1081 DrawGraphic(x, y, graphic);
1085 if (dx || dy) /* Verschiebung der Grafik? */
1087 if (x < BX1) /* Element kommt von links ins Bild */
1094 else if (x > BX2) /* Element kommt von rechts ins Bild */
1100 else if (x==BX1 && dx < 0) /* Element verläßt links das Bild */
1106 else if (x==BX2 && dx > 0) /* Element verläßt rechts das Bild */
1108 else if (dx) /* allg. Bewegung in x-Richtung */
1109 MarkTileDirty(x + SIGN(dx), y);
1111 if (y < BY1) /* Element kommt von oben ins Bild */
1113 if (cut_mode==CUT_BELOW) /* Element oberhalb des Bildes */
1121 else if (y > BY2) /* Element kommt von unten ins Bild */
1127 else if (y==BY1 && dy < 0) /* Element verläßt oben das Bild */
1133 else if (dy > 0 && cut_mode == CUT_ABOVE)
1135 if (y == BY2) /* Element unterhalb des Bildes */
1141 MarkTileDirty(x, y + 1);
1142 } /* Element verläßt unten das Bild */
1143 else if (dy > 0 && (y == BY2 || cut_mode == CUT_BELOW))
1145 else if (dy) /* allg. Bewegung in y-Richtung */
1146 MarkTileDirty(x, y + SIGN(dy));
1149 getGraphicSource(graphic, &src_bitmap, &src_x, &src_y);
1150 drawing_gc = src_bitmap->stored_clip_gc;
1155 dest_x = FX + x * TILEX + dx;
1156 dest_y = FY + y * TILEY + dy;
1159 if (!IN_SCR_FIELD(x,y))
1161 printf("DrawGraphicShifted(): x = %d, y = %d, graphic = %d\n",x,y,graphic);
1162 printf("DrawGraphicShifted(): This should never happen!\n");
1167 if (mask_mode == USE_MASKING)
1169 if (tile_clipmask[tile] != None)
1171 SetClipMask(src_bitmap, tile_clip_gc, tile_clipmask[tile]);
1172 SetClipOrigin(src_bitmap, tile_clip_gc, dest_x, dest_y);
1173 BlitBitmapMasked(src_bitmap, drawto_field,
1174 src_x, src_y, TILEX, TILEY, dest_x, dest_y);
1180 printf("DrawGraphicShifted(): tile '%d' needs clipping!\n", tile);
1184 SetClipOrigin(src_bitmap, drawing_gc, dest_x - src_x, dest_y - src_y);
1185 BlitBitmapMasked(src_bitmap, drawto_field,
1186 src_x, src_y, width, height, dest_x, dest_y);
1190 BlitBitmap(src_bitmap, drawto_field,
1191 src_x, src_y, width, height, dest_x, dest_y);
1196 void DrawNewGraphicShifted(int x,int y, int dx,int dy, int graphic, int frame,
1197 int cut_mode, int mask_mode)
1206 int width = TILEX, height = TILEY;
1212 DrawNewGraphic(x, y, graphic, frame);
1216 if (dx || dy) /* Verschiebung der Grafik? */
1218 if (x < BX1) /* Element kommt von links ins Bild */
1225 else if (x > BX2) /* Element kommt von rechts ins Bild */
1231 else if (x==BX1 && dx < 0) /* Element verläßt links das Bild */
1237 else if (x==BX2 && dx > 0) /* Element verläßt rechts das Bild */
1239 else if (dx) /* allg. Bewegung in x-Richtung */
1240 MarkTileDirty(x + SIGN(dx), y);
1242 if (y < BY1) /* Element kommt von oben ins Bild */
1244 if (cut_mode==CUT_BELOW) /* Element oberhalb des Bildes */
1252 else if (y > BY2) /* Element kommt von unten ins Bild */
1258 else if (y==BY1 && dy < 0) /* Element verläßt oben das Bild */
1264 else if (dy > 0 && cut_mode == CUT_ABOVE)
1266 if (y == BY2) /* Element unterhalb des Bildes */
1272 MarkTileDirty(x, y + 1);
1273 } /* Element verläßt unten das Bild */
1274 else if (dy > 0 && (y == BY2 || cut_mode == CUT_BELOW))
1276 else if (dy) /* allg. Bewegung in y-Richtung */
1277 MarkTileDirty(x, y + SIGN(dy));
1280 src_bitmap = new_graphic_info[graphic].bitmap;
1281 drawing_gc = src_bitmap->stored_clip_gc;
1282 src_x = new_graphic_info[graphic].src_x;
1283 src_y = new_graphic_info[graphic].src_y;
1284 offset_x = new_graphic_info[graphic].offset_x;
1285 offset_y = new_graphic_info[graphic].offset_y;
1287 src_x += frame * offset_x;
1288 src_y += frame * offset_y;
1293 dest_x = FX + x * TILEX + dx;
1294 dest_y = FY + y * TILEY + dy;
1297 if (!IN_SCR_FIELD(x,y))
1299 printf("DrawGraphicShifted(): x = %d, y = %d, graphic = %d\n",x,y,graphic);
1300 printf("DrawGraphicShifted(): This should never happen!\n");
1305 if (mask_mode == USE_MASKING)
1306 SetClipOrigin(src_bitmap, drawing_gc, dest_x - src_x, dest_y - src_y);
1308 BlitBitmap(src_bitmap, drawto_field, src_x, src_y, width, height,
1314 void DrawGraphicShiftedThruMask(int x,int y, int dx,int dy, int graphic,
1317 DrawGraphicShifted(x,y, dx,dy, graphic, cut_mode, USE_MASKING);
1320 void DrawNewGraphicShiftedThruMask(int x,int y, int dx,int dy, int graphic,
1321 int frame, int cut_mode)
1323 DrawNewGraphicShifted(x,y, dx,dy, graphic, frame, cut_mode, USE_MASKING);
1326 void DrawScreenElementExt(int x, int y, int dx, int dy, int element,
1327 int cut_mode, int mask_mode)
1329 int ux = LEVELX(x), uy = LEVELY(y);
1330 int graphic = el2gfx(element);
1331 int phase8 = ABS(MovPos[ux][uy]) / (TILEX / 8);
1332 int phase4 = phase8 / 2;
1333 int phase2 = phase8 / 4;
1334 int dir = MovDir[ux][uy];
1336 if (element == EL_PACMAN || element == EL_BUG || element == EL_SPACESHIP)
1338 graphic += 1 * !phase2;
1342 else if (dir == MV_LEFT)
1344 else if (dir == MV_DOWN)
1347 else if (element == EL_SP_SNIKSNAK)
1350 graphic = GFX_SP_SNIKSNAK_LEFT;
1351 else if (dir == MV_RIGHT)
1352 graphic = GFX_SP_SNIKSNAK_RIGHT;
1353 else if (dir == MV_UP)
1354 graphic = GFX_SP_SNIKSNAK_UP;
1356 graphic = GFX_SP_SNIKSNAK_DOWN;
1358 graphic += (phase8 < 4 ? phase8 : 7 - phase8);
1360 else if (element == EL_SP_ELECTRON)
1362 graphic = GFX2_SP_ELECTRON + getGraphicAnimationPhase(8, 2, ANIM_LOOP);
1364 else if (element == EL_MOLE || element == EL_PENGUIN ||
1365 element == EL_PIG || element == EL_DRAGON)
1368 graphic = (element == EL_MOLE ? GFX_MOLE_LEFT :
1369 element == EL_PENGUIN ? GFX_PINGUIN_LEFT :
1370 element == EL_PIG ? GFX_SCHWEIN_LEFT : GFX_DRACHE_LEFT);
1371 else if (dir == MV_RIGHT)
1372 graphic = (element == EL_MOLE ? GFX_MOLE_RIGHT :
1373 element == EL_PENGUIN ? GFX_PINGUIN_RIGHT :
1374 element == EL_PIG ? GFX_SCHWEIN_RIGHT : GFX_DRACHE_RIGHT);
1375 else if (dir == MV_UP)
1376 graphic = (element == EL_MOLE ? GFX_MOLE_UP :
1377 element == EL_PENGUIN ? GFX_PINGUIN_UP :
1378 element == EL_PIG ? GFX_SCHWEIN_UP : GFX_DRACHE_UP);
1380 graphic = (element == EL_MOLE ? GFX_MOLE_DOWN :
1381 element == EL_PENGUIN ? GFX_PINGUIN_DOWN :
1382 element == EL_PIG ? GFX_SCHWEIN_DOWN : GFX_DRACHE_DOWN);
1386 else if (element == EL_SATELLITE)
1388 graphic = GFX_SONDE_START + getGraphicAnimationPhase(8, 2, ANIM_LOOP);
1390 else if (element == EL_ACID)
1392 graphic = GFX_GEBLUBBER + getGraphicAnimationPhase(4, 10, ANIM_LOOP);
1394 else if (element == EL_BD_BUTTERFLY || element == EL_BD_FIREFLY)
1398 else if (element == EL_BALLOON)
1402 else if ((element == EL_ROCK ||
1403 element == EL_SP_ZONK ||
1404 element == EL_BD_ROCK ||
1405 element == EL_SP_INFOTRON ||
1409 if (uy >= lev_fieldy-1 || !IS_BELT(Feld[ux][uy+1]))
1411 if (element == EL_ROCK ||
1412 element == EL_SP_ZONK ||
1413 element == EL_BD_ROCK)
1416 graphic += (4 - phase4) % 4;
1417 else if (dir == MV_RIGHT)
1420 graphic += phase2 * 2;
1422 else if (element != EL_SP_INFOTRON)
1426 else if (element == EL_MAGIC_WALL_ACTIVE ||
1427 element == EL_MAGIC_WALL_EMPTYING ||
1428 element == EL_BD_MAGIC_WALL_ACTIVE ||
1429 element == EL_BD_MAGIC_WALL_EMPTYING ||
1430 element == EL_MAGIC_WALL_FULL ||
1431 element == EL_BD_MAGIC_WALL_FULL)
1433 graphic += 3 + getGraphicAnimationPhase(4, 4, ANIM_REVERSE);
1435 else if (IS_AMOEBOID(element) || element == EL_AMOEBA_DRIPPING)
1437 graphic = (element == EL_AMOEBA_DEAD ? GFX_AMOEBE_TOT : GFX_AMOEBE_LEBT);
1438 graphic += (x + 2 * y + 4) % 4;
1440 else if (element == EL_WALL_GROWING)
1442 boolean links_massiv = FALSE, rechts_massiv = FALSE;
1444 if (!IN_LEV_FIELD(ux-1, uy) || IS_MAUER(Feld[ux-1][uy]))
1445 links_massiv = TRUE;
1446 if (!IN_LEV_FIELD(ux+1, uy) || IS_MAUER(Feld[ux+1][uy]))
1447 rechts_massiv = TRUE;
1449 if (links_massiv && rechts_massiv)
1450 graphic = GFX_MAUERWERK;
1451 else if (links_massiv)
1452 graphic = GFX_MAUER_R;
1453 else if (rechts_massiv)
1454 graphic = GFX_MAUER_L;
1457 else if ((element == EL_INVISIBLE_STEELWALL ||
1458 element == EL_INVISIBLE_WALL ||
1459 element == EL_INVISIBLE_SAND) && game.light_time_left)
1461 graphic = (element == EL_INVISIBLE_STEELWALL ? GFX_INVISIBLE_STEEL_ON :
1462 element == EL_INVISIBLE_WALL ? GFX_UNSICHTBAR_ON :
1463 GFX_SAND_INVISIBLE_ON);
1468 DrawGraphicShifted(x, y, dx, dy, graphic, cut_mode, mask_mode);
1469 else if (mask_mode == USE_MASKING)
1470 DrawGraphicThruMask(x, y, graphic);
1472 DrawGraphic(x, y, graphic);
1475 inline static int getFramePosition(int x, int y)
1477 int element = Feld[x][y];
1480 if (element == EL_QUICKSAND_FULL ||
1481 element == EL_MAGIC_WALL_FULL ||
1482 element == EL_BD_MAGIC_WALL_FULL)
1484 else if (IS_MOVING(x, y) || CAN_MOVE(element) || CAN_FALL(element))
1485 frame_pos = ABS(MovPos[x][y]) / (TILEX / 8);
1490 inline static int getGfxAction(int x, int y)
1492 int gfx_action = GFX_ACTION_DEFAULT;
1494 if (GfxAction[x][y] != GFX_ACTION_DEFAULT)
1495 gfx_action = GfxAction[x][y];
1496 else if (IS_MOVING(x, y))
1497 gfx_action = GFX_ACTION_MOVING;
1502 void DrawNewScreenElementExt(int x, int y, int dx, int dy, int element,
1503 int cut_mode, int mask_mode)
1505 int ux = LEVELX(x), uy = LEVELY(y);
1506 int move_dir = MovDir[ux][uy];
1507 int move_pos = getFramePosition(ux, uy);
1508 int gfx_action = getGfxAction(ux, uy);
1509 int graphic = el_dir_act2img(element, move_dir, gfx_action);
1510 int frame = getNewGraphicAnimationFrame(graphic, move_pos);
1512 if (element == EL_WALL_GROWING)
1514 boolean left_stopped = FALSE, right_stopped = FALSE;
1516 if (!IN_LEV_FIELD(ux - 1, uy) || IS_MAUER(Feld[ux - 1][uy]))
1517 left_stopped = TRUE;
1518 if (!IN_LEV_FIELD(ux + 1, uy) || IS_MAUER(Feld[ux + 1][uy]))
1519 right_stopped = TRUE;
1521 if (left_stopped && right_stopped)
1523 else if (left_stopped)
1525 graphic = IMG_WALL_GROWING_ACTIVE_RIGHT;
1526 frame = new_graphic_info[graphic].anim_frames - 1;
1528 else if (right_stopped)
1530 graphic = IMG_WALL_GROWING_ACTIVE_LEFT;
1531 frame = new_graphic_info[graphic].anim_frames - 1;
1535 else if ((element == EL_ROCK ||
1536 element == EL_SP_ZONK ||
1537 element == EL_BD_ROCK ||
1538 element == EL_SP_INFOTRON ||
1542 if (uy >= lev_fieldy-1 || !IS_BELT(Feld[ux][uy+1]))
1544 if (element == EL_ROCK ||
1545 element == EL_SP_ZONK ||
1546 element == EL_BD_ROCK)
1548 if (move_dir == MV_LEFT)
1549 graphic += (4 - phase4) % 4;
1550 else if (move_dir == MV_RIGHT)
1553 graphic += phase2 * 2;
1555 else if (element != EL_SP_INFOTRON)
1560 else if (IS_AMOEBOID(element) || element == EL_AMOEBA_DRIPPING)
1562 graphic = (element == EL_BD_AMOEBA ? IMG_BD_AMOEBA_PART1 :
1563 element == EL_AMOEBA_WET ? IMG_AMOEBA_WET_PART1 :
1564 element == EL_AMOEBA_DRY ? IMG_AMOEBA_DRY_PART1 :
1565 element == EL_AMOEBA_FULL ? IMG_AMOEBA_FULL_PART1 :
1566 IMG_AMOEBA_DEAD_PART1);
1568 graphic += (x + 2 * y + 4) % 4;
1572 DrawNewGraphicShifted(x, y, dx, dy, graphic, frame, cut_mode, mask_mode);
1573 else if (mask_mode == USE_MASKING)
1574 DrawNewGraphicThruMask(x, y, graphic, frame);
1576 DrawNewGraphic(x, y, graphic, frame);
1579 void DrawLevelElementExt(int x, int y, int dx, int dy, int element,
1580 int cut_mode, int mask_mode)
1582 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1583 DrawScreenElementExt(SCREENX(x), SCREENY(y), dx, dy, element,
1584 cut_mode, mask_mode);
1587 void DrawNewLevelElementExt(int x, int y, int dx, int dy, int element,
1588 int cut_mode, int mask_mode)
1590 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1591 DrawNewScreenElementExt(SCREENX(x), SCREENY(y), dx, dy, element,
1592 cut_mode, mask_mode);
1595 void DrawScreenElementShifted(int x, int y, int dx, int dy, int element,
1598 DrawScreenElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
1601 void DrawNewScreenElementShifted(int x, int y, int dx, int dy, int element,
1604 DrawNewScreenElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
1607 void DrawLevelElementShifted(int x, int y, int dx, int dy, int element,
1610 DrawLevelElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
1613 void DrawNewLevelElementShifted(int x, int y, int dx, int dy, int element,
1616 DrawNewLevelElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
1619 void DrawScreenElementThruMask(int x, int y, int element)
1621 DrawScreenElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
1624 void DrawNewScreenElementThruMask(int x, int y, int element)
1626 DrawNewScreenElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
1629 void DrawLevelElementThruMask(int x, int y, int element)
1631 DrawLevelElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
1634 void DrawNewLevelElementThruMask(int x, int y, int element)
1636 DrawNewLevelElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
1639 void DrawLevelFieldThruMask(int x, int y)
1641 DrawLevelElementExt(x, y, 0, 0, Feld[x][y], NO_CUTTING, USE_MASKING);
1644 void DrawNewLevelFieldThruMask(int x, int y)
1646 DrawNewLevelElementExt(x, y, 0, 0, Feld[x][y], NO_CUTTING, USE_MASKING);
1649 void ErdreichAnbroeckeln(int x, int y)
1653 int i, width, height, cx,cy;
1654 int ux = LEVELX(x), uy = LEVELY(y);
1655 int element, graphic;
1657 static int xy[4][2] =
1665 if (!IN_LEV_FIELD(ux, uy))
1668 element = Feld[ux][uy];
1670 if (element == EL_SAND ||
1671 element == EL_LANDMINE ||
1672 element == EL_TRAP ||
1673 element == EL_TRAP_ACTIVE)
1675 if (!IN_SCR_FIELD(x, y))
1678 graphic = GFX_ERDENRAND;
1680 getGraphicSource(graphic, &src_bitmap, &src_x, &src_y);
1686 uxx = ux + xy[i][0];
1687 uyy = uy + xy[i][1];
1688 if (!IN_LEV_FIELD(uxx, uyy))
1689 element = EL_STEELWALL;
1691 element = Feld[uxx][uyy];
1693 if (element == EL_SAND ||
1694 element == EL_LANDMINE ||
1695 element == EL_TRAP ||
1696 element == EL_TRAP_ACTIVE)
1699 if (i == 1 || i == 2)
1703 cx = (i == 2 ? TILEX - snip : 0);
1711 cy = (i == 3 ? TILEY - snip : 0);
1714 BlitBitmap(src_bitmap, drawto_field, src_x + cx, src_y + cy,
1715 width, height, FX + x * TILEX + cx, FY + y * TILEY + cy);
1718 MarkTileDirty(x, y);
1722 graphic = GFX_ERDENRAND;
1724 getGraphicSource(graphic, &src_bitmap, &src_x, &src_y);
1728 int xx, yy, uxx, uyy;
1732 uxx = ux + xy[i][0];
1733 uyy = uy + xy[i][1];
1735 if (!IN_LEV_FIELD(uxx, uyy) ||
1736 (Feld[uxx][uyy] != EL_SAND &&
1737 Feld[uxx][uyy] != EL_LANDMINE &&
1738 Feld[uxx][uyy] != EL_TRAP &&
1739 Feld[uxx][uyy] != EL_TRAP_ACTIVE) ||
1740 !IN_SCR_FIELD(xx, yy))
1743 if (i == 1 || i == 2)
1747 cx = (i == 1 ? TILEX - snip : 0);
1755 cy = (i==0 ? TILEY-snip : 0);
1758 BlitBitmap(src_bitmap, drawto_field, src_x + cx, src_y + cy,
1759 width, height, FX + xx * TILEX + cx, FY + yy * TILEY + cy);
1761 MarkTileDirty(xx, yy);
1766 void DrawScreenElement(int x, int y, int element)
1768 DrawScreenElementExt(x, y, 0, 0, element, NO_CUTTING, NO_MASKING);
1769 ErdreichAnbroeckeln(x, y);
1772 void DrawNewScreenElement(int x, int y, int element)
1774 DrawNewScreenElementExt(x, y, 0, 0, element, NO_CUTTING, NO_MASKING);
1775 ErdreichAnbroeckeln(x, y);
1778 void DrawLevelElement(int x, int y, int element)
1780 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1781 DrawScreenElement(SCREENX(x), SCREENY(y), element);
1784 void DrawNewLevelElement(int x, int y, int element)
1786 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1787 DrawNewScreenElement(SCREENX(x), SCREENY(y), element);
1790 void DrawScreenField(int x, int y)
1792 int ux = LEVELX(x), uy = LEVELY(y);
1793 int element, content;
1795 if (!IN_LEV_FIELD(ux, uy))
1797 if (ux < -1 || ux > lev_fieldx || uy < -1 || uy > lev_fieldy)
1800 element = BorderElement;
1802 DrawScreenElement(x, y, element);
1806 element = Feld[ux][uy];
1807 content = Store[ux][uy];
1809 if (IS_MOVING(ux, uy))
1811 int horiz_move = (MovDir[ux][uy] == MV_LEFT || MovDir[ux][uy] == MV_RIGHT);
1812 boolean cut_mode = NO_CUTTING;
1814 if (element == EL_QUICKSAND_EMPTYING ||
1815 element == EL_MAGIC_WALL_EMPTYING ||
1816 element == EL_BD_MAGIC_WALL_EMPTYING ||
1817 element == EL_AMOEBA_DRIPPING)
1818 cut_mode = CUT_ABOVE;
1819 else if (element == EL_QUICKSAND_FILLING ||
1820 element == EL_MAGIC_WALL_FILLING ||
1821 element == EL_BD_MAGIC_WALL_FILLING)
1822 cut_mode = CUT_BELOW;
1824 if (cut_mode == CUT_ABOVE)
1825 DrawScreenElementShifted(x, y, 0, 0, element, NO_CUTTING);
1827 DrawScreenElement(x, y, EL_EMPTY);
1830 DrawScreenElementShifted(x, y, MovPos[ux][uy], 0, element, NO_CUTTING);
1831 else if (cut_mode == NO_CUTTING)
1832 DrawScreenElementShifted(x, y, 0, MovPos[ux][uy], element, cut_mode);
1834 DrawScreenElementShifted(x, y, 0, MovPos[ux][uy], content, cut_mode);
1836 if (content == EL_ACID)
1837 DrawLevelElementThruMask(ux, uy + 1, EL_ACID);
1839 else if (IS_BLOCKED(ux, uy))
1844 boolean cut_mode = NO_CUTTING;
1845 int element_old, content_old;
1847 Blocked2Moving(ux, uy, &oldx, &oldy);
1850 horiz_move = (MovDir[oldx][oldy] == MV_LEFT ||
1851 MovDir[oldx][oldy] == MV_RIGHT);
1853 element_old = Feld[oldx][oldy];
1854 content_old = Store[oldx][oldy];
1856 if (element_old == EL_QUICKSAND_EMPTYING ||
1857 element_old == EL_MAGIC_WALL_EMPTYING ||
1858 element_old == EL_BD_MAGIC_WALL_EMPTYING ||
1859 element_old == EL_AMOEBA_DRIPPING)
1860 cut_mode = CUT_ABOVE;
1862 DrawScreenElement(x, y, EL_EMPTY);
1865 DrawScreenElementShifted(sx, sy, MovPos[oldx][oldy], 0, element_old,
1867 else if (cut_mode == NO_CUTTING)
1868 DrawScreenElementShifted(sx, sy, 0, MovPos[oldx][oldy], element_old,
1871 DrawScreenElementShifted(sx, sy, 0, MovPos[oldx][oldy], content_old,
1874 else if (IS_DRAWABLE(element))
1875 DrawScreenElement(x, y, element);
1877 DrawScreenElement(x, y, EL_EMPTY);
1880 void DrawNewScreenField(int x, int y)
1882 int ux = LEVELX(x), uy = LEVELY(y);
1883 int element, content;
1885 if (!IN_LEV_FIELD(ux, uy))
1887 if (ux < -1 || ux > lev_fieldx || uy < -1 || uy > lev_fieldy)
1890 element = BorderElement;
1892 DrawNewScreenElement(x, y, element);
1896 element = Feld[ux][uy];
1897 content = Store[ux][uy];
1899 if (IS_MOVING(ux, uy))
1901 int horiz_move = (MovDir[ux][uy] == MV_LEFT || MovDir[ux][uy] == MV_RIGHT);
1902 boolean cut_mode = NO_CUTTING;
1904 if (element == EL_QUICKSAND_EMPTYING ||
1905 element == EL_MAGIC_WALL_EMPTYING ||
1906 element == EL_BD_MAGIC_WALL_EMPTYING ||
1907 element == EL_AMOEBA_DRIPPING)
1908 cut_mode = CUT_ABOVE;
1909 else if (element == EL_QUICKSAND_FILLING ||
1910 element == EL_MAGIC_WALL_FILLING ||
1911 element == EL_BD_MAGIC_WALL_FILLING)
1912 cut_mode = CUT_BELOW;
1914 if (cut_mode == CUT_ABOVE)
1915 DrawNewScreenElementShifted(x, y, 0, 0, element, NO_CUTTING);
1917 DrawNewScreenElement(x, y, EL_EMPTY);
1920 DrawNewScreenElementShifted(x, y, MovPos[ux][uy], 0, element, NO_CUTTING);
1921 else if (cut_mode == NO_CUTTING)
1922 DrawNewScreenElementShifted(x, y, 0, MovPos[ux][uy], element, cut_mode);
1924 DrawNewScreenElementShifted(x, y, 0, MovPos[ux][uy], content, cut_mode);
1926 if (content == EL_ACID)
1927 DrawNewLevelElementThruMask(ux, uy + 1, EL_ACID);
1929 else if (IS_BLOCKED(ux, uy))
1934 boolean cut_mode = NO_CUTTING;
1935 int element_old, content_old;
1937 Blocked2Moving(ux, uy, &oldx, &oldy);
1940 horiz_move = (MovDir[oldx][oldy] == MV_LEFT ||
1941 MovDir[oldx][oldy] == MV_RIGHT);
1943 element_old = Feld[oldx][oldy];
1944 content_old = Store[oldx][oldy];
1946 if (element_old == EL_QUICKSAND_EMPTYING ||
1947 element_old == EL_MAGIC_WALL_EMPTYING ||
1948 element_old == EL_BD_MAGIC_WALL_EMPTYING ||
1949 element_old == EL_AMOEBA_DRIPPING)
1950 cut_mode = CUT_ABOVE;
1952 DrawNewScreenElement(x, y, EL_EMPTY);
1955 DrawNewScreenElementShifted(sx, sy, MovPos[oldx][oldy], 0, element_old,
1957 else if (cut_mode == NO_CUTTING)
1958 DrawNewScreenElementShifted(sx, sy, 0, MovPos[oldx][oldy], element_old,
1961 DrawNewScreenElementShifted(sx, sy, 0, MovPos[oldx][oldy], content_old,
1964 else if (IS_DRAWABLE(element))
1965 DrawNewScreenElement(x, y, element);
1967 DrawNewScreenElement(x, y, EL_EMPTY);
1970 void DrawLevelField(int x, int y)
1972 if (IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1973 DrawScreenField(SCREENX(x), SCREENY(y));
1974 else if (IS_MOVING(x, y))
1978 Moving2Blocked(x, y, &newx, &newy);
1979 if (IN_SCR_FIELD(SCREENX(newx), SCREENY(newy)))
1980 DrawScreenField(SCREENX(newx), SCREENY(newy));
1982 else if (IS_BLOCKED(x, y))
1986 Blocked2Moving(x, y, &oldx, &oldy);
1987 if (IN_SCR_FIELD(SCREENX(oldx), SCREENY(oldy)))
1988 DrawScreenField(SCREENX(oldx), SCREENY(oldy));
1992 void DrawNewLevelField(int x, int y)
1994 if (IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1995 DrawNewScreenField(SCREENX(x), SCREENY(y));
1996 else if (IS_MOVING(x, y))
2000 Moving2Blocked(x, y, &newx, &newy);
2001 if (IN_SCR_FIELD(SCREENX(newx), SCREENY(newy)))
2002 DrawNewScreenField(SCREENX(newx), SCREENY(newy));
2004 else if (IS_BLOCKED(x, y))
2008 Blocked2Moving(x, y, &oldx, &oldy);
2009 if (IN_SCR_FIELD(SCREENX(oldx), SCREENY(oldy)))
2010 DrawNewScreenField(SCREENX(oldx), SCREENY(oldy));
2014 void DrawMiniElement(int x, int y, int element)
2020 DrawMiniGraphic(x, y, -1);
2024 graphic = el2gfx(element);
2025 DrawMiniGraphic(x, y, graphic);
2028 void DrawMiniElementOrWall(int sx, int sy, int scroll_x, int scroll_y)
2030 int x = sx + scroll_x, y = sy + scroll_y;
2032 if (x < -1 || x > lev_fieldx || y < -1 || y > lev_fieldy)
2033 DrawMiniElement(sx, sy, EL_EMPTY);
2034 else if (x > -1 && x < lev_fieldx && y > -1 && y < lev_fieldy)
2035 DrawMiniElement(sx, sy, Feld[x][y]);
2038 int steel_type, steel_position;
2041 { GFX_VSTEEL_UPPER_LEFT, GFX_ISTEEL_UPPER_LEFT },
2042 { GFX_VSTEEL_UPPER_RIGHT, GFX_ISTEEL_UPPER_RIGHT },
2043 { GFX_VSTEEL_LOWER_LEFT, GFX_ISTEEL_LOWER_LEFT },
2044 { GFX_VSTEEL_LOWER_RIGHT, GFX_ISTEEL_LOWER_RIGHT },
2045 { GFX_VSTEEL_VERTICAL, GFX_ISTEEL_VERTICAL },
2046 { GFX_VSTEEL_HORIZONTAL, GFX_ISTEEL_HORIZONTAL }
2049 steel_type = (BorderElement == EL_STEELWALL ? 0 : 1);
2050 steel_position = (x == -1 && y == -1 ? 0 :
2051 x == lev_fieldx && y == -1 ? 1 :
2052 x == -1 && y == lev_fieldy ? 2 :
2053 x == lev_fieldx && y == lev_fieldy ? 3 :
2054 x == -1 || x == lev_fieldx ? 4 :
2055 y == -1 || y == lev_fieldy ? 5 : -1);
2057 if (steel_position != -1)
2058 DrawMiniGraphic(sx, sy, border[steel_position][steel_type]);
2062 void DrawMicroElement(int xpos, int ypos, int element)
2066 if (element == EL_EMPTY)
2069 graphic = el2gfx(element);
2071 if (graphic >= GFX_START_ROCKSSP && graphic <= GFX_END_ROCKSSP)
2073 graphic -= GFX_START_ROCKSSP;
2074 BlitBitmap(pix[PIX_SP], drawto,
2075 MICRO_SP_STARTX + (graphic % MICRO_SP_PER_LINE) * MICRO_TILEX,
2076 MICRO_SP_STARTY + (graphic / MICRO_SP_PER_LINE) * MICRO_TILEY,
2077 MICRO_TILEX, MICRO_TILEY, xpos, ypos);
2079 else if (graphic >= GFX_START_ROCKSDC && graphic <= GFX_END_ROCKSDC)
2081 graphic -= GFX_START_ROCKSDC;
2082 BlitBitmap(pix[PIX_DC], drawto,
2083 MICRO_DC_STARTX + (graphic % MICRO_DC_PER_LINE) * MICRO_TILEX,
2084 MICRO_DC_STARTY + (graphic / MICRO_DC_PER_LINE) * MICRO_TILEY,
2085 MICRO_TILEX, MICRO_TILEY, xpos, ypos);
2087 else if (graphic >= GFX_START_ROCKSMORE && graphic <= GFX_END_ROCKSMORE)
2089 graphic -= GFX_START_ROCKSMORE;
2090 BlitBitmap(pix[PIX_MORE], drawto,
2091 MICRO_MORE_STARTX + (graphic % MICRO_MORE_PER_LINE)*MICRO_TILEX,
2092 MICRO_MORE_STARTY + (graphic / MICRO_MORE_PER_LINE)*MICRO_TILEY,
2093 MICRO_TILEX, MICRO_TILEY, xpos, ypos);
2095 else if (graphic >= GFX_CHAR_START && graphic <= GFX_CHAR_END)
2097 graphic -= GFX_CHAR_START;
2098 BlitBitmap(pix[PIX_FONT_EM], drawto,
2099 MICRO_FONT_STARTX + (graphic % MICRO_GFX_PER_LINE)* MICRO_TILEX,
2100 MICRO_FONT_STARTY + (graphic / MICRO_GFX_PER_LINE)* MICRO_TILEY,
2101 MICRO_TILEX, MICRO_TILEY, xpos, ypos);
2104 BlitBitmap(pix[PIX_ELEMENTS], drawto,
2105 MICRO_GFX_STARTX + (graphic % MICRO_GFX_PER_LINE) * MICRO_TILEX,
2106 MICRO_GFX_STARTY + (graphic / MICRO_GFX_PER_LINE) * MICRO_TILEY,
2107 MICRO_TILEX, MICRO_TILEY, xpos, ypos);
2116 for(x=BX1; x<=BX2; x++)
2117 for(y=BY1; y<=BY2; y++)
2118 DrawNewScreenField(x, y);
2120 redraw_mask |= REDRAW_FIELD;
2123 void DrawMiniLevel(int size_x, int size_y, int scroll_x, int scroll_y)
2127 for(x=0; x<size_x; x++)
2128 for(y=0; y<size_y; y++)
2129 DrawMiniElementOrWall(x, y, scroll_x, scroll_y);
2131 redraw_mask |= REDRAW_FIELD;
2134 static void DrawMicroLevelExt(int xpos, int ypos, int from_x, int from_y)
2138 ClearRectangle(drawto, xpos, ypos, MICROLEV_XSIZE, MICROLEV_YSIZE);
2140 if (lev_fieldx < STD_LEV_FIELDX)
2141 xpos += (STD_LEV_FIELDX - lev_fieldx) / 2 * MICRO_TILEX;
2142 if (lev_fieldy < STD_LEV_FIELDY)
2143 ypos += (STD_LEV_FIELDY - lev_fieldy) / 2 * MICRO_TILEY;
2145 xpos += MICRO_TILEX;
2146 ypos += MICRO_TILEY;
2148 for(x=-1; x<=STD_LEV_FIELDX; x++)
2150 for(y=-1; y<=STD_LEV_FIELDY; y++)
2152 int lx = from_x + x, ly = from_y + y;
2154 if (lx >= 0 && lx < lev_fieldx && ly >= 0 && ly < lev_fieldy)
2155 DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
2157 else if (lx >= -1 && lx < lev_fieldx+1 && ly >= -1 && ly < lev_fieldy+1)
2158 DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
2163 redraw_mask |= REDRAW_MICROLEVEL;
2166 #define MICROLABEL_EMPTY 0
2167 #define MICROLABEL_LEVEL_NAME 1
2168 #define MICROLABEL_CREATED_BY 2
2169 #define MICROLABEL_LEVEL_AUTHOR 3
2170 #define MICROLABEL_IMPORTED_FROM 4
2171 #define MICROLABEL_LEVEL_IMPORT_INFO 5
2173 #define MAX_MICROLABEL_SIZE (SXSIZE / FONT4_XSIZE)
2175 static void DrawMicroLevelLabelExt(int mode)
2177 char label_text[MAX_MICROLABEL_SIZE + 1];
2179 ClearRectangle(drawto, SX, MICROLABEL_YPOS, SXSIZE, FONT4_YSIZE);
2181 strncpy(label_text, (mode == MICROLABEL_LEVEL_NAME ? level.name :
2182 mode == MICROLABEL_CREATED_BY ? "created by" :
2183 mode == MICROLABEL_LEVEL_AUTHOR ? level.author :
2184 mode == MICROLABEL_IMPORTED_FROM ? "imported from" :
2185 mode == MICROLABEL_LEVEL_IMPORT_INFO ?
2186 leveldir_current->imported_from : ""),
2187 MAX_MICROLABEL_SIZE);
2188 label_text[MAX_MICROLABEL_SIZE] = '\0';
2190 if (strlen(label_text) > 0)
2192 int lxpos = SX + (SXSIZE - strlen(label_text) * FONT4_XSIZE) / 2;
2193 int lypos = MICROLABEL_YPOS;
2195 DrawText(lxpos, lypos, label_text, FS_SMALL, FC_SPECIAL2);
2198 redraw_mask |= REDRAW_MICROLEVEL;
2201 void DrawMicroLevel(int xpos, int ypos, boolean restart)
2203 static unsigned long scroll_delay = 0;
2204 static unsigned long label_delay = 0;
2205 static int from_x, from_y, scroll_direction;
2206 static int label_state, label_counter;
2210 from_x = from_y = 0;
2211 scroll_direction = MV_RIGHT;
2215 DrawMicroLevelExt(xpos, ypos, from_x, from_y);
2216 DrawMicroLevelLabelExt(label_state);
2218 /* initialize delay counters */
2219 DelayReached(&scroll_delay, 0);
2220 DelayReached(&label_delay, 0);
2225 /* scroll micro level, if needed */
2226 if ((lev_fieldx > STD_LEV_FIELDX || lev_fieldy > STD_LEV_FIELDY) &&
2227 DelayReached(&scroll_delay, MICROLEVEL_SCROLL_DELAY))
2229 switch (scroll_direction)
2235 scroll_direction = MV_UP;
2239 if (from_x < lev_fieldx - STD_LEV_FIELDX)
2242 scroll_direction = MV_DOWN;
2249 scroll_direction = MV_RIGHT;
2253 if (from_y < lev_fieldy - STD_LEV_FIELDY)
2256 scroll_direction = MV_LEFT;
2263 DrawMicroLevelExt(xpos, ypos, from_x, from_y);
2266 /* redraw micro level label, if needed */
2267 if (strcmp(level.name, NAMELESS_LEVEL_NAME) != 0 &&
2268 strcmp(level.author, ANONYMOUS_NAME) != 0 &&
2269 strcmp(level.author, leveldir_current->name) != 0 &&
2270 DelayReached(&label_delay, MICROLEVEL_LABEL_DELAY))
2272 int max_label_counter = 23;
2274 if (leveldir_current->imported_from != NULL)
2275 max_label_counter += 14;
2277 label_counter = (label_counter + 1) % max_label_counter;
2278 label_state = (label_counter >= 0 && label_counter <= 7 ?
2279 MICROLABEL_LEVEL_NAME :
2280 label_counter >= 9 && label_counter <= 12 ?
2281 MICROLABEL_CREATED_BY :
2282 label_counter >= 14 && label_counter <= 21 ?
2283 MICROLABEL_LEVEL_AUTHOR :
2284 label_counter >= 23 && label_counter <= 26 ?
2285 MICROLABEL_IMPORTED_FROM :
2286 label_counter >= 28 && label_counter <= 35 ?
2287 MICROLABEL_LEVEL_IMPORT_INFO : MICROLABEL_EMPTY);
2288 DrawMicroLevelLabelExt(label_state);
2292 int REQ_in_range(int x, int y)
2294 if (y > DY+249 && y < DY+278)
2296 if (x > DX+1 && x < DX+48)
2298 else if (x > DX+51 && x < DX+98)
2304 #define MAX_REQUEST_LINES 13
2305 #define MAX_REQUEST_LINE_LEN 7
2307 boolean Request(char *text, unsigned int req_state)
2309 int mx, my, ty, result = -1;
2310 unsigned int old_door_state;
2312 #if defined(PLATFORM_UNIX)
2313 /* pause network game while waiting for request to answer */
2314 if (options.network &&
2315 game_status == PLAYING &&
2316 req_state & REQUEST_WAIT_FOR)
2317 SendToServer_PausePlaying();
2320 old_door_state = GetDoorState();
2324 CloseDoor(DOOR_CLOSE_1);
2326 /* save old door content */
2327 BlitBitmap(pix[PIX_DB_DOOR], pix[PIX_DB_DOOR],
2328 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE,
2329 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1);
2331 /* clear door drawing field */
2332 ClearRectangle(drawto, DX, DY, DXSIZE, DYSIZE);
2334 /* write text for request */
2335 for(ty=0; ty < MAX_REQUEST_LINES; ty++)
2337 char text_line[MAX_REQUEST_LINE_LEN + 1];
2343 for(tl=0,tx=0; tx < MAX_REQUEST_LINE_LEN; tl++,tx++)
2346 if (!tc || tc == ' ')
2357 strncpy(text_line, text, tl);
2360 DrawTextExt(drawto, DX + 50 - (tl * 14)/2, DY + 8 + ty * 16,
2361 text_line, FS_SMALL, FC_YELLOW);
2363 text += tl + (tc == ' ' ? 1 : 0);
2366 if (req_state & REQ_ASK)
2368 MapGadget(tool_gadget[TOOL_CTRL_ID_YES]);
2369 MapGadget(tool_gadget[TOOL_CTRL_ID_NO]);
2371 else if (req_state & REQ_CONFIRM)
2373 MapGadget(tool_gadget[TOOL_CTRL_ID_CONFIRM]);
2375 else if (req_state & REQ_PLAYER)
2377 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_1]);
2378 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_2]);
2379 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_3]);
2380 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_4]);
2383 /* copy request gadgets to door backbuffer */
2384 BlitBitmap(drawto, pix[PIX_DB_DOOR],
2385 DX, DY, DXSIZE, DYSIZE,
2386 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
2388 OpenDoor(DOOR_OPEN_1);
2394 if (!(req_state & REQUEST_WAIT_FOR))
2397 if (game_status != MAINMENU)
2400 button_status = MB_RELEASED;
2402 request_gadget_id = -1;
2414 case EVENT_BUTTONPRESS:
2415 case EVENT_BUTTONRELEASE:
2416 case EVENT_MOTIONNOTIFY:
2418 if (event.type == EVENT_MOTIONNOTIFY)
2420 if (!PointerInWindow(window))
2421 continue; /* window and pointer are on different screens */
2426 motion_status = TRUE;
2427 mx = ((MotionEvent *) &event)->x;
2428 my = ((MotionEvent *) &event)->y;
2432 motion_status = FALSE;
2433 mx = ((ButtonEvent *) &event)->x;
2434 my = ((ButtonEvent *) &event)->y;
2435 if (event.type == EVENT_BUTTONPRESS)
2436 button_status = ((ButtonEvent *) &event)->button;
2438 button_status = MB_RELEASED;
2441 /* this sets 'request_gadget_id' */
2442 HandleGadgets(mx, my, button_status);
2444 switch(request_gadget_id)
2446 case TOOL_CTRL_ID_YES:
2449 case TOOL_CTRL_ID_NO:
2452 case TOOL_CTRL_ID_CONFIRM:
2453 result = TRUE | FALSE;
2456 case TOOL_CTRL_ID_PLAYER_1:
2459 case TOOL_CTRL_ID_PLAYER_2:
2462 case TOOL_CTRL_ID_PLAYER_3:
2465 case TOOL_CTRL_ID_PLAYER_4:
2476 case EVENT_KEYPRESS:
2477 switch(GetEventKey((KeyEvent *)&event, TRUE))
2490 if (req_state & REQ_PLAYER)
2494 case EVENT_KEYRELEASE:
2495 ClearPlayerAction();
2499 HandleOtherEvents(&event);
2503 else if (AnyJoystickButton() == JOY_BUTTON_NEW_PRESSED)
2505 int joy = AnyJoystick();
2507 if (joy & JOY_BUTTON_1)
2509 else if (joy & JOY_BUTTON_2)
2515 /* don't eat all CPU time */
2519 if (game_status != MAINMENU)
2524 if (!(req_state & REQ_STAY_OPEN))
2526 CloseDoor(DOOR_CLOSE_1);
2528 if (!(req_state & REQ_STAY_CLOSED) && (old_door_state & DOOR_OPEN_1))
2530 BlitBitmap(pix[PIX_DB_DOOR], pix[PIX_DB_DOOR],
2531 DOOR_GFX_PAGEX2,DOOR_GFX_PAGEY1, DXSIZE,DYSIZE,
2532 DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY1);
2533 OpenDoor(DOOR_OPEN_1);
2539 #if defined(PLATFORM_UNIX)
2540 /* continue network game after request */
2541 if (options.network &&
2542 game_status == PLAYING &&
2543 req_state & REQUEST_WAIT_FOR)
2544 SendToServer_ContinuePlaying();
2550 unsigned int OpenDoor(unsigned int door_state)
2552 unsigned int new_door_state;
2554 if (door_state & DOOR_COPY_BACK)
2556 BlitBitmap(pix[PIX_DB_DOOR], pix[PIX_DB_DOOR],
2557 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE + VYSIZE,
2558 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
2559 door_state &= ~DOOR_COPY_BACK;
2562 new_door_state = MoveDoor(door_state);
2564 return(new_door_state);
2567 unsigned int CloseDoor(unsigned int door_state)
2569 unsigned int new_door_state;
2571 BlitBitmap(backbuffer, pix[PIX_DB_DOOR],
2572 DX, DY, DXSIZE, DYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
2573 BlitBitmap(backbuffer, pix[PIX_DB_DOOR],
2574 VX, VY, VXSIZE, VYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2);
2576 new_door_state = MoveDoor(door_state);
2578 return(new_door_state);
2581 unsigned int GetDoorState()
2583 return MoveDoor(DOOR_GET_STATE);
2586 unsigned int SetDoorState(unsigned int door_state)
2588 return MoveDoor(door_state | DOOR_SET_STATE);
2591 unsigned int MoveDoor(unsigned int door_state)
2593 static int door1 = DOOR_OPEN_1;
2594 static int door2 = DOOR_CLOSE_2;
2595 static unsigned long door_delay = 0;
2596 int x, start, stepsize = 2;
2597 unsigned long door_delay_value = stepsize * 5;
2599 if (door_state == DOOR_GET_STATE)
2600 return(door1 | door2);
2602 if (door_state & DOOR_SET_STATE)
2604 if (door_state & DOOR_ACTION_1)
2605 door1 = door_state & DOOR_ACTION_1;
2606 if (door_state & DOOR_ACTION_2)
2607 door2 = door_state & DOOR_ACTION_2;
2609 return(door1 | door2);
2612 if (door1 == DOOR_OPEN_1 && door_state & DOOR_OPEN_1)
2613 door_state &= ~DOOR_OPEN_1;
2614 else if (door1 == DOOR_CLOSE_1 && door_state & DOOR_CLOSE_1)
2615 door_state &= ~DOOR_CLOSE_1;
2616 if (door2 == DOOR_OPEN_2 && door_state & DOOR_OPEN_2)
2617 door_state &= ~DOOR_OPEN_2;
2618 else if (door2 == DOOR_CLOSE_2 && door_state & DOOR_CLOSE_2)
2619 door_state &= ~DOOR_CLOSE_2;
2621 if (setup.quick_doors)
2624 door_delay_value = 0;
2625 StopSound(SND_MENU_DOOR_OPENING);
2626 StopSound(SND_MENU_DOOR_CLOSING);
2629 if (door_state & DOOR_ACTION)
2631 if (!(door_state & DOOR_NO_DELAY))
2633 /* opening door sound has priority over simultaneously closing door */
2634 if (door_state & (DOOR_OPEN_1 | DOOR_OPEN_2))
2635 PlaySoundStereo(SND_MENU_DOOR_OPENING, SOUND_MAX_RIGHT);
2636 else if (door_state & (DOOR_CLOSE_1 | DOOR_CLOSE_2))
2637 PlaySoundStereo(SND_MENU_DOOR_CLOSING, SOUND_MAX_RIGHT);
2640 start = ((door_state & DOOR_NO_DELAY) ? DXSIZE : 0);
2642 for(x=start; x<=DXSIZE; x+=stepsize)
2644 Bitmap *bitmap = pix[PIX_DOOR];
2645 GC gc = bitmap->stored_clip_gc;
2647 WaitUntilDelayReached(&door_delay, door_delay_value);
2649 if (door_state & DOOR_ACTION_1)
2651 int i = (door_state & DOOR_OPEN_1 ? DXSIZE-x : x);
2652 int j = (DXSIZE - i) / 3;
2654 BlitBitmap(pix[PIX_DB_DOOR], drawto,
2655 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1 + i/2,
2656 DXSIZE,DYSIZE - i/2, DX, DY);
2658 ClearRectangle(drawto, DX, DY + DYSIZE - i/2, DXSIZE,i/2);
2660 SetClipOrigin(bitmap, gc, DX - i, (DY + j) - DOOR_GFX_PAGEY1);
2661 BlitBitmapMasked(bitmap, drawto,
2662 DXSIZE, DOOR_GFX_PAGEY1, i, 77,
2663 DX + DXSIZE - i, DY + j);
2664 BlitBitmapMasked(bitmap, drawto,
2665 DXSIZE, DOOR_GFX_PAGEY1 + 140, i, 63,
2666 DX + DXSIZE - i, DY + 140 + j);
2667 SetClipOrigin(bitmap, gc, DX - DXSIZE + i, DY - (DOOR_GFX_PAGEY1 + j));
2668 BlitBitmapMasked(bitmap, drawto,
2669 DXSIZE - i, DOOR_GFX_PAGEY1 + j, i, 77 - j,
2671 BlitBitmapMasked(bitmap, drawto,
2672 DXSIZE-i, DOOR_GFX_PAGEY1 + 140, i, 63,
2675 BlitBitmapMasked(bitmap, drawto,
2676 DXSIZE - i, DOOR_GFX_PAGEY1 + 77, i, 63,
2678 BlitBitmapMasked(bitmap, drawto,
2679 DXSIZE - i, DOOR_GFX_PAGEY1 + 203, i, 77,
2681 SetClipOrigin(bitmap, gc, DX - i, (DY + j) - DOOR_GFX_PAGEY1);
2682 BlitBitmapMasked(bitmap, drawto,
2683 DXSIZE, DOOR_GFX_PAGEY1 + 77, i, 63,
2684 DX + DXSIZE - i, DY + 77 + j);
2685 BlitBitmapMasked(bitmap, drawto,
2686 DXSIZE, DOOR_GFX_PAGEY1 + 203, i, 77 - j,
2687 DX + DXSIZE - i, DY + 203 + j);
2689 redraw_mask |= REDRAW_DOOR_1;
2692 if (door_state & DOOR_ACTION_2)
2694 int i = (door_state & DOOR_OPEN_2 ? VXSIZE - x : x);
2695 int j = (VXSIZE - i) / 3;
2697 BlitBitmap(pix[PIX_DB_DOOR], drawto,
2698 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2 + i/2,
2699 VXSIZE, VYSIZE - i/2, VX, VY);
2701 ClearRectangle(drawto, VX, VY + VYSIZE-i/2, VXSIZE, i/2);
2703 SetClipOrigin(bitmap, gc, VX - i, (VY + j) - DOOR_GFX_PAGEY2);
2704 BlitBitmapMasked(bitmap, drawto,
2705 VXSIZE, DOOR_GFX_PAGEY2, i, VYSIZE / 2,
2706 VX + VXSIZE-i, VY+j);
2707 SetClipOrigin(bitmap, gc,
2708 VX - VXSIZE + i, VY - (DOOR_GFX_PAGEY2 + j));
2709 BlitBitmapMasked(bitmap, drawto,
2710 VXSIZE - i, DOOR_GFX_PAGEY2 + j, i, VYSIZE / 2 - j,
2713 BlitBitmapMasked(bitmap, drawto,
2714 VXSIZE - i, DOOR_GFX_PAGEY2 + VYSIZE / 2,
2715 i, VYSIZE / 2, VX, VY + VYSIZE / 2 - j);
2716 SetClipOrigin(bitmap, gc, VX - i, (VY + j) - DOOR_GFX_PAGEY2);
2717 BlitBitmapMasked(bitmap, drawto,
2718 VXSIZE, DOOR_GFX_PAGEY2 + VYSIZE / 2,
2720 VX + VXSIZE - i, VY + VYSIZE / 2 + j);
2722 redraw_mask |= REDRAW_DOOR_2;
2727 if (game_status == MAINMENU)
2732 if (setup.quick_doors)
2734 StopSound(SND_MENU_DOOR_OPENING);
2735 StopSound(SND_MENU_DOOR_CLOSING);
2738 if (door_state & DOOR_ACTION_1)
2739 door1 = door_state & DOOR_ACTION_1;
2740 if (door_state & DOOR_ACTION_2)
2741 door2 = door_state & DOOR_ACTION_2;
2743 return (door1 | door2);
2746 void DrawSpecialEditorDoor()
2748 /* draw bigger toolbox window */
2749 BlitBitmap(pix[PIX_DOOR], drawto,
2750 DOOR_GFX_PAGEX7, 0, 108, 56, EX - 4, EY - 12);
2752 redraw_mask |= REDRAW_ALL;
2755 void UndrawSpecialEditorDoor()
2757 /* draw normal tape recorder window */
2758 BlitBitmap(pix[PIX_BACK], drawto,
2759 562, 344, 108, 56, EX - 4, EY - 12);
2761 redraw_mask |= REDRAW_ALL;
2765 int ReadPixel(DrawBuffer *bitmap, int x, int y)
2767 XImage *pixel_image;
2768 unsigned long pixel_value;
2770 pixel_image = XGetImage(display, bitmap->drawable,
2771 x, y, 1, 1, AllPlanes, ZPixmap);
2772 pixel_value = XGetPixel(pixel_image, 0, 0);
2774 XDestroyImage(pixel_image);
2780 /* ---------- new tool button stuff ---------------------------------------- */
2782 /* graphic position values for tool buttons */
2783 #define TOOL_BUTTON_YES_XPOS 2
2784 #define TOOL_BUTTON_YES_YPOS 250
2785 #define TOOL_BUTTON_YES_GFX_YPOS 0
2786 #define TOOL_BUTTON_YES_XSIZE 46
2787 #define TOOL_BUTTON_YES_YSIZE 28
2788 #define TOOL_BUTTON_NO_XPOS 52
2789 #define TOOL_BUTTON_NO_YPOS TOOL_BUTTON_YES_YPOS
2790 #define TOOL_BUTTON_NO_GFX_YPOS TOOL_BUTTON_YES_GFX_YPOS
2791 #define TOOL_BUTTON_NO_XSIZE TOOL_BUTTON_YES_XSIZE
2792 #define TOOL_BUTTON_NO_YSIZE TOOL_BUTTON_YES_YSIZE
2793 #define TOOL_BUTTON_CONFIRM_XPOS TOOL_BUTTON_YES_XPOS
2794 #define TOOL_BUTTON_CONFIRM_YPOS TOOL_BUTTON_YES_YPOS
2795 #define TOOL_BUTTON_CONFIRM_GFX_YPOS 30
2796 #define TOOL_BUTTON_CONFIRM_XSIZE 96
2797 #define TOOL_BUTTON_CONFIRM_YSIZE TOOL_BUTTON_YES_YSIZE
2798 #define TOOL_BUTTON_PLAYER_XSIZE 30
2799 #define TOOL_BUTTON_PLAYER_YSIZE 30
2800 #define TOOL_BUTTON_PLAYER_GFX_XPOS 5
2801 #define TOOL_BUTTON_PLAYER_GFX_YPOS 185
2802 #define TOOL_BUTTON_PLAYER_XPOS (5 + TOOL_BUTTON_PLAYER_XSIZE / 2)
2803 #define TOOL_BUTTON_PLAYER_YPOS (215 - TOOL_BUTTON_PLAYER_YSIZE / 2)
2804 #define TOOL_BUTTON_PLAYER1_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2805 + 0 * TOOL_BUTTON_PLAYER_XSIZE)
2806 #define TOOL_BUTTON_PLAYER2_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2807 + 1 * TOOL_BUTTON_PLAYER_XSIZE)
2808 #define TOOL_BUTTON_PLAYER3_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2809 + 0 * TOOL_BUTTON_PLAYER_XSIZE)
2810 #define TOOL_BUTTON_PLAYER4_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2811 + 1 * TOOL_BUTTON_PLAYER_XSIZE)
2812 #define TOOL_BUTTON_PLAYER1_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2813 + 0 * TOOL_BUTTON_PLAYER_YSIZE)
2814 #define TOOL_BUTTON_PLAYER2_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2815 + 0 * TOOL_BUTTON_PLAYER_YSIZE)
2816 #define TOOL_BUTTON_PLAYER3_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2817 + 1 * TOOL_BUTTON_PLAYER_YSIZE)
2818 #define TOOL_BUTTON_PLAYER4_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2819 + 1 * TOOL_BUTTON_PLAYER_YSIZE)
2828 } toolbutton_info[NUM_TOOL_BUTTONS] =
2831 TOOL_BUTTON_YES_XPOS, TOOL_BUTTON_YES_GFX_YPOS,
2832 TOOL_BUTTON_YES_XPOS, TOOL_BUTTON_YES_YPOS,
2833 TOOL_BUTTON_YES_XSIZE, TOOL_BUTTON_YES_YSIZE,
2838 TOOL_BUTTON_NO_XPOS, TOOL_BUTTON_NO_GFX_YPOS,
2839 TOOL_BUTTON_NO_XPOS, TOOL_BUTTON_NO_YPOS,
2840 TOOL_BUTTON_NO_XSIZE, TOOL_BUTTON_NO_YSIZE,
2845 TOOL_BUTTON_CONFIRM_XPOS, TOOL_BUTTON_CONFIRM_GFX_YPOS,
2846 TOOL_BUTTON_CONFIRM_XPOS, TOOL_BUTTON_CONFIRM_YPOS,
2847 TOOL_BUTTON_CONFIRM_XSIZE, TOOL_BUTTON_CONFIRM_YSIZE,
2848 TOOL_CTRL_ID_CONFIRM,
2852 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2853 TOOL_BUTTON_PLAYER1_XPOS, TOOL_BUTTON_PLAYER1_YPOS,
2854 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2855 TOOL_CTRL_ID_PLAYER_1,
2859 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2860 TOOL_BUTTON_PLAYER2_XPOS, TOOL_BUTTON_PLAYER2_YPOS,
2861 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2862 TOOL_CTRL_ID_PLAYER_2,
2866 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2867 TOOL_BUTTON_PLAYER3_XPOS, TOOL_BUTTON_PLAYER3_YPOS,
2868 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2869 TOOL_CTRL_ID_PLAYER_3,
2873 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2874 TOOL_BUTTON_PLAYER4_XPOS, TOOL_BUTTON_PLAYER4_YPOS,
2875 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2876 TOOL_CTRL_ID_PLAYER_4,
2881 void CreateToolButtons()
2885 for (i=0; i<NUM_TOOL_BUTTONS; i++)
2887 Bitmap *gd_bitmap = pix[PIX_DOOR];
2888 Bitmap *deco_bitmap = None;
2889 int deco_x = 0, deco_y = 0, deco_xpos = 0, deco_ypos = 0;
2890 struct GadgetInfo *gi;
2891 unsigned long event_mask;
2892 int gd_xoffset, gd_yoffset;
2893 int gd_x1, gd_x2, gd_y;
2896 event_mask = GD_EVENT_RELEASED;
2898 gd_xoffset = toolbutton_info[i].xpos;
2899 gd_yoffset = toolbutton_info[i].ypos;
2900 gd_x1 = DOOR_GFX_PAGEX4 + gd_xoffset;
2901 gd_x2 = DOOR_GFX_PAGEX3 + gd_xoffset;
2902 gd_y = DOOR_GFX_PAGEY1 + gd_yoffset;
2904 if (id >= TOOL_CTRL_ID_PLAYER_1 && id <= TOOL_CTRL_ID_PLAYER_4)
2906 getMiniGraphicSource(GFX_SPIELER1 + id - TOOL_CTRL_ID_PLAYER_1,
2907 &deco_bitmap, &deco_x, &deco_y);
2908 deco_xpos = (toolbutton_info[i].width - MINI_TILEX) / 2;
2909 deco_ypos = (toolbutton_info[i].height - MINI_TILEY) / 2;
2912 gi = CreateGadget(GDI_CUSTOM_ID, id,
2913 GDI_INFO_TEXT, toolbutton_info[i].infotext,
2914 GDI_X, DX + toolbutton_info[i].x,
2915 GDI_Y, DY + toolbutton_info[i].y,
2916 GDI_WIDTH, toolbutton_info[i].width,
2917 GDI_HEIGHT, toolbutton_info[i].height,
2918 GDI_TYPE, GD_TYPE_NORMAL_BUTTON,
2919 GDI_STATE, GD_BUTTON_UNPRESSED,
2920 GDI_DESIGN_UNPRESSED, gd_bitmap, gd_x1, gd_y,
2921 GDI_DESIGN_PRESSED, gd_bitmap, gd_x2, gd_y,
2922 GDI_DECORATION_DESIGN, deco_bitmap, deco_x, deco_y,
2923 GDI_DECORATION_POSITION, deco_xpos, deco_ypos,
2924 GDI_DECORATION_SIZE, MINI_TILEX, MINI_TILEY,
2925 GDI_DECORATION_SHIFTING, 1, 1,
2926 GDI_EVENT_MASK, event_mask,
2927 GDI_CALLBACK_ACTION, HandleToolButtons,
2931 Error(ERR_EXIT, "cannot create gadget");
2933 tool_gadget[id] = gi;
2937 static void UnmapToolButtons()
2941 for (i=0; i<NUM_TOOL_BUTTONS; i++)
2942 UnmapGadget(tool_gadget[i]);
2945 static void HandleToolButtons(struct GadgetInfo *gi)
2947 request_gadget_id = gi->custom_id;
2950 int get_next_element(int element)
2954 case EL_QUICKSAND_FILLING: return EL_QUICKSAND_FULL;
2955 case EL_QUICKSAND_EMPTYING: return EL_QUICKSAND_EMPTY;
2956 case EL_MAGIC_WALL_FILLING: return EL_MAGIC_WALL_FULL;
2957 case EL_MAGIC_WALL_EMPTYING: return EL_MAGIC_WALL_ACTIVE;
2958 case EL_BD_MAGIC_WALL_FILLING: return EL_BD_MAGIC_WALL_FULL;
2959 case EL_BD_MAGIC_WALL_EMPTYING: return EL_BD_MAGIC_WALL_ACTIVE;
2960 case EL_AMOEBA_DRIPPING: return EL_AMOEBA_WET;
2962 default: return element;
2966 int el2gfx_OLD(int element)
2970 case EL_EMPTY: return -1;
2971 case EL_SAND: return GFX_ERDREICH;
2972 case EL_WALL: return GFX_MAUERWERK;
2973 case EL_WALL_CRUMBLED: return GFX_FELSBODEN;
2974 case EL_ROCK: return GFX_FELSBROCKEN;
2975 case EL_EMERALD: return GFX_EDELSTEIN;
2976 case EL_EXIT_CLOSED: return GFX_AUSGANG_ZU;
2977 case EL_EXIT_OPENING: return GFX_AUSGANG_ACT;
2978 case EL_EXIT_OPEN: return GFX_AUSGANG_AUF;
2979 case EL_SP_EXIT_OPEN: return GFX_SP_EXIT;
2980 case EL_PLAYER1: return GFX_SPIELER1;
2981 case EL_PLAYER2: return GFX_SPIELER2;
2982 case EL_PLAYER3: return GFX_SPIELER3;
2983 case EL_PLAYER4: return GFX_SPIELER4;
2984 case EL_BUG: return GFX_KAEFER;
2985 case EL_BUG_RIGHT: return GFX_KAEFER_RIGHT;
2986 case EL_BUG_UP: return GFX_KAEFER_UP;
2987 case EL_BUG_LEFT: return GFX_KAEFER_LEFT;
2988 case EL_BUG_DOWN: return GFX_KAEFER_DOWN;
2989 case EL_SPACESHIP: return GFX_FLIEGER;
2990 case EL_SPACESHIP_RIGHT: return GFX_FLIEGER_RIGHT;
2991 case EL_SPACESHIP_UP: return GFX_FLIEGER_UP;
2992 case EL_SPACESHIP_LEFT: return GFX_FLIEGER_LEFT;
2993 case EL_SPACESHIP_DOWN: return GFX_FLIEGER_DOWN;
2994 case EL_BD_BUTTERFLY: return GFX_BUTTERFLY;
2995 case EL_BD_BUTTERFLY_RIGHT: return GFX_BUTTERFLY_RIGHT;
2996 case EL_BD_BUTTERFLY_UP: return GFX_BUTTERFLY_UP;
2997 case EL_BD_BUTTERFLY_LEFT: return GFX_BUTTERFLY_LEFT;
2998 case EL_BD_BUTTERFLY_DOWN: return GFX_BUTTERFLY_DOWN;
2999 case EL_BD_FIREFLY: return GFX_FIREFLY;
3000 case EL_BD_FIREFLY_RIGHT: return GFX_FIREFLY_RIGHT;
3001 case EL_BD_FIREFLY_UP: return GFX_FIREFLY_UP;
3002 case EL_BD_FIREFLY_LEFT: return GFX_FIREFLY_LEFT;
3003 case EL_BD_FIREFLY_DOWN: return GFX_FIREFLY_DOWN;
3004 case EL_YAMYAM: return GFX_MAMPFER;
3005 case EL_ROBOT: return GFX_ROBOT;
3006 case EL_STEELWALL: return GFX_BETON;
3007 case EL_DIAMOND: return GFX_DIAMANT;
3008 case EL_QUICKSAND_EMPTY: return GFX_MORAST_LEER;
3009 case EL_QUICKSAND_FULL: return GFX_MORAST_VOLL;
3010 case EL_QUICKSAND_EMPTYING: return GFX_MORAST_LEER;
3011 case EL_AMOEBA_DROP: return GFX_TROPFEN;
3012 case EL_BOMB: return GFX_BOMBE;
3013 case EL_MAGIC_WALL: return GFX_MAGIC_WALL_OFF;
3014 case EL_MAGIC_WALL_ACTIVE: return GFX_MAGIC_WALL_EMPTY;
3015 case EL_MAGIC_WALL_EMPTYING: return GFX_MAGIC_WALL_EMPTY;
3016 case EL_MAGIC_WALL_FULL: return GFX_MAGIC_WALL_FULL;
3017 case EL_MAGIC_WALL_DEAD: return GFX_MAGIC_WALL_DEAD;
3018 case EL_ACID: return GFX_SALZSAEURE;
3019 case EL_AMOEBA_DEAD: return GFX_AMOEBE_TOT;
3020 case EL_AMOEBA_WET: return GFX_AMOEBE_NASS;
3021 case EL_AMOEBA_DRY: return GFX_AMOEBE_NORM;
3022 case EL_AMOEBA_FULL: return GFX_AMOEBE_VOLL;
3023 case EL_BD_AMOEBA: return GFX_AMOEBE_BD;
3024 case EL_AMOEBA_TO_DIAMOND: return GFX_AMOEBA2DIAM;
3025 case EL_AMOEBA_DRIPPING: return GFX_AMOEBE_NASS;
3026 case EL_NUT: return GFX_KOKOSNUSS;
3027 case EL_GAMEOFLIFE: return GFX_LIFE;
3028 case EL_BIOMAZE: return GFX_LIFE_ASYNC;
3029 case EL_DYNAMITE_ACTIVE: return GFX_DYNAMIT;
3030 case EL_STONEBLOCK: return GFX_BADEWANNE;
3031 case EL_ACIDPOOL_TOPLEFT: return GFX_BADEWANNE1;
3032 case EL_ACIDPOOL_TOPRIGHT: return GFX_BADEWANNE2;
3033 case EL_ACIDPOOL_BOTTOMLEFT: return GFX_BADEWANNE3;
3034 case EL_ACIDPOOL_BOTTOM: return GFX_BADEWANNE4;
3035 case EL_ACIDPOOL_BOTTOMRIGHT: return GFX_BADEWANNE5;
3036 case EL_ROBOT_WHEEL: return GFX_ABLENK_AUS;
3037 case EL_ROBOT_WHEEL_ACTIVE: return GFX_ABLENK_EIN;
3038 case EL_KEY1: return GFX_SCHLUESSEL1;
3039 case EL_KEY2: return GFX_SCHLUESSEL2;
3040 case EL_KEY3: return GFX_SCHLUESSEL3;
3041 case EL_KEY4: return GFX_SCHLUESSEL4;
3042 case EL_GATE1: return GFX_PFORTE1;
3043 case EL_GATE2: return GFX_PFORTE2;
3044 case EL_GATE3: return GFX_PFORTE3;
3045 case EL_GATE4: return GFX_PFORTE4;
3046 case EL_GATE1_GRAY: return GFX_PFORTE1X;
3047 case EL_GATE2_GRAY: return GFX_PFORTE2X;
3048 case EL_GATE3_GRAY: return GFX_PFORTE3X;
3049 case EL_GATE4_GRAY: return GFX_PFORTE4X;
3050 case EL_DYNAMITE: return GFX_DYNAMIT_AUS;
3051 case EL_PACMAN: return GFX_PACMAN;
3052 case EL_PACMAN_RIGHT: return GFX_PACMAN_RIGHT;
3053 case EL_PACMAN_UP: return GFX_PACMAN_UP;
3054 case EL_PACMAN_LEFT: return GFX_PACMAN_LEFT;
3055 case EL_PACMAN_DOWN: return GFX_PACMAN_DOWN;
3056 case EL_INVISIBLE_WALL: return GFX_UNSICHTBAR;
3057 case EL_INVISIBLE_WALL_ACTIVE: return GFX_UNSICHTBAR_ON;
3058 case EL_WALL_EMERALD: return GFX_ERZ_EDEL;
3059 case EL_WALL_DIAMOND: return GFX_ERZ_DIAM;
3060 case EL_LAMP: return GFX_BIRNE_AUS;
3061 case EL_LAMP_ACTIVE: return GFX_BIRNE_EIN;
3062 case EL_TIME_ORB_FULL: return GFX_ZEIT_VOLL;
3063 case EL_TIME_ORB_EMPTY: return GFX_ZEIT_LEER;
3064 case EL_WALL_GROWING: return GFX_MAUER_LEBT;
3065 case EL_WALL_GROWING_X: return GFX_MAUER_X;
3066 case EL_WALL_GROWING_Y: return GFX_MAUER_Y;
3067 case EL_WALL_GROWING_XY: return GFX_MAUER_XY;
3068 case EL_BD_DIAMOND: return GFX_EDELSTEIN_BD;
3069 case EL_EMERALD_YELLOW: return GFX_EDELSTEIN_GELB;
3070 case EL_EMERALD_RED: return GFX_EDELSTEIN_ROT;
3071 case EL_EMERALD_PURPLE: return GFX_EDELSTEIN_LILA;
3072 case EL_WALL_BD_DIAMOND: return GFX_ERZ_EDEL_BD;
3073 case EL_WALL_EMERALD_YELLOW: return GFX_ERZ_EDEL_GELB;
3074 case EL_WALL_EMERALD_RED: return GFX_ERZ_EDEL_ROT;
3075 case EL_WALL_EMERALD_PURPLE: return GFX_ERZ_EDEL_LILA;
3076 case EL_DARK_YAMYAM: return GFX_MAMPFER2;
3077 case EL_BD_MAGIC_WALL: return GFX_MAGIC_WALL_BD_OFF;
3078 case EL_BD_MAGIC_WALL_ACTIVE: return GFX_MAGIC_WALL_BD_EMPTY;
3079 case EL_BD_MAGIC_WALL_EMPTYING: return GFX_MAGIC_WALL_BD_EMPTY;
3080 case EL_BD_MAGIC_WALL_FULL: return GFX_MAGIC_WALL_BD_FULL;
3081 case EL_BD_MAGIC_WALL_DEAD: return GFX_MAGIC_WALL_BD_DEAD;
3082 case EL_DYNABOMB_PLAYER1_ACTIVE: return GFX_DYNABOMB;
3083 case EL_DYNABOMB_PLAYER2_ACTIVE: return GFX_DYNABOMB;
3084 case EL_DYNABOMB_PLAYER3_ACTIVE: return GFX_DYNABOMB;
3085 case EL_DYNABOMB_PLAYER4_ACTIVE: return GFX_DYNABOMB;
3086 case EL_DYNABOMB_NR: return GFX_DYNABOMB_NR;
3087 case EL_DYNABOMB_SZ: return GFX_DYNABOMB_SZ;
3088 case EL_DYNABOMB_XL: return GFX_DYNABOMB_XL;
3089 case EL_SOKOBAN_OBJECT: return GFX_SOKOBAN_OBJEKT;
3090 case EL_SOKOBAN_FIELD_EMPTY: return GFX_SOKOBAN_FELD_LEER;
3091 case EL_SOKOBAN_FIELD_FULL: return GFX_SOKOBAN_FELD_VOLL;
3092 case EL_MOLE: return GFX_MOLE;
3093 case EL_PENGUIN: return GFX_PINGUIN;
3094 case EL_PIG: return GFX_SCHWEIN;
3095 case EL_DRAGON: return GFX_DRACHE;
3096 case EL_SATELLITE: return GFX_SONDE;
3097 case EL_ARROW_BLUE_LEFT: return GFX_PFEIL_LEFT;
3098 case EL_ARROW_BLUE_RIGHT: return GFX_PFEIL_RIGHT;
3099 case EL_ARROW_BLUE_UP: return GFX_PFEIL_UP;
3100 case EL_ARROW_BLUE_DOWN: return GFX_PFEIL_DOWN;
3101 case EL_SPEED_PILL: return GFX_SPEED_PILL;
3102 case EL_SP_TERMINAL_ACTIVE: return GFX_SP_TERMINAL;
3103 case EL_SP_BUGGY_BASE_ACTIVE: return GFX_SP_BUG_ACTIVE;
3104 case EL_SP_ZONK: return GFX_SP_ZONK;
3105 /* ^^^^^^^^^^ non-standard position in supaplex graphic set! */
3106 case EL_INVISIBLE_STEELWALL: return GFX_INVISIBLE_STEEL;
3107 case EL_INVISIBLE_STEELWALL_ACTIVE: return GFX_INVISIBLE_STEEL_ON;
3108 case EL_BLACK_ORB: return GFX_BLACK_ORB;
3109 case EL_EM_GATE1: return GFX_EM_GATE_1;
3110 case EL_EM_GATE2: return GFX_EM_GATE_2;
3111 case EL_EM_GATE3: return GFX_EM_GATE_3;
3112 case EL_EM_GATE4: return GFX_EM_GATE_4;
3113 case EL_EM_GATE1_GRAY: return GFX_EM_GATE_1X;
3114 case EL_EM_GATE2_GRAY: return GFX_EM_GATE_2X;
3115 case EL_EM_GATE3_GRAY: return GFX_EM_GATE_3X;
3116 case EL_EM_GATE4_GRAY: return GFX_EM_GATE_4X;
3117 case EL_EM_KEY1_FILE: return GFX_EM_KEY_1;
3118 case EL_EM_KEY2_FILE: return GFX_EM_KEY_2;
3119 case EL_EM_KEY3_FILE: return GFX_EM_KEY_3;
3120 case EL_EM_KEY4_FILE: return GFX_EM_KEY_4;
3121 case EL_EM_KEY1: return GFX_EM_KEY_1;
3122 case EL_EM_KEY2: return GFX_EM_KEY_2;
3123 case EL_EM_KEY3: return GFX_EM_KEY_3;
3124 case EL_EM_KEY4: return GFX_EM_KEY_4;
3125 case EL_PEARL: return GFX_PEARL;
3126 case EL_CRYSTAL: return GFX_CRYSTAL;
3127 case EL_WALL_PEARL: return GFX_WALL_PEARL;
3128 case EL_WALL_CRYSTAL: return GFX_WALL_CRYSTAL;
3129 case EL_DOOR_WHITE: return GFX_DOOR_WHITE;
3130 case EL_DOOR_WHITE_GRAY: return GFX_DOOR_WHITE_GRAY;
3131 case EL_KEY_WHITE: return GFX_KEY_WHITE;
3132 case EL_SHIELD_NORMAL: return GFX_SHIELD_PASSIVE;
3133 case EL_SHIELD_DEADLY: return GFX_SHIELD_ACTIVE;
3134 case EL_EXTRA_TIME: return GFX_EXTRA_TIME;
3135 case EL_SWITCHGATE_OPEN: return GFX_SWITCHGATE_OPEN;
3136 case EL_SWITCHGATE_CLOSED: return GFX_SWITCHGATE_CLOSED;
3137 case EL_SWITCHGATE_SWITCH_UP: return GFX_SWITCHGATE_SWITCH_1;
3138 case EL_SWITCHGATE_SWITCH_DOWN: return GFX_SWITCHGATE_SWITCH_2;
3139 case EL_CONVEYOR_BELT1_LEFT: return GFX_BELT1_LEFT;
3140 case EL_CONVEYOR_BELT1_MIDDLE: return GFX_BELT1_MIDDLE;
3141 case EL_CONVEYOR_BELT1_RIGHT: return GFX_BELT1_RIGHT;
3142 case EL_CONVEYOR_BELT1_LEFT_ACTIVE: return GFX_BELT1_LEFT;
3143 case EL_CONVEYOR_BELT1_MIDDLE_ACTIVE:return GFX_BELT1_MIDDLE;
3144 case EL_CONVEYOR_BELT1_RIGHT_ACTIVE:return GFX_BELT1_RIGHT;
3145 case EL_CONVEYOR_BELT1_SWITCH_LEFT: return GFX_BELT1_SWITCH_LEFT;
3146 case EL_CONVEYOR_BELT1_SWITCH_MIDDLE:return GFX_BELT1_SWITCH_MIDDLE;
3147 case EL_CONVEYOR_BELT1_SWITCH_RIGHT:return GFX_BELT1_SWITCH_RIGHT;
3148 case EL_CONVEYOR_BELT2_LEFT: return GFX_BELT2_LEFT;
3149 case EL_CONVEYOR_BELT2_MIDDLE: return GFX_BELT2_MIDDLE;
3150 case EL_CONVEYOR_BELT2_RIGHT: return GFX_BELT2_RIGHT;
3151 case EL_CONVEYOR_BELT2_LEFT_ACTIVE: return GFX_BELT2_LEFT;
3152 case EL_CONVEYOR_BELT2_MIDDLE_ACTIVE:return GFX_BELT2_MIDDLE;
3153 case EL_CONVEYOR_BELT2_RIGHT_ACTIVE:return GFX_BELT2_RIGHT;
3154 case EL_CONVEYOR_BELT2_SWITCH_LEFT: return GFX_BELT2_SWITCH_LEFT;
3155 case EL_CONVEYOR_BELT2_SWITCH_MIDDLE:return GFX_BELT2_SWITCH_MIDDLE;
3156 case EL_CONVEYOR_BELT2_SWITCH_RIGHT:return GFX_BELT2_SWITCH_RIGHT;
3157 case EL_CONVEYOR_BELT3_LEFT: return GFX_BELT3_LEFT;
3158 case EL_CONVEYOR_BELT3_MIDDLE: return GFX_BELT3_MIDDLE;
3159 case EL_CONVEYOR_BELT3_RIGHT: return GFX_BELT3_RIGHT;
3160 case EL_CONVEYOR_BELT3_LEFT_ACTIVE: return GFX_BELT3_LEFT;
3161 case EL_CONVEYOR_BELT3_MIDDLE_ACTIVE:return GFX_BELT3_MIDDLE;
3162 case EL_CONVEYOR_BELT3_RIGHT_ACTIVE:return GFX_BELT3_RIGHT;
3163 case EL_CONVEYOR_BELT3_SWITCH_LEFT: return GFX_BELT3_SWITCH_LEFT;
3164 case EL_CONVEYOR_BELT3_SWITCH_MIDDLE:return GFX_BELT3_SWITCH_MIDDLE;
3165 case EL_CONVEYOR_BELT3_SWITCH_RIGHT:return GFX_BELT3_SWITCH_RIGHT;
3166 case EL_CONVEYOR_BELT4_LEFT: return GFX_BELT4_LEFT;
3167 case EL_CONVEYOR_BELT4_MIDDLE: return GFX_BELT4_MIDDLE;
3168 case EL_CONVEYOR_BELT4_RIGHT: return GFX_BELT4_RIGHT;
3169 case EL_CONVEYOR_BELT4_LEFT_ACTIVE: return GFX_BELT4_LEFT;
3170 case EL_CONVEYOR_BELT4_MIDDLE_ACTIVE:return GFX_BELT4_MIDDLE;
3171 case EL_CONVEYOR_BELT4_RIGHT_ACTIVE:return GFX_BELT4_RIGHT;
3172 case EL_CONVEYOR_BELT4_SWITCH_LEFT: return GFX_BELT4_SWITCH_LEFT;
3173 case EL_CONVEYOR_BELT4_SWITCH_MIDDLE:return GFX_BELT4_SWITCH_MIDDLE;
3174 case EL_CONVEYOR_BELT4_SWITCH_RIGHT:return GFX_BELT4_SWITCH_RIGHT;
3175 case EL_LANDMINE: return GFX_LANDMINE;
3176 case EL_ENVELOPE: return GFX_ENVELOPE;
3177 case EL_LIGHT_SWITCH: return GFX_LIGHT_SWITCH_OFF;
3178 case EL_LIGHT_SWITCH_ACTIVE: return GFX_LIGHT_SWITCH_ON;
3179 case EL_SIGN_EXCLAMATION: return GFX_SIGN_EXCLAMATION;
3180 case EL_SIGN_RADIOACTIVITY: return GFX_SIGN_RADIOACTIVITY;
3181 case EL_SIGN_STOP: return GFX_SIGN_STOP;
3182 case EL_SIGN_WHEELCHAIR: return GFX_SIGN_WHEELCHAIR;
3183 case EL_SIGN_PARKING: return GFX_SIGN_PARKING;
3184 case EL_SIGN_ONEWAY: return GFX_SIGN_ONEWAY;
3185 case EL_SIGN_HEART: return GFX_SIGN_HEART;
3186 case EL_SIGN_TRIANGLE: return GFX_SIGN_TRIANGLE;
3187 case EL_SIGN_ROUND: return GFX_SIGN_ROUND;
3188 case EL_SIGN_EXIT: return GFX_SIGN_EXIT;
3189 case EL_SIGN_YINYANG: return GFX_SIGN_YINYANG;
3190 case EL_SIGN_OTHER: return GFX_SIGN_OTHER;
3191 case EL_MOLE_LEFT: return GFX_MOLE_LEFT;
3192 case EL_MOLE_RIGHT: return GFX_MOLE_RIGHT;
3193 case EL_MOLE_UP: return GFX_MOLE_UP;
3194 case EL_MOLE_DOWN: return GFX_MOLE_DOWN;
3195 case EL_STEELWALL_SLANTED: return GFX_STEEL_SLANTED;
3196 case EL_INVISIBLE_SAND: return GFX_SAND_INVISIBLE;
3197 case EL_INVISIBLE_SAND_ACTIVE: return GFX_SAND_INVISIBLE_ON;
3198 case EL_DX_UNKNOWN_15: return GFX_DX_UNKNOWN_15;
3199 case EL_DX_UNKNOWN_42: return GFX_DX_UNKNOWN_42;
3200 case EL_TIMEGATE_OPEN: return GFX_TIMEGATE_OPEN;
3201 case EL_TIMEGATE_CLOSED: return GFX_TIMEGATE_CLOSED;
3202 case EL_TIMEGATE_SWITCH_ACTIVE: return GFX_TIMEGATE_SWITCH;
3203 case EL_TIMEGATE_SWITCH: return GFX_TIMEGATE_SWITCH;
3204 case EL_BALLOON: return GFX_BALLOON;
3205 case EL_BALLOON_SEND_LEFT: return GFX_BALLOON_SEND_LEFT;
3206 case EL_BALLOON_SEND_RIGHT: return GFX_BALLOON_SEND_RIGHT;
3207 case EL_BALLOON_SEND_UP: return GFX_BALLOON_SEND_UP;
3208 case EL_BALLOON_SEND_DOWN: return GFX_BALLOON_SEND_DOWN;
3209 case EL_BALLOON_SEND_ANY_DIRECTION: return GFX_BALLOON_SEND_ANY;
3210 case EL_EMC_STEELWALL1: return GFX_EMC_STEEL_WALL_1;
3211 case EL_EMC_STEELWALL2: return GFX_EMC_STEEL_WALL_2;
3212 case EL_EMC_STEELWALL3: return GFX_EMC_STEEL_WALL_3;
3213 case EL_EMC_STEELWALL4: return GFX_EMC_STEEL_WALL_4;
3214 case EL_EMC_WALL_PILLAR_UPPER: return GFX_EMC_WALL_1;
3215 case EL_EMC_WALL_PILLAR_MIDDLE: return GFX_EMC_WALL_2;
3216 case EL_EMC_WALL_PILLAR_LOWER: return GFX_EMC_WALL_3;
3217 case EL_EMC_WALL4: return GFX_EMC_WALL_4;
3218 case EL_EMC_WALL5: return GFX_EMC_WALL_5;
3219 case EL_EMC_WALL6: return GFX_EMC_WALL_6;
3220 case EL_EMC_WALL7: return GFX_EMC_WALL_7;
3221 case EL_EMC_WALL8: return GFX_EMC_WALL_8;
3222 case EL_TUBE_ALL: return GFX_TUBE_CROSS;
3223 case EL_TUBE_VERTICAL: return GFX_TUBE_VERTICAL;
3224 case EL_TUBE_HORIZONTAL: return GFX_TUBE_HORIZONTAL;
3225 case EL_TUBE_VERTICAL_LEFT: return GFX_TUBE_VERT_LEFT;
3226 case EL_TUBE_VERTICAL_RIGHT: return GFX_TUBE_VERT_RIGHT;
3227 case EL_TUBE_HORIZONTAL_UP: return GFX_TUBE_HORIZ_UP;
3228 case EL_TUBE_HORIZONTAL_DOWN: return GFX_TUBE_HORIZ_DOWN;
3229 case EL_TUBE_LEFT_UP: return GFX_TUBE_LEFT_UP;
3230 case EL_TUBE_LEFT_DOWN: return GFX_TUBE_LEFT_DOWN;
3231 case EL_TUBE_RIGHT_UP: return GFX_TUBE_RIGHT_UP;
3232 case EL_TUBE_RIGHT_DOWN: return GFX_TUBE_RIGHT_DOWN;
3233 case EL_SPRING: return GFX_SPRING;
3234 case EL_SPRING_MOVING: return GFX_SPRING;
3235 case EL_TRAP: return GFX_TRAP_INACTIVE;
3236 case EL_TRAP_ACTIVE: return GFX_TRAP_ACTIVE;
3237 case EL_BD_WALL: return GFX_BD_WALL;
3238 case EL_BD_ROCK: return GFX_BD_ROCK;
3239 case EL_DX_SUPABOMB: return GFX_DX_SUPABOMB;
3240 case EL_SP_MURPHY_CLONE: return GFX_SP_MURPHY_CLONE;
3244 if (IS_CHAR(element))
3245 return GFX_CHAR_START + (element - EL_CHAR_START);
3246 else if (element >= EL_SP_START && element <= EL_SP_END)
3248 int nr_element = element - EL_SP_START;
3249 int gfx_per_line = 8;
3251 (nr_element / gfx_per_line) * SP_PER_LINE +
3252 (nr_element % gfx_per_line);
3254 return GFX_START_ROCKSSP + nr_graphic;
3262 int el2gfx(int element)
3265 int graphic_OLD = el2gfx_OLD(element);
3270 int graphic_NEW = element_info[element].graphic[GFX_ACTION_DEFAULT];
3273 int graphic_OLD = el2gfx_OLD(element);
3275 if (element >= MAX_ELEMENTS)
3277 Error(ERR_WARN, "el2gfx: element == %d >= MAX_ELEMENTS", element);
3280 if (graphic_NEW != graphic_OLD)
3282 Error(ERR_WARN, "el2gfx: graphic_NEW (%d) != graphic_OLD (%d)",
3283 graphic_NEW, graphic_OLD);
3291 int el2img(int element)
3294 int graphic_NEW = element_info[element].graphic[GFX_ACTION_DEFAULT];
3301 case EL_BD_BUTTERFLY: return IMG_BD_BUTTERFLY;
3302 case EL_BD_FIREFLY: return IMG_BD_FIREFLY;
3303 case EL_SP_ELECTRON: return IMG_SP_ELECTRON;
3313 int el_dir2img(int element, int direction)
3315 return el_dir_act2img(element, direction, GFX_ACTION_DEFAULT);
3318 int el_dir_act2img(int element, int direction, int action)
3320 action = graphics_action_mapping[action];
3321 direction = MV_DIR_BIT(direction);
3323 return element_info[element].direction_graphic[action][direction];