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)
768 int delay = new_graphic_info[graphic].anim_delay;
770 if (!(FrameCounter % delay) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
772 int frame = getNewGraphicAnimationFrame(graphic, -1);
774 if (mask_mode == USE_MASKING)
775 DrawNewGraphicThruMask(SCREENX(x), SCREENY(y), graphic, frame);
777 DrawNewGraphic(SCREENX(x), SCREENY(y), graphic, frame);
781 void DrawGraphicAnimation(int x, int y, int graphic,
782 int frames, int delay, int mode)
784 DrawGraphicAnimationExt(x, y, graphic, frames, delay, mode, NO_MASKING);
787 void DrawNewGraphicAnimation(int x, int y, int graphic)
789 DrawNewGraphicAnimationExt(x, y, graphic, NO_MASKING);
792 void DrawGraphicAnimationThruMask(int x, int y, int graphic,
793 int frames, int delay, int mode)
795 DrawGraphicAnimationExt(x, y, graphic, frames, delay, mode, USE_MASKING);
798 static void DrawGraphicAnimationShiftedThruMask(int sx, int sy,
801 int frames, int delay,
804 int phase = getGraphicAnimationPhase(frames, delay, mode);
806 DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic + phase, NO_CUTTING);
809 void getGraphicSource(int graphic, Bitmap **bitmap, int *x, int *y)
811 if (graphic >= 0 && graphic_info[graphic].bitmap != NULL)
813 *bitmap = graphic_info[graphic].bitmap;
814 *x = graphic_info[graphic].src_x;
815 *y = graphic_info[graphic].src_y;
817 else if (graphic >= GFX_START_ROCKSELEMENTS &&
818 graphic <= GFX_END_ROCKSELEMENTS)
820 graphic -= GFX_START_ROCKSELEMENTS;
821 *bitmap = pix[PIX_ELEMENTS];
822 *x = (graphic % GFX_PER_LINE) * TILEX;
823 *y = (graphic / GFX_PER_LINE) * TILEY;
825 else if (graphic >= GFX_START_ROCKSHEROES && graphic <= GFX_END_ROCKSHEROES)
827 graphic -= GFX_START_ROCKSHEROES;
828 *bitmap = pix[PIX_HEROES];
829 *x = (graphic % HEROES_PER_LINE) * TILEX;
830 *y = (graphic / HEROES_PER_LINE) * TILEY;
832 else if (graphic >= GFX_START_ROCKSSP && graphic <= GFX_END_ROCKSSP)
834 graphic -= GFX_START_ROCKSSP;
835 *bitmap = pix[PIX_SP];
836 *x = (graphic % SP_PER_LINE) * TILEX;
837 *y = (graphic / SP_PER_LINE) * TILEY;
839 else if (graphic >= GFX_START_ROCKSDC && graphic <= GFX_END_ROCKSDC)
841 graphic -= GFX_START_ROCKSDC;
842 *bitmap = pix[PIX_DC];
843 *x = (graphic % DC_PER_LINE) * TILEX;
844 *y = (graphic / DC_PER_LINE) * TILEY;
846 else if (graphic >= GFX_START_ROCKSMORE && graphic <= GFX_END_ROCKSMORE)
848 graphic -= GFX_START_ROCKSMORE;
849 *bitmap = pix[PIX_MORE];
850 *x = (graphic % MORE_PER_LINE) * TILEX;
851 *y = (graphic / MORE_PER_LINE) * TILEY;
853 else if (graphic >= GFX_START_ROCKSFONT && graphic <= GFX_END_ROCKSFONT)
855 graphic -= GFX_START_ROCKSFONT;
856 *bitmap = pix[PIX_FONT_EM];
857 *x = (graphic % FONT_CHARS_PER_LINE) * TILEX;
858 *y = (graphic / FONT_CHARS_PER_LINE) * TILEY;
862 *bitmap = pix[PIX_SP];
868 void DrawGraphic(int x, int y, int graphic)
871 if (!IN_SCR_FIELD(x, y))
873 printf("DrawGraphic(): x = %d, y = %d, graphic = %d\n", x, y, graphic);
874 printf("DrawGraphic(): This should never happen!\n");
879 DrawGraphicExt(drawto_field, FX + x * TILEX, FY + y * TILEY, graphic);
883 void DrawNewGraphic(int x, int y, int graphic, int frame)
886 if (!IN_SCR_FIELD(x, y))
888 printf("DrawNewGraphic(): x = %d, y = %d, graphic = %d\n", x, y, graphic);
889 printf("DrawNewGraphic(): This should never happen!\n");
894 DrawNewGraphicExt(drawto_field, FX + x * TILEX, FY + y * TILEY,
899 void DrawGraphicExt(DrawBuffer *dst_bitmap, int x, int y, int graphic)
904 getGraphicSource(graphic, &src_bitmap, &src_x, &src_y);
905 BlitBitmap(src_bitmap, dst_bitmap, src_x, src_y, TILEX, TILEY, x, y);
908 void DrawNewGraphicExt(DrawBuffer *dst_bitmap, int x, int y, int graphic,
911 Bitmap *src_bitmap = new_graphic_info[graphic].bitmap;
912 int src_x = new_graphic_info[graphic].src_x;
913 int src_y = new_graphic_info[graphic].src_y;
914 int offset_x = new_graphic_info[graphic].offset_x;
915 int offset_y = new_graphic_info[graphic].offset_y;
917 src_x += frame * offset_x;
918 src_y += frame * offset_y;
920 BlitBitmap(src_bitmap, dst_bitmap, src_x, src_y, TILEX, TILEY, x, y);
923 void DrawGraphicThruMask(int x, int y, int graphic)
926 if (!IN_SCR_FIELD(x, y))
928 printf("DrawGraphicThruMask(): x = %d,y = %d, graphic = %d\n",x,y,graphic);
929 printf("DrawGraphicThruMask(): This should never happen!\n");
934 DrawGraphicThruMaskExt(drawto_field, FX + x * TILEX, FY + y *TILEY, graphic);
938 void DrawNewGraphicThruMask(int x, int y, int graphic, int frame)
941 if (!IN_SCR_FIELD(x, y))
943 printf("DrawGraphicThruMask(): x = %d,y = %d, graphic = %d\n",x,y,graphic);
944 printf("DrawGraphicThruMask(): This should never happen!\n");
949 DrawNewGraphicThruMaskExt(drawto_field, FX + x * TILEX, FY + y *TILEY,
954 void DrawGraphicThruMaskExt(DrawBuffer *d, int dest_x, int dest_y, int graphic)
961 if (graphic == GFX_LEERRAUM)
964 getGraphicSource(graphic, &src_bitmap, &src_x, &src_y);
965 drawing_gc = src_bitmap->stored_clip_gc;
967 if (tile_clipmask[tile] != None)
969 SetClipMask(src_bitmap, tile_clip_gc, tile_clipmask[tile]);
970 SetClipOrigin(src_bitmap, tile_clip_gc, dest_x, dest_y);
971 BlitBitmapMasked(src_bitmap, d,
972 src_x, src_y, TILEX, TILEY, dest_x, dest_y);
978 printf("DrawGraphicThruMask(): tile '%d' needs clipping!\n", tile);
982 SetClipOrigin(src_bitmap, drawing_gc, dest_x - src_x, dest_y - src_y);
983 BlitBitmapMasked(src_bitmap, d,
984 src_x, src_y, TILEX, TILEY, dest_x, dest_y);
988 void DrawNewGraphicThruMaskExt(DrawBuffer *d, int dest_x, int dest_y,
989 int graphic, int frame)
991 Bitmap *src_bitmap = new_graphic_info[graphic].bitmap;
992 GC drawing_gc = src_bitmap->stored_clip_gc;
993 int src_x = new_graphic_info[graphic].src_x;
994 int src_y = new_graphic_info[graphic].src_y;
995 int offset_x = new_graphic_info[graphic].offset_x;
996 int offset_y = new_graphic_info[graphic].offset_y;
998 src_x += frame * offset_x;
999 src_y += frame * offset_y;
1001 SetClipOrigin(src_bitmap, drawing_gc, dest_x - src_x, dest_y - src_y);
1002 BlitBitmapMasked(src_bitmap, d, src_x, src_y, TILEX, TILEY, dest_x, dest_y);
1005 void DrawMiniGraphic(int x, int y, int graphic)
1007 DrawMiniGraphicExt(drawto, SX + x*MINI_TILEX, SY + y*MINI_TILEY, graphic);
1008 MarkTileDirty(x/2, y/2);
1011 void getMiniGraphicSource(int graphic, Bitmap **bitmap, int *x, int *y)
1013 if (graphic >= GFX_START_ROCKSELEMENTS && graphic <= GFX_END_ROCKSELEMENTS)
1015 graphic -= GFX_START_ROCKSELEMENTS;
1016 *bitmap = pix[PIX_ELEMENTS];
1017 *x = MINI_GFX_STARTX + (graphic % MINI_GFX_PER_LINE) * MINI_TILEX;
1018 *y = MINI_GFX_STARTY + (graphic / MINI_GFX_PER_LINE) * MINI_TILEY;
1020 else if (graphic >= GFX_START_ROCKSSP && graphic <= GFX_END_ROCKSSP)
1022 graphic -= GFX_START_ROCKSSP;
1023 *bitmap = pix[PIX_SP];
1024 *x = MINI_SP_STARTX + (graphic % MINI_SP_PER_LINE) * MINI_TILEX;
1025 *y = MINI_SP_STARTY + (graphic / MINI_SP_PER_LINE) * MINI_TILEY;
1027 else if (graphic >= GFX_START_ROCKSDC && graphic <= GFX_END_ROCKSDC)
1029 graphic -= GFX_START_ROCKSDC;
1030 *bitmap = pix[PIX_DC];
1031 *x = MINI_DC_STARTX + (graphic % MINI_DC_PER_LINE) * MINI_TILEX;
1032 *y = MINI_DC_STARTY + (graphic / MINI_DC_PER_LINE) * MINI_TILEY;
1034 else if (graphic >= GFX_START_ROCKSMORE && graphic <= GFX_END_ROCKSMORE)
1036 graphic -= GFX_START_ROCKSMORE;
1037 *bitmap = pix[PIX_MORE];
1038 *x = MINI_MORE_STARTX + (graphic % MINI_MORE_PER_LINE) * MINI_TILEX;
1039 *y = MINI_MORE_STARTY + (graphic / MINI_MORE_PER_LINE) * MINI_TILEY;
1041 else if (graphic >= GFX_START_ROCKSFONT && graphic <= GFX_END_ROCKSFONT)
1043 graphic -= GFX_START_ROCKSFONT;
1044 *bitmap = pix[PIX_FONT_EM];
1045 *x = MINI_FONT_STARTX + (graphic % FONT_CHARS_PER_LINE) * FONT4_XSIZE;
1046 *y = MINI_FONT_STARTY + (graphic / FONT_CHARS_PER_LINE) * FONT4_YSIZE;
1050 *bitmap = pix[PIX_SP];
1051 *x = MINI_SP_STARTX;
1052 *y = MINI_SP_STARTY;
1056 void DrawMiniGraphicExt(DrawBuffer *d, int x, int y, int graphic)
1061 getMiniGraphicSource(graphic, &bitmap, &src_x, &src_y);
1062 BlitBitmap(bitmap, d, src_x, src_y, MINI_TILEX, MINI_TILEY, x, y);
1065 void DrawGraphicShifted(int x,int y, int dx,int dy, int graphic,
1066 int cut_mode, int mask_mode)
1068 int width = TILEX, height = TILEY;
1070 int src_x, src_y, dest_x, dest_y;
1077 DrawGraphic(x, y, graphic);
1081 if (dx || dy) /* Verschiebung der Grafik? */
1083 if (x < BX1) /* Element kommt von links ins Bild */
1090 else if (x > BX2) /* Element kommt von rechts ins Bild */
1096 else if (x==BX1 && dx < 0) /* Element verläßt links das Bild */
1102 else if (x==BX2 && dx > 0) /* Element verläßt rechts das Bild */
1104 else if (dx) /* allg. Bewegung in x-Richtung */
1105 MarkTileDirty(x + SIGN(dx), y);
1107 if (y < BY1) /* Element kommt von oben ins Bild */
1109 if (cut_mode==CUT_BELOW) /* Element oberhalb des Bildes */
1117 else if (y > BY2) /* Element kommt von unten ins Bild */
1123 else if (y==BY1 && dy < 0) /* Element verläßt oben das Bild */
1129 else if (dy > 0 && cut_mode == CUT_ABOVE)
1131 if (y == BY2) /* Element unterhalb des Bildes */
1137 MarkTileDirty(x, y + 1);
1138 } /* Element verläßt unten das Bild */
1139 else if (dy > 0 && (y == BY2 || cut_mode == CUT_BELOW))
1141 else if (dy) /* allg. Bewegung in y-Richtung */
1142 MarkTileDirty(x, y + SIGN(dy));
1145 getGraphicSource(graphic, &src_bitmap, &src_x, &src_y);
1146 drawing_gc = src_bitmap->stored_clip_gc;
1151 dest_x = FX + x * TILEX + dx;
1152 dest_y = FY + y * TILEY + dy;
1155 if (!IN_SCR_FIELD(x,y))
1157 printf("DrawGraphicShifted(): x = %d, y = %d, graphic = %d\n",x,y,graphic);
1158 printf("DrawGraphicShifted(): This should never happen!\n");
1163 if (mask_mode == USE_MASKING)
1165 if (tile_clipmask[tile] != None)
1167 SetClipMask(src_bitmap, tile_clip_gc, tile_clipmask[tile]);
1168 SetClipOrigin(src_bitmap, tile_clip_gc, dest_x, dest_y);
1169 BlitBitmapMasked(src_bitmap, drawto_field,
1170 src_x, src_y, TILEX, TILEY, dest_x, dest_y);
1176 printf("DrawGraphicShifted(): tile '%d' needs clipping!\n", tile);
1180 SetClipOrigin(src_bitmap, drawing_gc, dest_x - src_x, dest_y - src_y);
1181 BlitBitmapMasked(src_bitmap, drawto_field,
1182 src_x, src_y, width, height, dest_x, dest_y);
1186 BlitBitmap(src_bitmap, drawto_field,
1187 src_x, src_y, width, height, dest_x, dest_y);
1192 void DrawNewGraphicShifted(int x,int y, int dx,int dy, int graphic, int frame,
1193 int cut_mode, int mask_mode)
1202 int width = TILEX, height = TILEY;
1208 DrawNewGraphic(x, y, graphic, frame);
1212 if (dx || dy) /* Verschiebung der Grafik? */
1214 if (x < BX1) /* Element kommt von links ins Bild */
1221 else if (x > BX2) /* Element kommt von rechts ins Bild */
1227 else if (x==BX1 && dx < 0) /* Element verläßt links das Bild */
1233 else if (x==BX2 && dx > 0) /* Element verläßt rechts das Bild */
1235 else if (dx) /* allg. Bewegung in x-Richtung */
1236 MarkTileDirty(x + SIGN(dx), y);
1238 if (y < BY1) /* Element kommt von oben ins Bild */
1240 if (cut_mode==CUT_BELOW) /* Element oberhalb des Bildes */
1248 else if (y > BY2) /* Element kommt von unten ins Bild */
1254 else if (y==BY1 && dy < 0) /* Element verläßt oben das Bild */
1260 else if (dy > 0 && cut_mode == CUT_ABOVE)
1262 if (y == BY2) /* Element unterhalb des Bildes */
1268 MarkTileDirty(x, y + 1);
1269 } /* Element verläßt unten das Bild */
1270 else if (dy > 0 && (y == BY2 || cut_mode == CUT_BELOW))
1272 else if (dy) /* allg. Bewegung in y-Richtung */
1273 MarkTileDirty(x, y + SIGN(dy));
1276 src_bitmap = new_graphic_info[graphic].bitmap;
1277 drawing_gc = src_bitmap->stored_clip_gc;
1278 src_x = new_graphic_info[graphic].src_x;
1279 src_y = new_graphic_info[graphic].src_y;
1280 offset_x = new_graphic_info[graphic].offset_x;
1281 offset_y = new_graphic_info[graphic].offset_y;
1283 src_x += frame * offset_x;
1284 src_y += frame * offset_y;
1289 dest_x = FX + x * TILEX + dx;
1290 dest_y = FY + y * TILEY + dy;
1293 if (!IN_SCR_FIELD(x,y))
1295 printf("DrawGraphicShifted(): x = %d, y = %d, graphic = %d\n",x,y,graphic);
1296 printf("DrawGraphicShifted(): This should never happen!\n");
1301 if (mask_mode == USE_MASKING)
1302 SetClipOrigin(src_bitmap, drawing_gc, dest_x - src_x, dest_y - src_y);
1304 BlitBitmap(src_bitmap, drawto_field, src_x, src_y, width, height,
1310 void DrawGraphicShiftedThruMask(int x,int y, int dx,int dy, int graphic,
1313 DrawGraphicShifted(x,y, dx,dy, graphic, cut_mode, USE_MASKING);
1316 void DrawNewGraphicShiftedThruMask(int x,int y, int dx,int dy, int graphic,
1317 int frame, int cut_mode)
1319 DrawNewGraphicShifted(x,y, dx,dy, graphic, frame, cut_mode, USE_MASKING);
1322 void DrawScreenElementExt(int x, int y, int dx, int dy, int element,
1323 int cut_mode, int mask_mode)
1325 int ux = LEVELX(x), uy = LEVELY(y);
1326 int graphic = el2gfx(element);
1327 int phase8 = ABS(MovPos[ux][uy]) / (TILEX / 8);
1328 int phase4 = phase8 / 2;
1329 int phase2 = phase8 / 4;
1330 int dir = MovDir[ux][uy];
1332 if (element == EL_PACMAN || element == EL_BUG || element == EL_SPACESHIP)
1334 graphic += 1 * !phase2;
1338 else if (dir == MV_LEFT)
1340 else if (dir == MV_DOWN)
1343 else if (element == EL_SP_SNIKSNAK)
1346 graphic = GFX_SP_SNIKSNAK_LEFT;
1347 else if (dir == MV_RIGHT)
1348 graphic = GFX_SP_SNIKSNAK_RIGHT;
1349 else if (dir == MV_UP)
1350 graphic = GFX_SP_SNIKSNAK_UP;
1352 graphic = GFX_SP_SNIKSNAK_DOWN;
1354 graphic += (phase8 < 4 ? phase8 : 7 - phase8);
1356 else if (element == EL_SP_ELECTRON)
1358 graphic = GFX2_SP_ELECTRON + getGraphicAnimationPhase(8, 2, ANIM_LOOP);
1360 else if (element == EL_MOLE || element == EL_PENGUIN ||
1361 element == EL_PIG || element == EL_DRAGON)
1364 graphic = (element == EL_MOLE ? GFX_MOLE_LEFT :
1365 element == EL_PENGUIN ? GFX_PINGUIN_LEFT :
1366 element == EL_PIG ? GFX_SCHWEIN_LEFT : GFX_DRACHE_LEFT);
1367 else if (dir == MV_RIGHT)
1368 graphic = (element == EL_MOLE ? GFX_MOLE_RIGHT :
1369 element == EL_PENGUIN ? GFX_PINGUIN_RIGHT :
1370 element == EL_PIG ? GFX_SCHWEIN_RIGHT : GFX_DRACHE_RIGHT);
1371 else if (dir == MV_UP)
1372 graphic = (element == EL_MOLE ? GFX_MOLE_UP :
1373 element == EL_PENGUIN ? GFX_PINGUIN_UP :
1374 element == EL_PIG ? GFX_SCHWEIN_UP : GFX_DRACHE_UP);
1376 graphic = (element == EL_MOLE ? GFX_MOLE_DOWN :
1377 element == EL_PENGUIN ? GFX_PINGUIN_DOWN :
1378 element == EL_PIG ? GFX_SCHWEIN_DOWN : GFX_DRACHE_DOWN);
1382 else if (element == EL_SATELLITE)
1384 graphic = GFX_SONDE_START + getGraphicAnimationPhase(8, 2, ANIM_LOOP);
1386 else if (element == EL_ACID)
1388 graphic = GFX_GEBLUBBER + getGraphicAnimationPhase(4, 10, ANIM_LOOP);
1390 else if (element == EL_BD_BUTTERFLY || element == EL_BD_FIREFLY)
1394 else if (element == EL_BALLOON)
1398 else if ((element == EL_ROCK ||
1399 element == EL_SP_ZONK ||
1400 element == EL_BD_ROCK ||
1401 element == EL_SP_INFOTRON ||
1405 if (uy >= lev_fieldy-1 || !IS_BELT(Feld[ux][uy+1]))
1407 if (element == EL_ROCK ||
1408 element == EL_SP_ZONK ||
1409 element == EL_BD_ROCK)
1412 graphic += (4 - phase4) % 4;
1413 else if (dir == MV_RIGHT)
1416 graphic += phase2 * 2;
1418 else if (element != EL_SP_INFOTRON)
1422 else if (element == EL_MAGIC_WALL_ACTIVE ||
1423 element == EL_MAGIC_WALL_EMPTYING ||
1424 element == EL_BD_MAGIC_WALL_ACTIVE ||
1425 element == EL_BD_MAGIC_WALL_EMPTYING ||
1426 element == EL_MAGIC_WALL_FULL ||
1427 element == EL_BD_MAGIC_WALL_FULL)
1429 graphic += 3 + getGraphicAnimationPhase(4, 4, ANIM_REVERSE);
1431 else if (IS_AMOEBOID(element) || element == EL_AMOEBA_DRIPPING)
1433 graphic = (element == EL_AMOEBA_DEAD ? GFX_AMOEBE_TOT : GFX_AMOEBE_LEBT);
1434 graphic += (x + 2 * y + 4) % 4;
1436 else if (element == EL_WALL_GROWING)
1438 boolean links_massiv = FALSE, rechts_massiv = FALSE;
1440 if (!IN_LEV_FIELD(ux-1, uy) || IS_MAUER(Feld[ux-1][uy]))
1441 links_massiv = TRUE;
1442 if (!IN_LEV_FIELD(ux+1, uy) || IS_MAUER(Feld[ux+1][uy]))
1443 rechts_massiv = TRUE;
1445 if (links_massiv && rechts_massiv)
1446 graphic = GFX_MAUERWERK;
1447 else if (links_massiv)
1448 graphic = GFX_MAUER_R;
1449 else if (rechts_massiv)
1450 graphic = GFX_MAUER_L;
1453 else if ((element == EL_INVISIBLE_STEELWALL ||
1454 element == EL_INVISIBLE_WALL ||
1455 element == EL_INVISIBLE_SAND) && game.light_time_left)
1457 graphic = (element == EL_INVISIBLE_STEELWALL ? GFX_INVISIBLE_STEEL_ON :
1458 element == EL_INVISIBLE_WALL ? GFX_UNSICHTBAR_ON :
1459 GFX_SAND_INVISIBLE_ON);
1464 DrawGraphicShifted(x, y, dx, dy, graphic, cut_mode, mask_mode);
1465 else if (mask_mode == USE_MASKING)
1466 DrawGraphicThruMask(x, y, graphic);
1468 DrawGraphic(x, y, graphic);
1471 inline static int getGfxAction(int x, int y)
1473 int gfx_action = GFX_ACTION_DEFAULT;
1475 if (GfxAction[x][y] != GFX_ACTION_DEFAULT)
1476 gfx_action = GfxAction[x][y];
1477 else if (IS_MOVING(x, y))
1478 gfx_action = GFX_ACTION_MOVING;
1483 void DrawNewScreenElementExt(int x, int y, int dx, int dy, int element,
1484 int cut_mode, int mask_mode)
1486 int ux = LEVELX(x), uy = LEVELY(y);
1487 int move_dir = MovDir[ux][uy];
1488 int move_pos = ABS(MovPos[ux][uy]) / (TILEX / 8);
1489 int gfx_action = getGfxAction(ux, uy);
1490 int graphic = el_dir_act2img(element, move_dir, gfx_action);
1491 int frame = getNewGraphicAnimationFrame(graphic, move_pos);
1493 if (element == EL_WALL_GROWING)
1495 boolean left_stopped = FALSE, right_stopped = FALSE;
1497 if (!IN_LEV_FIELD(ux-1, uy) || IS_MAUER(Feld[ux-1][uy]))
1498 left_stopped = TRUE;
1499 if (!IN_LEV_FIELD(ux+1, uy) || IS_MAUER(Feld[ux+1][uy]))
1500 right_stopped = TRUE;
1502 if (left_stopped && right_stopped)
1504 else if (left_stopped)
1505 graphic = IMG_WALL_GROWING_ACTIVE_RIGHT;
1506 else if (right_stopped)
1507 graphic = IMG_WALL_GROWING_ACTIVE_LEFT;
1510 else if ((element == EL_ROCK ||
1511 element == EL_SP_ZONK ||
1512 element == EL_BD_ROCK ||
1513 element == EL_SP_INFOTRON ||
1517 if (uy >= lev_fieldy-1 || !IS_BELT(Feld[ux][uy+1]))
1519 if (element == EL_ROCK ||
1520 element == EL_SP_ZONK ||
1521 element == EL_BD_ROCK)
1523 if (move_dir == MV_LEFT)
1524 graphic += (4 - phase4) % 4;
1525 else if (move_dir == MV_RIGHT)
1528 graphic += phase2 * 2;
1530 else if (element != EL_SP_INFOTRON)
1534 else if (IS_AMOEBOID(element) || element == EL_AMOEBA_DRIPPING)
1536 graphic = (element == EL_AMOEBA_DEAD ? GFX_AMOEBE_TOT : GFX_AMOEBE_LEBT);
1537 graphic += (x + 2 * y + 4) % 4;
1542 DrawNewGraphicShifted(x, y, dx, dy, graphic, frame, cut_mode, mask_mode);
1543 else if (mask_mode == USE_MASKING)
1544 DrawNewGraphicThruMask(x, y, graphic, frame);
1546 DrawNewGraphic(x, y, graphic, frame);
1549 void DrawLevelElementExt(int x, int y, int dx, int dy, int element,
1550 int cut_mode, int mask_mode)
1552 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1553 DrawScreenElementExt(SCREENX(x), SCREENY(y), dx, dy, element,
1554 cut_mode, mask_mode);
1557 void DrawNewLevelElementExt(int x, int y, int dx, int dy, int element,
1558 int cut_mode, int mask_mode)
1560 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1561 DrawNewScreenElementExt(SCREENX(x), SCREENY(y), dx, dy, element,
1562 cut_mode, mask_mode);
1565 void DrawScreenElementShifted(int x, int y, int dx, int dy, int element,
1568 DrawScreenElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
1571 void DrawNewScreenElementShifted(int x, int y, int dx, int dy, int element,
1574 DrawNewScreenElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
1577 void DrawLevelElementShifted(int x, int y, int dx, int dy, int element,
1580 DrawLevelElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
1583 void DrawNewLevelElementShifted(int x, int y, int dx, int dy, int element,
1586 DrawNewLevelElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
1589 void DrawScreenElementThruMask(int x, int y, int element)
1591 DrawScreenElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
1594 void DrawNewScreenElementThruMask(int x, int y, int element)
1596 DrawNewScreenElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
1599 void DrawLevelElementThruMask(int x, int y, int element)
1601 DrawLevelElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
1604 void DrawNewLevelElementThruMask(int x, int y, int element)
1606 DrawNewLevelElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
1609 void DrawLevelFieldThruMask(int x, int y)
1611 DrawLevelElementExt(x, y, 0, 0, Feld[x][y], NO_CUTTING, USE_MASKING);
1614 void DrawNewLevelFieldThruMask(int x, int y)
1616 DrawNewLevelElementExt(x, y, 0, 0, Feld[x][y], NO_CUTTING, USE_MASKING);
1619 void ErdreichAnbroeckeln(int x, int y)
1623 int i, width, height, cx,cy;
1624 int ux = LEVELX(x), uy = LEVELY(y);
1625 int element, graphic;
1627 static int xy[4][2] =
1635 if (!IN_LEV_FIELD(ux, uy))
1638 element = Feld[ux][uy];
1640 if (element == EL_SAND ||
1641 element == EL_LANDMINE ||
1642 element == EL_TRAP ||
1643 element == EL_TRAP_ACTIVE)
1645 if (!IN_SCR_FIELD(x, y))
1648 graphic = GFX_ERDENRAND;
1650 getGraphicSource(graphic, &src_bitmap, &src_x, &src_y);
1656 uxx = ux + xy[i][0];
1657 uyy = uy + xy[i][1];
1658 if (!IN_LEV_FIELD(uxx, uyy))
1659 element = EL_STEELWALL;
1661 element = Feld[uxx][uyy];
1663 if (element == EL_SAND ||
1664 element == EL_LANDMINE ||
1665 element == EL_TRAP ||
1666 element == EL_TRAP_ACTIVE)
1669 if (i == 1 || i == 2)
1673 cx = (i == 2 ? TILEX - snip : 0);
1681 cy = (i == 3 ? TILEY - snip : 0);
1684 BlitBitmap(src_bitmap, drawto_field, src_x + cx, src_y + cy,
1685 width, height, FX + x * TILEX + cx, FY + y * TILEY + cy);
1688 MarkTileDirty(x, y);
1692 graphic = GFX_ERDENRAND;
1694 getGraphicSource(graphic, &src_bitmap, &src_x, &src_y);
1698 int xx, yy, uxx, uyy;
1702 uxx = ux + xy[i][0];
1703 uyy = uy + xy[i][1];
1705 if (!IN_LEV_FIELD(uxx, uyy) ||
1706 (Feld[uxx][uyy] != EL_SAND &&
1707 Feld[uxx][uyy] != EL_LANDMINE &&
1708 Feld[uxx][uyy] != EL_TRAP &&
1709 Feld[uxx][uyy] != EL_TRAP_ACTIVE) ||
1710 !IN_SCR_FIELD(xx, yy))
1713 if (i == 1 || i == 2)
1717 cx = (i == 1 ? TILEX - snip : 0);
1725 cy = (i==0 ? TILEY-snip : 0);
1728 BlitBitmap(src_bitmap, drawto_field, src_x + cx, src_y + cy,
1729 width, height, FX + xx * TILEX + cx, FY + yy * TILEY + cy);
1731 MarkTileDirty(xx, yy);
1736 void DrawScreenElement(int x, int y, int element)
1738 DrawScreenElementExt(x, y, 0, 0, element, NO_CUTTING, NO_MASKING);
1739 ErdreichAnbroeckeln(x, y);
1742 void DrawNewScreenElement(int x, int y, int element)
1744 DrawNewScreenElementExt(x, y, 0, 0, element, NO_CUTTING, NO_MASKING);
1745 ErdreichAnbroeckeln(x, y);
1748 void DrawLevelElement(int x, int y, int element)
1750 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1751 DrawScreenElement(SCREENX(x), SCREENY(y), element);
1754 void DrawNewLevelElement(int x, int y, int element)
1756 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1757 DrawNewScreenElement(SCREENX(x), SCREENY(y), element);
1760 void DrawScreenField(int x, int y)
1762 int ux = LEVELX(x), uy = LEVELY(y);
1763 int element, content;
1765 if (!IN_LEV_FIELD(ux, uy))
1767 if (ux < -1 || ux > lev_fieldx || uy < -1 || uy > lev_fieldy)
1770 element = BorderElement;
1772 DrawScreenElement(x, y, element);
1776 element = Feld[ux][uy];
1777 content = Store[ux][uy];
1779 if (IS_MOVING(ux, uy))
1781 int horiz_move = (MovDir[ux][uy] == MV_LEFT || MovDir[ux][uy] == MV_RIGHT);
1782 boolean cut_mode = NO_CUTTING;
1784 if (element == EL_QUICKSAND_EMPTYING ||
1785 element == EL_MAGIC_WALL_EMPTYING ||
1786 element == EL_BD_MAGIC_WALL_EMPTYING ||
1787 element == EL_AMOEBA_DRIPPING)
1788 cut_mode = CUT_ABOVE;
1789 else if (element == EL_QUICKSAND_FILLING ||
1790 element == EL_MAGIC_WALL_FILLING ||
1791 element == EL_BD_MAGIC_WALL_FILLING)
1792 cut_mode = CUT_BELOW;
1794 if (cut_mode == CUT_ABOVE)
1795 DrawScreenElementShifted(x, y, 0, 0, element, NO_CUTTING);
1797 DrawScreenElement(x, y, EL_EMPTY);
1800 DrawScreenElementShifted(x, y, MovPos[ux][uy], 0, element, NO_CUTTING);
1801 else if (cut_mode == NO_CUTTING)
1802 DrawScreenElementShifted(x, y, 0, MovPos[ux][uy], element, cut_mode);
1804 DrawScreenElementShifted(x, y, 0, MovPos[ux][uy], content, cut_mode);
1806 if (content == EL_ACID)
1807 DrawLevelElementThruMask(ux, uy + 1, EL_ACID);
1809 else if (IS_BLOCKED(ux, uy))
1814 boolean cut_mode = NO_CUTTING;
1815 int element_old, content_old;
1817 Blocked2Moving(ux, uy, &oldx, &oldy);
1820 horiz_move = (MovDir[oldx][oldy] == MV_LEFT ||
1821 MovDir[oldx][oldy] == MV_RIGHT);
1823 element_old = Feld[oldx][oldy];
1824 content_old = Store[oldx][oldy];
1826 if (element_old == EL_QUICKSAND_EMPTYING ||
1827 element_old == EL_MAGIC_WALL_EMPTYING ||
1828 element_old == EL_BD_MAGIC_WALL_EMPTYING ||
1829 element_old == EL_AMOEBA_DRIPPING)
1830 cut_mode = CUT_ABOVE;
1832 DrawScreenElement(x, y, EL_EMPTY);
1835 DrawScreenElementShifted(sx, sy, MovPos[oldx][oldy], 0, element_old,
1837 else if (cut_mode == NO_CUTTING)
1838 DrawScreenElementShifted(sx, sy, 0, MovPos[oldx][oldy], element_old,
1841 DrawScreenElementShifted(sx, sy, 0, MovPos[oldx][oldy], content_old,
1844 else if (IS_DRAWABLE(element))
1845 DrawScreenElement(x, y, element);
1847 DrawScreenElement(x, y, EL_EMPTY);
1850 void DrawNewScreenField(int x, int y)
1852 int ux = LEVELX(x), uy = LEVELY(y);
1853 int element, content;
1855 if (!IN_LEV_FIELD(ux, uy))
1857 if (ux < -1 || ux > lev_fieldx || uy < -1 || uy > lev_fieldy)
1860 element = BorderElement;
1862 DrawNewScreenElement(x, y, element);
1866 element = Feld[ux][uy];
1867 content = Store[ux][uy];
1869 if (IS_MOVING(ux, uy))
1871 int horiz_move = (MovDir[ux][uy] == MV_LEFT || MovDir[ux][uy] == MV_RIGHT);
1872 boolean cut_mode = NO_CUTTING;
1874 if (element == EL_QUICKSAND_EMPTYING ||
1875 element == EL_MAGIC_WALL_EMPTYING ||
1876 element == EL_BD_MAGIC_WALL_EMPTYING ||
1877 element == EL_AMOEBA_DRIPPING)
1878 cut_mode = CUT_ABOVE;
1879 else if (element == EL_QUICKSAND_FILLING ||
1880 element == EL_MAGIC_WALL_FILLING ||
1881 element == EL_BD_MAGIC_WALL_FILLING)
1882 cut_mode = CUT_BELOW;
1884 if (cut_mode == CUT_ABOVE)
1885 DrawNewScreenElementShifted(x, y, 0, 0, element, NO_CUTTING);
1887 DrawNewScreenElement(x, y, EL_EMPTY);
1890 DrawNewScreenElementShifted(x, y, MovPos[ux][uy], 0, element, NO_CUTTING);
1891 else if (cut_mode == NO_CUTTING)
1892 DrawNewScreenElementShifted(x, y, 0, MovPos[ux][uy], element, cut_mode);
1894 DrawNewScreenElementShifted(x, y, 0, MovPos[ux][uy], content, cut_mode);
1896 if (content == EL_ACID)
1897 DrawNewLevelElementThruMask(ux, uy + 1, EL_ACID);
1899 else if (IS_BLOCKED(ux, uy))
1904 boolean cut_mode = NO_CUTTING;
1905 int element_old, content_old;
1907 Blocked2Moving(ux, uy, &oldx, &oldy);
1910 horiz_move = (MovDir[oldx][oldy] == MV_LEFT ||
1911 MovDir[oldx][oldy] == MV_RIGHT);
1913 element_old = Feld[oldx][oldy];
1914 content_old = Store[oldx][oldy];
1916 if (element_old == EL_QUICKSAND_EMPTYING ||
1917 element_old == EL_MAGIC_WALL_EMPTYING ||
1918 element_old == EL_BD_MAGIC_WALL_EMPTYING ||
1919 element_old == EL_AMOEBA_DRIPPING)
1920 cut_mode = CUT_ABOVE;
1922 DrawNewScreenElement(x, y, EL_EMPTY);
1925 DrawNewScreenElementShifted(sx, sy, MovPos[oldx][oldy], 0, element_old,
1927 else if (cut_mode == NO_CUTTING)
1928 DrawNewScreenElementShifted(sx, sy, 0, MovPos[oldx][oldy], element_old,
1931 DrawNewScreenElementShifted(sx, sy, 0, MovPos[oldx][oldy], content_old,
1934 else if (IS_DRAWABLE(element))
1935 DrawNewScreenElement(x, y, element);
1937 DrawNewScreenElement(x, y, EL_EMPTY);
1940 void DrawLevelField(int x, int y)
1942 if (IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1943 DrawScreenField(SCREENX(x), SCREENY(y));
1944 else if (IS_MOVING(x, y))
1948 Moving2Blocked(x, y, &newx, &newy);
1949 if (IN_SCR_FIELD(SCREENX(newx), SCREENY(newy)))
1950 DrawScreenField(SCREENX(newx), SCREENY(newy));
1952 else if (IS_BLOCKED(x, y))
1956 Blocked2Moving(x, y, &oldx, &oldy);
1957 if (IN_SCR_FIELD(SCREENX(oldx), SCREENY(oldy)))
1958 DrawScreenField(SCREENX(oldx), SCREENY(oldy));
1962 void DrawNewLevelField(int x, int y)
1964 if (IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1965 DrawNewScreenField(SCREENX(x), SCREENY(y));
1966 else if (IS_MOVING(x, y))
1970 Moving2Blocked(x, y, &newx, &newy);
1971 if (IN_SCR_FIELD(SCREENX(newx), SCREENY(newy)))
1972 DrawNewScreenField(SCREENX(newx), SCREENY(newy));
1974 else if (IS_BLOCKED(x, y))
1978 Blocked2Moving(x, y, &oldx, &oldy);
1979 if (IN_SCR_FIELD(SCREENX(oldx), SCREENY(oldy)))
1980 DrawNewScreenField(SCREENX(oldx), SCREENY(oldy));
1984 void DrawMiniElement(int x, int y, int element)
1990 DrawMiniGraphic(x, y, -1);
1994 graphic = el2gfx(element);
1995 DrawMiniGraphic(x, y, graphic);
1998 void DrawMiniElementOrWall(int sx, int sy, int scroll_x, int scroll_y)
2000 int x = sx + scroll_x, y = sy + scroll_y;
2002 if (x < -1 || x > lev_fieldx || y < -1 || y > lev_fieldy)
2003 DrawMiniElement(sx, sy, EL_EMPTY);
2004 else if (x > -1 && x < lev_fieldx && y > -1 && y < lev_fieldy)
2005 DrawMiniElement(sx, sy, Feld[x][y]);
2008 int steel_type, steel_position;
2011 { GFX_VSTEEL_UPPER_LEFT, GFX_ISTEEL_UPPER_LEFT },
2012 { GFX_VSTEEL_UPPER_RIGHT, GFX_ISTEEL_UPPER_RIGHT },
2013 { GFX_VSTEEL_LOWER_LEFT, GFX_ISTEEL_LOWER_LEFT },
2014 { GFX_VSTEEL_LOWER_RIGHT, GFX_ISTEEL_LOWER_RIGHT },
2015 { GFX_VSTEEL_VERTICAL, GFX_ISTEEL_VERTICAL },
2016 { GFX_VSTEEL_HORIZONTAL, GFX_ISTEEL_HORIZONTAL }
2019 steel_type = (BorderElement == EL_STEELWALL ? 0 : 1);
2020 steel_position = (x == -1 && y == -1 ? 0 :
2021 x == lev_fieldx && y == -1 ? 1 :
2022 x == -1 && y == lev_fieldy ? 2 :
2023 x == lev_fieldx && y == lev_fieldy ? 3 :
2024 x == -1 || x == lev_fieldx ? 4 :
2025 y == -1 || y == lev_fieldy ? 5 : -1);
2027 if (steel_position != -1)
2028 DrawMiniGraphic(sx, sy, border[steel_position][steel_type]);
2032 void DrawMicroElement(int xpos, int ypos, int element)
2036 if (element == EL_EMPTY)
2039 graphic = el2gfx(element);
2041 if (graphic >= GFX_START_ROCKSSP && graphic <= GFX_END_ROCKSSP)
2043 graphic -= GFX_START_ROCKSSP;
2044 BlitBitmap(pix[PIX_SP], drawto,
2045 MICRO_SP_STARTX + (graphic % MICRO_SP_PER_LINE) * MICRO_TILEX,
2046 MICRO_SP_STARTY + (graphic / MICRO_SP_PER_LINE) * MICRO_TILEY,
2047 MICRO_TILEX, MICRO_TILEY, xpos, ypos);
2049 else if (graphic >= GFX_START_ROCKSDC && graphic <= GFX_END_ROCKSDC)
2051 graphic -= GFX_START_ROCKSDC;
2052 BlitBitmap(pix[PIX_DC], drawto,
2053 MICRO_DC_STARTX + (graphic % MICRO_DC_PER_LINE) * MICRO_TILEX,
2054 MICRO_DC_STARTY + (graphic / MICRO_DC_PER_LINE) * MICRO_TILEY,
2055 MICRO_TILEX, MICRO_TILEY, xpos, ypos);
2057 else if (graphic >= GFX_START_ROCKSMORE && graphic <= GFX_END_ROCKSMORE)
2059 graphic -= GFX_START_ROCKSMORE;
2060 BlitBitmap(pix[PIX_MORE], drawto,
2061 MICRO_MORE_STARTX + (graphic % MICRO_MORE_PER_LINE)*MICRO_TILEX,
2062 MICRO_MORE_STARTY + (graphic / MICRO_MORE_PER_LINE)*MICRO_TILEY,
2063 MICRO_TILEX, MICRO_TILEY, xpos, ypos);
2065 else if (graphic >= GFX_CHAR_START && graphic <= GFX_CHAR_END)
2067 graphic -= GFX_CHAR_START;
2068 BlitBitmap(pix[PIX_FONT_EM], drawto,
2069 MICRO_FONT_STARTX + (graphic % MICRO_GFX_PER_LINE)* MICRO_TILEX,
2070 MICRO_FONT_STARTY + (graphic / MICRO_GFX_PER_LINE)* MICRO_TILEY,
2071 MICRO_TILEX, MICRO_TILEY, xpos, ypos);
2074 BlitBitmap(pix[PIX_ELEMENTS], drawto,
2075 MICRO_GFX_STARTX + (graphic % MICRO_GFX_PER_LINE) * MICRO_TILEX,
2076 MICRO_GFX_STARTY + (graphic / MICRO_GFX_PER_LINE) * MICRO_TILEY,
2077 MICRO_TILEX, MICRO_TILEY, xpos, ypos);
2086 for(x=BX1; x<=BX2; x++)
2087 for(y=BY1; y<=BY2; y++)
2088 DrawScreenField(x, y);
2090 redraw_mask |= REDRAW_FIELD;
2093 void DrawMiniLevel(int size_x, int size_y, int scroll_x, int scroll_y)
2097 for(x=0; x<size_x; x++)
2098 for(y=0; y<size_y; y++)
2099 DrawMiniElementOrWall(x, y, scroll_x, scroll_y);
2101 redraw_mask |= REDRAW_FIELD;
2104 static void DrawMicroLevelExt(int xpos, int ypos, int from_x, int from_y)
2108 ClearRectangle(drawto, xpos, ypos, MICROLEV_XSIZE, MICROLEV_YSIZE);
2110 if (lev_fieldx < STD_LEV_FIELDX)
2111 xpos += (STD_LEV_FIELDX - lev_fieldx) / 2 * MICRO_TILEX;
2112 if (lev_fieldy < STD_LEV_FIELDY)
2113 ypos += (STD_LEV_FIELDY - lev_fieldy) / 2 * MICRO_TILEY;
2115 xpos += MICRO_TILEX;
2116 ypos += MICRO_TILEY;
2118 for(x=-1; x<=STD_LEV_FIELDX; x++)
2120 for(y=-1; y<=STD_LEV_FIELDY; y++)
2122 int lx = from_x + x, ly = from_y + y;
2124 if (lx >= 0 && lx < lev_fieldx && ly >= 0 && ly < lev_fieldy)
2125 DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
2127 else if (lx >= -1 && lx < lev_fieldx+1 && ly >= -1 && ly < lev_fieldy+1)
2128 DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
2133 redraw_mask |= REDRAW_MICROLEVEL;
2136 #define MICROLABEL_EMPTY 0
2137 #define MICROLABEL_LEVEL_NAME 1
2138 #define MICROLABEL_CREATED_BY 2
2139 #define MICROLABEL_LEVEL_AUTHOR 3
2140 #define MICROLABEL_IMPORTED_FROM 4
2141 #define MICROLABEL_LEVEL_IMPORT_INFO 5
2143 #define MAX_MICROLABEL_SIZE (SXSIZE / FONT4_XSIZE)
2145 static void DrawMicroLevelLabelExt(int mode)
2147 char label_text[MAX_MICROLABEL_SIZE + 1];
2149 ClearRectangle(drawto, SX, MICROLABEL_YPOS, SXSIZE, FONT4_YSIZE);
2151 strncpy(label_text, (mode == MICROLABEL_LEVEL_NAME ? level.name :
2152 mode == MICROLABEL_CREATED_BY ? "created by" :
2153 mode == MICROLABEL_LEVEL_AUTHOR ? level.author :
2154 mode == MICROLABEL_IMPORTED_FROM ? "imported from" :
2155 mode == MICROLABEL_LEVEL_IMPORT_INFO ?
2156 leveldir_current->imported_from : ""),
2157 MAX_MICROLABEL_SIZE);
2158 label_text[MAX_MICROLABEL_SIZE] = '\0';
2160 if (strlen(label_text) > 0)
2162 int lxpos = SX + (SXSIZE - strlen(label_text) * FONT4_XSIZE) / 2;
2163 int lypos = MICROLABEL_YPOS;
2165 DrawText(lxpos, lypos, label_text, FS_SMALL, FC_SPECIAL2);
2168 redraw_mask |= REDRAW_MICROLEVEL;
2171 void DrawMicroLevel(int xpos, int ypos, boolean restart)
2173 static unsigned long scroll_delay = 0;
2174 static unsigned long label_delay = 0;
2175 static int from_x, from_y, scroll_direction;
2176 static int label_state, label_counter;
2180 from_x = from_y = 0;
2181 scroll_direction = MV_RIGHT;
2185 DrawMicroLevelExt(xpos, ypos, from_x, from_y);
2186 DrawMicroLevelLabelExt(label_state);
2188 /* initialize delay counters */
2189 DelayReached(&scroll_delay, 0);
2190 DelayReached(&label_delay, 0);
2195 /* scroll micro level, if needed */
2196 if ((lev_fieldx > STD_LEV_FIELDX || lev_fieldy > STD_LEV_FIELDY) &&
2197 DelayReached(&scroll_delay, MICROLEVEL_SCROLL_DELAY))
2199 switch (scroll_direction)
2205 scroll_direction = MV_UP;
2209 if (from_x < lev_fieldx - STD_LEV_FIELDX)
2212 scroll_direction = MV_DOWN;
2219 scroll_direction = MV_RIGHT;
2223 if (from_y < lev_fieldy - STD_LEV_FIELDY)
2226 scroll_direction = MV_LEFT;
2233 DrawMicroLevelExt(xpos, ypos, from_x, from_y);
2236 /* redraw micro level label, if needed */
2237 if (strcmp(level.name, NAMELESS_LEVEL_NAME) != 0 &&
2238 strcmp(level.author, ANONYMOUS_NAME) != 0 &&
2239 strcmp(level.author, leveldir_current->name) != 0 &&
2240 DelayReached(&label_delay, MICROLEVEL_LABEL_DELAY))
2242 int max_label_counter = 23;
2244 if (leveldir_current->imported_from != NULL)
2245 max_label_counter += 14;
2247 label_counter = (label_counter + 1) % max_label_counter;
2248 label_state = (label_counter >= 0 && label_counter <= 7 ?
2249 MICROLABEL_LEVEL_NAME :
2250 label_counter >= 9 && label_counter <= 12 ?
2251 MICROLABEL_CREATED_BY :
2252 label_counter >= 14 && label_counter <= 21 ?
2253 MICROLABEL_LEVEL_AUTHOR :
2254 label_counter >= 23 && label_counter <= 26 ?
2255 MICROLABEL_IMPORTED_FROM :
2256 label_counter >= 28 && label_counter <= 35 ?
2257 MICROLABEL_LEVEL_IMPORT_INFO : MICROLABEL_EMPTY);
2258 DrawMicroLevelLabelExt(label_state);
2262 int REQ_in_range(int x, int y)
2264 if (y > DY+249 && y < DY+278)
2266 if (x > DX+1 && x < DX+48)
2268 else if (x > DX+51 && x < DX+98)
2274 #define MAX_REQUEST_LINES 13
2275 #define MAX_REQUEST_LINE_LEN 7
2277 boolean Request(char *text, unsigned int req_state)
2279 int mx, my, ty, result = -1;
2280 unsigned int old_door_state;
2282 #if defined(PLATFORM_UNIX)
2283 /* pause network game while waiting for request to answer */
2284 if (options.network &&
2285 game_status == PLAYING &&
2286 req_state & REQUEST_WAIT_FOR)
2287 SendToServer_PausePlaying();
2290 old_door_state = GetDoorState();
2294 CloseDoor(DOOR_CLOSE_1);
2296 /* save old door content */
2297 BlitBitmap(pix[PIX_DB_DOOR], pix[PIX_DB_DOOR],
2298 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE,
2299 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1);
2301 /* clear door drawing field */
2302 ClearRectangle(drawto, DX, DY, DXSIZE, DYSIZE);
2304 /* write text for request */
2305 for(ty=0; ty < MAX_REQUEST_LINES; ty++)
2307 char text_line[MAX_REQUEST_LINE_LEN + 1];
2313 for(tl=0,tx=0; tx < MAX_REQUEST_LINE_LEN; tl++,tx++)
2316 if (!tc || tc == ' ')
2327 strncpy(text_line, text, tl);
2330 DrawTextExt(drawto, DX + 50 - (tl * 14)/2, DY + 8 + ty * 16,
2331 text_line, FS_SMALL, FC_YELLOW);
2333 text += tl + (tc == ' ' ? 1 : 0);
2336 if (req_state & REQ_ASK)
2338 MapGadget(tool_gadget[TOOL_CTRL_ID_YES]);
2339 MapGadget(tool_gadget[TOOL_CTRL_ID_NO]);
2341 else if (req_state & REQ_CONFIRM)
2343 MapGadget(tool_gadget[TOOL_CTRL_ID_CONFIRM]);
2345 else if (req_state & REQ_PLAYER)
2347 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_1]);
2348 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_2]);
2349 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_3]);
2350 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_4]);
2353 /* copy request gadgets to door backbuffer */
2354 BlitBitmap(drawto, pix[PIX_DB_DOOR],
2355 DX, DY, DXSIZE, DYSIZE,
2356 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
2358 OpenDoor(DOOR_OPEN_1);
2364 if (!(req_state & REQUEST_WAIT_FOR))
2367 if (game_status != MAINMENU)
2370 button_status = MB_RELEASED;
2372 request_gadget_id = -1;
2384 case EVENT_BUTTONPRESS:
2385 case EVENT_BUTTONRELEASE:
2386 case EVENT_MOTIONNOTIFY:
2388 if (event.type == EVENT_MOTIONNOTIFY)
2390 if (!PointerInWindow(window))
2391 continue; /* window and pointer are on different screens */
2396 motion_status = TRUE;
2397 mx = ((MotionEvent *) &event)->x;
2398 my = ((MotionEvent *) &event)->y;
2402 motion_status = FALSE;
2403 mx = ((ButtonEvent *) &event)->x;
2404 my = ((ButtonEvent *) &event)->y;
2405 if (event.type == EVENT_BUTTONPRESS)
2406 button_status = ((ButtonEvent *) &event)->button;
2408 button_status = MB_RELEASED;
2411 /* this sets 'request_gadget_id' */
2412 HandleGadgets(mx, my, button_status);
2414 switch(request_gadget_id)
2416 case TOOL_CTRL_ID_YES:
2419 case TOOL_CTRL_ID_NO:
2422 case TOOL_CTRL_ID_CONFIRM:
2423 result = TRUE | FALSE;
2426 case TOOL_CTRL_ID_PLAYER_1:
2429 case TOOL_CTRL_ID_PLAYER_2:
2432 case TOOL_CTRL_ID_PLAYER_3:
2435 case TOOL_CTRL_ID_PLAYER_4:
2446 case EVENT_KEYPRESS:
2447 switch(GetEventKey((KeyEvent *)&event, TRUE))
2460 if (req_state & REQ_PLAYER)
2464 case EVENT_KEYRELEASE:
2465 ClearPlayerAction();
2469 HandleOtherEvents(&event);
2473 else if (AnyJoystickButton() == JOY_BUTTON_NEW_PRESSED)
2475 int joy = AnyJoystick();
2477 if (joy & JOY_BUTTON_1)
2479 else if (joy & JOY_BUTTON_2)
2485 /* don't eat all CPU time */
2489 if (game_status != MAINMENU)
2494 if (!(req_state & REQ_STAY_OPEN))
2496 CloseDoor(DOOR_CLOSE_1);
2498 if (!(req_state & REQ_STAY_CLOSED) && (old_door_state & DOOR_OPEN_1))
2500 BlitBitmap(pix[PIX_DB_DOOR], pix[PIX_DB_DOOR],
2501 DOOR_GFX_PAGEX2,DOOR_GFX_PAGEY1, DXSIZE,DYSIZE,
2502 DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY1);
2503 OpenDoor(DOOR_OPEN_1);
2509 #if defined(PLATFORM_UNIX)
2510 /* continue network game after request */
2511 if (options.network &&
2512 game_status == PLAYING &&
2513 req_state & REQUEST_WAIT_FOR)
2514 SendToServer_ContinuePlaying();
2520 unsigned int OpenDoor(unsigned int door_state)
2522 unsigned int new_door_state;
2524 if (door_state & DOOR_COPY_BACK)
2526 BlitBitmap(pix[PIX_DB_DOOR], pix[PIX_DB_DOOR],
2527 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE + VYSIZE,
2528 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
2529 door_state &= ~DOOR_COPY_BACK;
2532 new_door_state = MoveDoor(door_state);
2534 return(new_door_state);
2537 unsigned int CloseDoor(unsigned int door_state)
2539 unsigned int new_door_state;
2541 BlitBitmap(backbuffer, pix[PIX_DB_DOOR],
2542 DX, DY, DXSIZE, DYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
2543 BlitBitmap(backbuffer, pix[PIX_DB_DOOR],
2544 VX, VY, VXSIZE, VYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2);
2546 new_door_state = MoveDoor(door_state);
2548 return(new_door_state);
2551 unsigned int GetDoorState()
2553 return MoveDoor(DOOR_GET_STATE);
2556 unsigned int SetDoorState(unsigned int door_state)
2558 return MoveDoor(door_state | DOOR_SET_STATE);
2561 unsigned int MoveDoor(unsigned int door_state)
2563 static int door1 = DOOR_OPEN_1;
2564 static int door2 = DOOR_CLOSE_2;
2565 static unsigned long door_delay = 0;
2566 int x, start, stepsize = 2;
2567 unsigned long door_delay_value = stepsize * 5;
2569 if (door_state == DOOR_GET_STATE)
2570 return(door1 | door2);
2572 if (door_state & DOOR_SET_STATE)
2574 if (door_state & DOOR_ACTION_1)
2575 door1 = door_state & DOOR_ACTION_1;
2576 if (door_state & DOOR_ACTION_2)
2577 door2 = door_state & DOOR_ACTION_2;
2579 return(door1 | door2);
2582 if (door1 == DOOR_OPEN_1 && door_state & DOOR_OPEN_1)
2583 door_state &= ~DOOR_OPEN_1;
2584 else if (door1 == DOOR_CLOSE_1 && door_state & DOOR_CLOSE_1)
2585 door_state &= ~DOOR_CLOSE_1;
2586 if (door2 == DOOR_OPEN_2 && door_state & DOOR_OPEN_2)
2587 door_state &= ~DOOR_OPEN_2;
2588 else if (door2 == DOOR_CLOSE_2 && door_state & DOOR_CLOSE_2)
2589 door_state &= ~DOOR_CLOSE_2;
2591 if (setup.quick_doors)
2594 door_delay_value = 0;
2595 StopSound(SND_MENU_DOOR_OPENING);
2596 StopSound(SND_MENU_DOOR_CLOSING);
2599 if (door_state & DOOR_ACTION)
2601 if (!(door_state & DOOR_NO_DELAY))
2603 /* opening door sound has priority over simultaneously closing door */
2604 if (door_state & (DOOR_OPEN_1 | DOOR_OPEN_2))
2605 PlaySoundStereo(SND_MENU_DOOR_OPENING, SOUND_MAX_RIGHT);
2606 else if (door_state & (DOOR_CLOSE_1 | DOOR_CLOSE_2))
2607 PlaySoundStereo(SND_MENU_DOOR_CLOSING, SOUND_MAX_RIGHT);
2610 start = ((door_state & DOOR_NO_DELAY) ? DXSIZE : 0);
2612 for(x=start; x<=DXSIZE; x+=stepsize)
2614 Bitmap *bitmap = pix[PIX_DOOR];
2615 GC gc = bitmap->stored_clip_gc;
2617 WaitUntilDelayReached(&door_delay, door_delay_value);
2619 if (door_state & DOOR_ACTION_1)
2621 int i = (door_state & DOOR_OPEN_1 ? DXSIZE-x : x);
2622 int j = (DXSIZE - i) / 3;
2624 BlitBitmap(pix[PIX_DB_DOOR], drawto,
2625 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1 + i/2,
2626 DXSIZE,DYSIZE - i/2, DX, DY);
2628 ClearRectangle(drawto, DX, DY + DYSIZE - i/2, DXSIZE,i/2);
2630 SetClipOrigin(bitmap, gc, DX - i, (DY + j) - DOOR_GFX_PAGEY1);
2631 BlitBitmapMasked(bitmap, drawto,
2632 DXSIZE, DOOR_GFX_PAGEY1, i, 77,
2633 DX + DXSIZE - i, DY + j);
2634 BlitBitmapMasked(bitmap, drawto,
2635 DXSIZE, DOOR_GFX_PAGEY1 + 140, i, 63,
2636 DX + DXSIZE - i, DY + 140 + j);
2637 SetClipOrigin(bitmap, gc, DX - DXSIZE + i, DY - (DOOR_GFX_PAGEY1 + j));
2638 BlitBitmapMasked(bitmap, drawto,
2639 DXSIZE - i, DOOR_GFX_PAGEY1 + j, i, 77 - j,
2641 BlitBitmapMasked(bitmap, drawto,
2642 DXSIZE-i, DOOR_GFX_PAGEY1 + 140, i, 63,
2645 BlitBitmapMasked(bitmap, drawto,
2646 DXSIZE - i, DOOR_GFX_PAGEY1 + 77, i, 63,
2648 BlitBitmapMasked(bitmap, drawto,
2649 DXSIZE - i, DOOR_GFX_PAGEY1 + 203, i, 77,
2651 SetClipOrigin(bitmap, gc, DX - i, (DY + j) - DOOR_GFX_PAGEY1);
2652 BlitBitmapMasked(bitmap, drawto,
2653 DXSIZE, DOOR_GFX_PAGEY1 + 77, i, 63,
2654 DX + DXSIZE - i, DY + 77 + j);
2655 BlitBitmapMasked(bitmap, drawto,
2656 DXSIZE, DOOR_GFX_PAGEY1 + 203, i, 77 - j,
2657 DX + DXSIZE - i, DY + 203 + j);
2659 redraw_mask |= REDRAW_DOOR_1;
2662 if (door_state & DOOR_ACTION_2)
2664 int i = (door_state & DOOR_OPEN_2 ? VXSIZE - x : x);
2665 int j = (VXSIZE - i) / 3;
2667 BlitBitmap(pix[PIX_DB_DOOR], drawto,
2668 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2 + i/2,
2669 VXSIZE, VYSIZE - i/2, VX, VY);
2671 ClearRectangle(drawto, VX, VY + VYSIZE-i/2, VXSIZE, i/2);
2673 SetClipOrigin(bitmap, gc, VX - i, (VY + j) - DOOR_GFX_PAGEY2);
2674 BlitBitmapMasked(bitmap, drawto,
2675 VXSIZE, DOOR_GFX_PAGEY2, i, VYSIZE / 2,
2676 VX + VXSIZE-i, VY+j);
2677 SetClipOrigin(bitmap, gc,
2678 VX - VXSIZE + i, VY - (DOOR_GFX_PAGEY2 + j));
2679 BlitBitmapMasked(bitmap, drawto,
2680 VXSIZE - i, DOOR_GFX_PAGEY2 + j, i, VYSIZE / 2 - j,
2683 BlitBitmapMasked(bitmap, drawto,
2684 VXSIZE - i, DOOR_GFX_PAGEY2 + VYSIZE / 2,
2685 i, VYSIZE / 2, VX, VY + VYSIZE / 2 - j);
2686 SetClipOrigin(bitmap, gc, VX - i, (VY + j) - DOOR_GFX_PAGEY2);
2687 BlitBitmapMasked(bitmap, drawto,
2688 VXSIZE, DOOR_GFX_PAGEY2 + VYSIZE / 2,
2690 VX + VXSIZE - i, VY + VYSIZE / 2 + j);
2692 redraw_mask |= REDRAW_DOOR_2;
2697 if (game_status == MAINMENU)
2702 if (setup.quick_doors)
2704 StopSound(SND_MENU_DOOR_OPENING);
2705 StopSound(SND_MENU_DOOR_CLOSING);
2708 if (door_state & DOOR_ACTION_1)
2709 door1 = door_state & DOOR_ACTION_1;
2710 if (door_state & DOOR_ACTION_2)
2711 door2 = door_state & DOOR_ACTION_2;
2713 return (door1 | door2);
2716 void DrawSpecialEditorDoor()
2718 /* draw bigger toolbox window */
2719 BlitBitmap(pix[PIX_DOOR], drawto,
2720 DOOR_GFX_PAGEX7, 0, 108, 56, EX - 4, EY - 12);
2722 redraw_mask |= REDRAW_ALL;
2725 void UndrawSpecialEditorDoor()
2727 /* draw normal tape recorder window */
2728 BlitBitmap(pix[PIX_BACK], drawto,
2729 562, 344, 108, 56, EX - 4, EY - 12);
2731 redraw_mask |= REDRAW_ALL;
2735 int ReadPixel(DrawBuffer *bitmap, int x, int y)
2737 XImage *pixel_image;
2738 unsigned long pixel_value;
2740 pixel_image = XGetImage(display, bitmap->drawable,
2741 x, y, 1, 1, AllPlanes, ZPixmap);
2742 pixel_value = XGetPixel(pixel_image, 0, 0);
2744 XDestroyImage(pixel_image);
2750 /* ---------- new tool button stuff ---------------------------------------- */
2752 /* graphic position values for tool buttons */
2753 #define TOOL_BUTTON_YES_XPOS 2
2754 #define TOOL_BUTTON_YES_YPOS 250
2755 #define TOOL_BUTTON_YES_GFX_YPOS 0
2756 #define TOOL_BUTTON_YES_XSIZE 46
2757 #define TOOL_BUTTON_YES_YSIZE 28
2758 #define TOOL_BUTTON_NO_XPOS 52
2759 #define TOOL_BUTTON_NO_YPOS TOOL_BUTTON_YES_YPOS
2760 #define TOOL_BUTTON_NO_GFX_YPOS TOOL_BUTTON_YES_GFX_YPOS
2761 #define TOOL_BUTTON_NO_XSIZE TOOL_BUTTON_YES_XSIZE
2762 #define TOOL_BUTTON_NO_YSIZE TOOL_BUTTON_YES_YSIZE
2763 #define TOOL_BUTTON_CONFIRM_XPOS TOOL_BUTTON_YES_XPOS
2764 #define TOOL_BUTTON_CONFIRM_YPOS TOOL_BUTTON_YES_YPOS
2765 #define TOOL_BUTTON_CONFIRM_GFX_YPOS 30
2766 #define TOOL_BUTTON_CONFIRM_XSIZE 96
2767 #define TOOL_BUTTON_CONFIRM_YSIZE TOOL_BUTTON_YES_YSIZE
2768 #define TOOL_BUTTON_PLAYER_XSIZE 30
2769 #define TOOL_BUTTON_PLAYER_YSIZE 30
2770 #define TOOL_BUTTON_PLAYER_GFX_XPOS 5
2771 #define TOOL_BUTTON_PLAYER_GFX_YPOS 185
2772 #define TOOL_BUTTON_PLAYER_XPOS (5 + TOOL_BUTTON_PLAYER_XSIZE / 2)
2773 #define TOOL_BUTTON_PLAYER_YPOS (215 - TOOL_BUTTON_PLAYER_YSIZE / 2)
2774 #define TOOL_BUTTON_PLAYER1_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2775 + 0 * TOOL_BUTTON_PLAYER_XSIZE)
2776 #define TOOL_BUTTON_PLAYER2_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2777 + 1 * TOOL_BUTTON_PLAYER_XSIZE)
2778 #define TOOL_BUTTON_PLAYER3_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2779 + 0 * TOOL_BUTTON_PLAYER_XSIZE)
2780 #define TOOL_BUTTON_PLAYER4_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2781 + 1 * TOOL_BUTTON_PLAYER_XSIZE)
2782 #define TOOL_BUTTON_PLAYER1_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2783 + 0 * TOOL_BUTTON_PLAYER_YSIZE)
2784 #define TOOL_BUTTON_PLAYER2_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2785 + 0 * TOOL_BUTTON_PLAYER_YSIZE)
2786 #define TOOL_BUTTON_PLAYER3_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2787 + 1 * TOOL_BUTTON_PLAYER_YSIZE)
2788 #define TOOL_BUTTON_PLAYER4_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2789 + 1 * TOOL_BUTTON_PLAYER_YSIZE)
2798 } toolbutton_info[NUM_TOOL_BUTTONS] =
2801 TOOL_BUTTON_YES_XPOS, TOOL_BUTTON_YES_GFX_YPOS,
2802 TOOL_BUTTON_YES_XPOS, TOOL_BUTTON_YES_YPOS,
2803 TOOL_BUTTON_YES_XSIZE, TOOL_BUTTON_YES_YSIZE,
2808 TOOL_BUTTON_NO_XPOS, TOOL_BUTTON_NO_GFX_YPOS,
2809 TOOL_BUTTON_NO_XPOS, TOOL_BUTTON_NO_YPOS,
2810 TOOL_BUTTON_NO_XSIZE, TOOL_BUTTON_NO_YSIZE,
2815 TOOL_BUTTON_CONFIRM_XPOS, TOOL_BUTTON_CONFIRM_GFX_YPOS,
2816 TOOL_BUTTON_CONFIRM_XPOS, TOOL_BUTTON_CONFIRM_YPOS,
2817 TOOL_BUTTON_CONFIRM_XSIZE, TOOL_BUTTON_CONFIRM_YSIZE,
2818 TOOL_CTRL_ID_CONFIRM,
2822 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2823 TOOL_BUTTON_PLAYER1_XPOS, TOOL_BUTTON_PLAYER1_YPOS,
2824 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2825 TOOL_CTRL_ID_PLAYER_1,
2829 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2830 TOOL_BUTTON_PLAYER2_XPOS, TOOL_BUTTON_PLAYER2_YPOS,
2831 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2832 TOOL_CTRL_ID_PLAYER_2,
2836 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2837 TOOL_BUTTON_PLAYER3_XPOS, TOOL_BUTTON_PLAYER3_YPOS,
2838 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2839 TOOL_CTRL_ID_PLAYER_3,
2843 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2844 TOOL_BUTTON_PLAYER4_XPOS, TOOL_BUTTON_PLAYER4_YPOS,
2845 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2846 TOOL_CTRL_ID_PLAYER_4,
2851 void CreateToolButtons()
2855 for (i=0; i<NUM_TOOL_BUTTONS; i++)
2857 Bitmap *gd_bitmap = pix[PIX_DOOR];
2858 Bitmap *deco_bitmap = None;
2859 int deco_x = 0, deco_y = 0, deco_xpos = 0, deco_ypos = 0;
2860 struct GadgetInfo *gi;
2861 unsigned long event_mask;
2862 int gd_xoffset, gd_yoffset;
2863 int gd_x1, gd_x2, gd_y;
2866 event_mask = GD_EVENT_RELEASED;
2868 gd_xoffset = toolbutton_info[i].xpos;
2869 gd_yoffset = toolbutton_info[i].ypos;
2870 gd_x1 = DOOR_GFX_PAGEX4 + gd_xoffset;
2871 gd_x2 = DOOR_GFX_PAGEX3 + gd_xoffset;
2872 gd_y = DOOR_GFX_PAGEY1 + gd_yoffset;
2874 if (id >= TOOL_CTRL_ID_PLAYER_1 && id <= TOOL_CTRL_ID_PLAYER_4)
2876 getMiniGraphicSource(GFX_SPIELER1 + id - TOOL_CTRL_ID_PLAYER_1,
2877 &deco_bitmap, &deco_x, &deco_y);
2878 deco_xpos = (toolbutton_info[i].width - MINI_TILEX) / 2;
2879 deco_ypos = (toolbutton_info[i].height - MINI_TILEY) / 2;
2882 gi = CreateGadget(GDI_CUSTOM_ID, id,
2883 GDI_INFO_TEXT, toolbutton_info[i].infotext,
2884 GDI_X, DX + toolbutton_info[i].x,
2885 GDI_Y, DY + toolbutton_info[i].y,
2886 GDI_WIDTH, toolbutton_info[i].width,
2887 GDI_HEIGHT, toolbutton_info[i].height,
2888 GDI_TYPE, GD_TYPE_NORMAL_BUTTON,
2889 GDI_STATE, GD_BUTTON_UNPRESSED,
2890 GDI_DESIGN_UNPRESSED, gd_bitmap, gd_x1, gd_y,
2891 GDI_DESIGN_PRESSED, gd_bitmap, gd_x2, gd_y,
2892 GDI_DECORATION_DESIGN, deco_bitmap, deco_x, deco_y,
2893 GDI_DECORATION_POSITION, deco_xpos, deco_ypos,
2894 GDI_DECORATION_SIZE, MINI_TILEX, MINI_TILEY,
2895 GDI_DECORATION_SHIFTING, 1, 1,
2896 GDI_EVENT_MASK, event_mask,
2897 GDI_CALLBACK_ACTION, HandleToolButtons,
2901 Error(ERR_EXIT, "cannot create gadget");
2903 tool_gadget[id] = gi;
2907 static void UnmapToolButtons()
2911 for (i=0; i<NUM_TOOL_BUTTONS; i++)
2912 UnmapGadget(tool_gadget[i]);
2915 static void HandleToolButtons(struct GadgetInfo *gi)
2917 request_gadget_id = gi->custom_id;
2920 int get_next_element(int element)
2924 case EL_QUICKSAND_FILLING: return EL_QUICKSAND_FULL;
2925 case EL_QUICKSAND_EMPTYING: return EL_QUICKSAND_EMPTY;
2926 case EL_MAGIC_WALL_FILLING: return EL_MAGIC_WALL_FULL;
2927 case EL_MAGIC_WALL_EMPTYING: return EL_MAGIC_WALL_ACTIVE;
2928 case EL_BD_MAGIC_WALL_FILLING: return EL_BD_MAGIC_WALL_FULL;
2929 case EL_BD_MAGIC_WALL_EMPTYING: return EL_BD_MAGIC_WALL_ACTIVE;
2930 case EL_AMOEBA_DRIPPING: return EL_AMOEBA_WET;
2932 default: return element;
2936 int el2gfx_OLD(int element)
2940 case EL_EMPTY: return -1;
2941 case EL_SAND: return GFX_ERDREICH;
2942 case EL_WALL: return GFX_MAUERWERK;
2943 case EL_WALL_CRUMBLED: return GFX_FELSBODEN;
2944 case EL_ROCK: return GFX_FELSBROCKEN;
2945 case EL_EMERALD: return GFX_EDELSTEIN;
2946 case EL_EXIT_CLOSED: return GFX_AUSGANG_ZU;
2947 case EL_EXIT_OPENING: return GFX_AUSGANG_ACT;
2948 case EL_EXIT_OPEN: return GFX_AUSGANG_AUF;
2949 case EL_SP_EXIT_OPEN: return GFX_SP_EXIT;
2950 case EL_PLAYER1: return GFX_SPIELER1;
2951 case EL_PLAYER2: return GFX_SPIELER2;
2952 case EL_PLAYER3: return GFX_SPIELER3;
2953 case EL_PLAYER4: return GFX_SPIELER4;
2954 case EL_BUG: return GFX_KAEFER;
2955 case EL_BUG_RIGHT: return GFX_KAEFER_RIGHT;
2956 case EL_BUG_UP: return GFX_KAEFER_UP;
2957 case EL_BUG_LEFT: return GFX_KAEFER_LEFT;
2958 case EL_BUG_DOWN: return GFX_KAEFER_DOWN;
2959 case EL_SPACESHIP: return GFX_FLIEGER;
2960 case EL_SPACESHIP_RIGHT: return GFX_FLIEGER_RIGHT;
2961 case EL_SPACESHIP_UP: return GFX_FLIEGER_UP;
2962 case EL_SPACESHIP_LEFT: return GFX_FLIEGER_LEFT;
2963 case EL_SPACESHIP_DOWN: return GFX_FLIEGER_DOWN;
2964 case EL_BD_BUTTERFLY: return GFX_BUTTERFLY;
2965 case EL_BD_BUTTERFLY_RIGHT: return GFX_BUTTERFLY_RIGHT;
2966 case EL_BD_BUTTERFLY_UP: return GFX_BUTTERFLY_UP;
2967 case EL_BD_BUTTERFLY_LEFT: return GFX_BUTTERFLY_LEFT;
2968 case EL_BD_BUTTERFLY_DOWN: return GFX_BUTTERFLY_DOWN;
2969 case EL_BD_FIREFLY: return GFX_FIREFLY;
2970 case EL_BD_FIREFLY_RIGHT: return GFX_FIREFLY_RIGHT;
2971 case EL_BD_FIREFLY_UP: return GFX_FIREFLY_UP;
2972 case EL_BD_FIREFLY_LEFT: return GFX_FIREFLY_LEFT;
2973 case EL_BD_FIREFLY_DOWN: return GFX_FIREFLY_DOWN;
2974 case EL_YAMYAM: return GFX_MAMPFER;
2975 case EL_ROBOT: return GFX_ROBOT;
2976 case EL_STEELWALL: return GFX_BETON;
2977 case EL_DIAMOND: return GFX_DIAMANT;
2978 case EL_QUICKSAND_EMPTY: return GFX_MORAST_LEER;
2979 case EL_QUICKSAND_FULL: return GFX_MORAST_VOLL;
2980 case EL_QUICKSAND_EMPTYING: return GFX_MORAST_LEER;
2981 case EL_AMOEBA_DROP: return GFX_TROPFEN;
2982 case EL_BOMB: return GFX_BOMBE;
2983 case EL_MAGIC_WALL: return GFX_MAGIC_WALL_OFF;
2984 case EL_MAGIC_WALL_ACTIVE: return GFX_MAGIC_WALL_EMPTY;
2985 case EL_MAGIC_WALL_EMPTYING: return GFX_MAGIC_WALL_EMPTY;
2986 case EL_MAGIC_WALL_FULL: return GFX_MAGIC_WALL_FULL;
2987 case EL_MAGIC_WALL_DEAD: return GFX_MAGIC_WALL_DEAD;
2988 case EL_ACID: return GFX_SALZSAEURE;
2989 case EL_AMOEBA_DEAD: return GFX_AMOEBE_TOT;
2990 case EL_AMOEBA_WET: return GFX_AMOEBE_NASS;
2991 case EL_AMOEBA_DRY: return GFX_AMOEBE_NORM;
2992 case EL_AMOEBA_FULL: return GFX_AMOEBE_VOLL;
2993 case EL_BD_AMOEBA: return GFX_AMOEBE_BD;
2994 case EL_AMOEBA_TO_DIAMOND: return GFX_AMOEBA2DIAM;
2995 case EL_AMOEBA_DRIPPING: return GFX_AMOEBE_NASS;
2996 case EL_NUT: return GFX_KOKOSNUSS;
2997 case EL_GAMEOFLIFE: return GFX_LIFE;
2998 case EL_BIOMAZE: return GFX_LIFE_ASYNC;
2999 case EL_DYNAMITE_ACTIVE: return GFX_DYNAMIT;
3000 case EL_STONEBLOCK: return GFX_BADEWANNE;
3001 case EL_ACIDPOOL_TOPLEFT: return GFX_BADEWANNE1;
3002 case EL_ACIDPOOL_TOPRIGHT: return GFX_BADEWANNE2;
3003 case EL_ACIDPOOL_BOTTOMLEFT: return GFX_BADEWANNE3;
3004 case EL_ACIDPOOL_BOTTOM: return GFX_BADEWANNE4;
3005 case EL_ACIDPOOL_BOTTOMRIGHT: return GFX_BADEWANNE5;
3006 case EL_ROBOT_WHEEL: return GFX_ABLENK_AUS;
3007 case EL_ROBOT_WHEEL_ACTIVE: return GFX_ABLENK_EIN;
3008 case EL_KEY1: return GFX_SCHLUESSEL1;
3009 case EL_KEY2: return GFX_SCHLUESSEL2;
3010 case EL_KEY3: return GFX_SCHLUESSEL3;
3011 case EL_KEY4: return GFX_SCHLUESSEL4;
3012 case EL_GATE1: return GFX_PFORTE1;
3013 case EL_GATE2: return GFX_PFORTE2;
3014 case EL_GATE3: return GFX_PFORTE3;
3015 case EL_GATE4: return GFX_PFORTE4;
3016 case EL_GATE1_GRAY: return GFX_PFORTE1X;
3017 case EL_GATE2_GRAY: return GFX_PFORTE2X;
3018 case EL_GATE3_GRAY: return GFX_PFORTE3X;
3019 case EL_GATE4_GRAY: return GFX_PFORTE4X;
3020 case EL_DYNAMITE: return GFX_DYNAMIT_AUS;
3021 case EL_PACMAN: return GFX_PACMAN;
3022 case EL_PACMAN_RIGHT: return GFX_PACMAN_RIGHT;
3023 case EL_PACMAN_UP: return GFX_PACMAN_UP;
3024 case EL_PACMAN_LEFT: return GFX_PACMAN_LEFT;
3025 case EL_PACMAN_DOWN: return GFX_PACMAN_DOWN;
3026 case EL_INVISIBLE_WALL: return GFX_UNSICHTBAR;
3027 case EL_INVISIBLE_WALL_ACTIVE: return GFX_UNSICHTBAR_ON;
3028 case EL_WALL_EMERALD: return GFX_ERZ_EDEL;
3029 case EL_WALL_DIAMOND: return GFX_ERZ_DIAM;
3030 case EL_LAMP: return GFX_BIRNE_AUS;
3031 case EL_LAMP_ACTIVE: return GFX_BIRNE_EIN;
3032 case EL_TIME_ORB_FULL: return GFX_ZEIT_VOLL;
3033 case EL_TIME_ORB_EMPTY: return GFX_ZEIT_LEER;
3034 case EL_WALL_GROWING: return GFX_MAUER_LEBT;
3035 case EL_WALL_GROWING_X: return GFX_MAUER_X;
3036 case EL_WALL_GROWING_Y: return GFX_MAUER_Y;
3037 case EL_WALL_GROWING_XY: return GFX_MAUER_XY;
3038 case EL_BD_DIAMOND: return GFX_EDELSTEIN_BD;
3039 case EL_EMERALD_YELLOW: return GFX_EDELSTEIN_GELB;
3040 case EL_EMERALD_RED: return GFX_EDELSTEIN_ROT;
3041 case EL_EMERALD_PURPLE: return GFX_EDELSTEIN_LILA;
3042 case EL_WALL_BD_DIAMOND: return GFX_ERZ_EDEL_BD;
3043 case EL_WALL_EMERALD_YELLOW: return GFX_ERZ_EDEL_GELB;
3044 case EL_WALL_EMERALD_RED: return GFX_ERZ_EDEL_ROT;
3045 case EL_WALL_EMERALD_PURPLE: return GFX_ERZ_EDEL_LILA;
3046 case EL_DARK_YAMYAM: return GFX_MAMPFER2;
3047 case EL_BD_MAGIC_WALL: return GFX_MAGIC_WALL_BD_OFF;
3048 case EL_BD_MAGIC_WALL_ACTIVE: return GFX_MAGIC_WALL_BD_EMPTY;
3049 case EL_BD_MAGIC_WALL_EMPTYING: return GFX_MAGIC_WALL_BD_EMPTY;
3050 case EL_BD_MAGIC_WALL_FULL: return GFX_MAGIC_WALL_BD_FULL;
3051 case EL_BD_MAGIC_WALL_DEAD: return GFX_MAGIC_WALL_BD_DEAD;
3052 case EL_DYNABOMB_PLAYER1_ACTIVE: return GFX_DYNABOMB;
3053 case EL_DYNABOMB_PLAYER2_ACTIVE: return GFX_DYNABOMB;
3054 case EL_DYNABOMB_PLAYER3_ACTIVE: return GFX_DYNABOMB;
3055 case EL_DYNABOMB_PLAYER4_ACTIVE: return GFX_DYNABOMB;
3056 case EL_DYNABOMB_NR: return GFX_DYNABOMB_NR;
3057 case EL_DYNABOMB_SZ: return GFX_DYNABOMB_SZ;
3058 case EL_DYNABOMB_XL: return GFX_DYNABOMB_XL;
3059 case EL_SOKOBAN_OBJECT: return GFX_SOKOBAN_OBJEKT;
3060 case EL_SOKOBAN_FIELD_EMPTY: return GFX_SOKOBAN_FELD_LEER;
3061 case EL_SOKOBAN_FIELD_FULL: return GFX_SOKOBAN_FELD_VOLL;
3062 case EL_MOLE: return GFX_MOLE;
3063 case EL_PENGUIN: return GFX_PINGUIN;
3064 case EL_PIG: return GFX_SCHWEIN;
3065 case EL_DRAGON: return GFX_DRACHE;
3066 case EL_SATELLITE: return GFX_SONDE;
3067 case EL_ARROW_BLUE_LEFT: return GFX_PFEIL_LEFT;
3068 case EL_ARROW_BLUE_RIGHT: return GFX_PFEIL_RIGHT;
3069 case EL_ARROW_BLUE_UP: return GFX_PFEIL_UP;
3070 case EL_ARROW_BLUE_DOWN: return GFX_PFEIL_DOWN;
3071 case EL_SPEED_PILL: return GFX_SPEED_PILL;
3072 case EL_SP_TERMINAL_ACTIVE: return GFX_SP_TERMINAL;
3073 case EL_SP_BUGGY_BASE_ACTIVE: return GFX_SP_BUG_ACTIVE;
3074 case EL_SP_ZONK: return GFX_SP_ZONK;
3075 /* ^^^^^^^^^^ non-standard position in supaplex graphic set! */
3076 case EL_INVISIBLE_STEELWALL: return GFX_INVISIBLE_STEEL;
3077 case EL_INVISIBLE_STEELWALL_ACTIVE: return GFX_INVISIBLE_STEEL_ON;
3078 case EL_BLACK_ORB: return GFX_BLACK_ORB;
3079 case EL_EM_GATE1: return GFX_EM_GATE_1;
3080 case EL_EM_GATE2: return GFX_EM_GATE_2;
3081 case EL_EM_GATE3: return GFX_EM_GATE_3;
3082 case EL_EM_GATE4: return GFX_EM_GATE_4;
3083 case EL_EM_GATE1_GRAY: return GFX_EM_GATE_1X;
3084 case EL_EM_GATE2_GRAY: return GFX_EM_GATE_2X;
3085 case EL_EM_GATE3_GRAY: return GFX_EM_GATE_3X;
3086 case EL_EM_GATE4_GRAY: return GFX_EM_GATE_4X;
3087 case EL_EM_KEY1_FILE: return GFX_EM_KEY_1;
3088 case EL_EM_KEY2_FILE: return GFX_EM_KEY_2;
3089 case EL_EM_KEY3_FILE: return GFX_EM_KEY_3;
3090 case EL_EM_KEY4_FILE: return GFX_EM_KEY_4;
3091 case EL_EM_KEY1: return GFX_EM_KEY_1;
3092 case EL_EM_KEY2: return GFX_EM_KEY_2;
3093 case EL_EM_KEY3: return GFX_EM_KEY_3;
3094 case EL_EM_KEY4: return GFX_EM_KEY_4;
3095 case EL_PEARL: return GFX_PEARL;
3096 case EL_CRYSTAL: return GFX_CRYSTAL;
3097 case EL_WALL_PEARL: return GFX_WALL_PEARL;
3098 case EL_WALL_CRYSTAL: return GFX_WALL_CRYSTAL;
3099 case EL_DOOR_WHITE: return GFX_DOOR_WHITE;
3100 case EL_DOOR_WHITE_GRAY: return GFX_DOOR_WHITE_GRAY;
3101 case EL_KEY_WHITE: return GFX_KEY_WHITE;
3102 case EL_SHIELD_NORMAL: return GFX_SHIELD_PASSIVE;
3103 case EL_SHIELD_DEADLY: return GFX_SHIELD_ACTIVE;
3104 case EL_EXTRA_TIME: return GFX_EXTRA_TIME;
3105 case EL_SWITCHGATE_OPEN: return GFX_SWITCHGATE_OPEN;
3106 case EL_SWITCHGATE_CLOSED: return GFX_SWITCHGATE_CLOSED;
3107 case EL_SWITCHGATE_SWITCH_UP: return GFX_SWITCHGATE_SWITCH_1;
3108 case EL_SWITCHGATE_SWITCH_DOWN: return GFX_SWITCHGATE_SWITCH_2;
3109 case EL_CONVEYOR_BELT1_LEFT: return GFX_BELT1_LEFT;
3110 case EL_CONVEYOR_BELT1_MIDDLE: return GFX_BELT1_MIDDLE;
3111 case EL_CONVEYOR_BELT1_RIGHT: return GFX_BELT1_RIGHT;
3112 case EL_CONVEYOR_BELT1_LEFT_ACTIVE: return GFX_BELT1_LEFT;
3113 case EL_CONVEYOR_BELT1_MIDDLE_ACTIVE:return GFX_BELT1_MIDDLE;
3114 case EL_CONVEYOR_BELT1_RIGHT_ACTIVE:return GFX_BELT1_RIGHT;
3115 case EL_CONVEYOR_BELT1_SWITCH_LEFT: return GFX_BELT1_SWITCH_LEFT;
3116 case EL_CONVEYOR_BELT1_SWITCH_MIDDLE:return GFX_BELT1_SWITCH_MIDDLE;
3117 case EL_CONVEYOR_BELT1_SWITCH_RIGHT:return GFX_BELT1_SWITCH_RIGHT;
3118 case EL_CONVEYOR_BELT2_LEFT: return GFX_BELT2_LEFT;
3119 case EL_CONVEYOR_BELT2_MIDDLE: return GFX_BELT2_MIDDLE;
3120 case EL_CONVEYOR_BELT2_RIGHT: return GFX_BELT2_RIGHT;
3121 case EL_CONVEYOR_BELT2_LEFT_ACTIVE: return GFX_BELT2_LEFT;
3122 case EL_CONVEYOR_BELT2_MIDDLE_ACTIVE:return GFX_BELT2_MIDDLE;
3123 case EL_CONVEYOR_BELT2_RIGHT_ACTIVE:return GFX_BELT2_RIGHT;
3124 case EL_CONVEYOR_BELT2_SWITCH_LEFT: return GFX_BELT2_SWITCH_LEFT;
3125 case EL_CONVEYOR_BELT2_SWITCH_MIDDLE:return GFX_BELT2_SWITCH_MIDDLE;
3126 case EL_CONVEYOR_BELT2_SWITCH_RIGHT:return GFX_BELT2_SWITCH_RIGHT;
3127 case EL_CONVEYOR_BELT3_LEFT: return GFX_BELT3_LEFT;
3128 case EL_CONVEYOR_BELT3_MIDDLE: return GFX_BELT3_MIDDLE;
3129 case EL_CONVEYOR_BELT3_RIGHT: return GFX_BELT3_RIGHT;
3130 case EL_CONVEYOR_BELT3_LEFT_ACTIVE: return GFX_BELT3_LEFT;
3131 case EL_CONVEYOR_BELT3_MIDDLE_ACTIVE:return GFX_BELT3_MIDDLE;
3132 case EL_CONVEYOR_BELT3_RIGHT_ACTIVE:return GFX_BELT3_RIGHT;
3133 case EL_CONVEYOR_BELT3_SWITCH_LEFT: return GFX_BELT3_SWITCH_LEFT;
3134 case EL_CONVEYOR_BELT3_SWITCH_MIDDLE:return GFX_BELT3_SWITCH_MIDDLE;
3135 case EL_CONVEYOR_BELT3_SWITCH_RIGHT:return GFX_BELT3_SWITCH_RIGHT;
3136 case EL_CONVEYOR_BELT4_LEFT: return GFX_BELT4_LEFT;
3137 case EL_CONVEYOR_BELT4_MIDDLE: return GFX_BELT4_MIDDLE;
3138 case EL_CONVEYOR_BELT4_RIGHT: return GFX_BELT4_RIGHT;
3139 case EL_CONVEYOR_BELT4_LEFT_ACTIVE: return GFX_BELT4_LEFT;
3140 case EL_CONVEYOR_BELT4_MIDDLE_ACTIVE:return GFX_BELT4_MIDDLE;
3141 case EL_CONVEYOR_BELT4_RIGHT_ACTIVE:return GFX_BELT4_RIGHT;
3142 case EL_CONVEYOR_BELT4_SWITCH_LEFT: return GFX_BELT4_SWITCH_LEFT;
3143 case EL_CONVEYOR_BELT4_SWITCH_MIDDLE:return GFX_BELT4_SWITCH_MIDDLE;
3144 case EL_CONVEYOR_BELT4_SWITCH_RIGHT:return GFX_BELT4_SWITCH_RIGHT;
3145 case EL_LANDMINE: return GFX_LANDMINE;
3146 case EL_ENVELOPE: return GFX_ENVELOPE;
3147 case EL_LIGHT_SWITCH: return GFX_LIGHT_SWITCH_OFF;
3148 case EL_LIGHT_SWITCH_ACTIVE: return GFX_LIGHT_SWITCH_ON;
3149 case EL_SIGN_EXCLAMATION: return GFX_SIGN_EXCLAMATION;
3150 case EL_SIGN_RADIOACTIVITY: return GFX_SIGN_RADIOACTIVITY;
3151 case EL_SIGN_STOP: return GFX_SIGN_STOP;
3152 case EL_SIGN_WHEELCHAIR: return GFX_SIGN_WHEELCHAIR;
3153 case EL_SIGN_PARKING: return GFX_SIGN_PARKING;
3154 case EL_SIGN_ONEWAY: return GFX_SIGN_ONEWAY;
3155 case EL_SIGN_HEART: return GFX_SIGN_HEART;
3156 case EL_SIGN_TRIANGLE: return GFX_SIGN_TRIANGLE;
3157 case EL_SIGN_ROUND: return GFX_SIGN_ROUND;
3158 case EL_SIGN_EXIT: return GFX_SIGN_EXIT;
3159 case EL_SIGN_YINYANG: return GFX_SIGN_YINYANG;
3160 case EL_SIGN_OTHER: return GFX_SIGN_OTHER;
3161 case EL_MOLE_LEFT: return GFX_MOLE_LEFT;
3162 case EL_MOLE_RIGHT: return GFX_MOLE_RIGHT;
3163 case EL_MOLE_UP: return GFX_MOLE_UP;
3164 case EL_MOLE_DOWN: return GFX_MOLE_DOWN;
3165 case EL_STEELWALL_SLANTED: return GFX_STEEL_SLANTED;
3166 case EL_INVISIBLE_SAND: return GFX_SAND_INVISIBLE;
3167 case EL_INVISIBLE_SAND_ACTIVE: return GFX_SAND_INVISIBLE_ON;
3168 case EL_DX_UNKNOWN_15: return GFX_DX_UNKNOWN_15;
3169 case EL_DX_UNKNOWN_42: return GFX_DX_UNKNOWN_42;
3170 case EL_TIMEGATE_OPEN: return GFX_TIMEGATE_OPEN;
3171 case EL_TIMEGATE_CLOSED: return GFX_TIMEGATE_CLOSED;
3172 case EL_TIMEGATE_SWITCH_ACTIVE: return GFX_TIMEGATE_SWITCH;
3173 case EL_TIMEGATE_SWITCH: return GFX_TIMEGATE_SWITCH;
3174 case EL_BALLOON: return GFX_BALLOON;
3175 case EL_BALLOON_SEND_LEFT: return GFX_BALLOON_SEND_LEFT;
3176 case EL_BALLOON_SEND_RIGHT: return GFX_BALLOON_SEND_RIGHT;
3177 case EL_BALLOON_SEND_UP: return GFX_BALLOON_SEND_UP;
3178 case EL_BALLOON_SEND_DOWN: return GFX_BALLOON_SEND_DOWN;
3179 case EL_BALLOON_SEND_ANY_DIRECTION: return GFX_BALLOON_SEND_ANY;
3180 case EL_EMC_STEELWALL1: return GFX_EMC_STEEL_WALL_1;
3181 case EL_EMC_STEELWALL2: return GFX_EMC_STEEL_WALL_2;
3182 case EL_EMC_STEELWALL3: return GFX_EMC_STEEL_WALL_3;
3183 case EL_EMC_STEELWALL4: return GFX_EMC_STEEL_WALL_4;
3184 case EL_EMC_WALL_PILLAR_UPPER: return GFX_EMC_WALL_1;
3185 case EL_EMC_WALL_PILLAR_MIDDLE: return GFX_EMC_WALL_2;
3186 case EL_EMC_WALL_PILLAR_LOWER: return GFX_EMC_WALL_3;
3187 case EL_EMC_WALL4: return GFX_EMC_WALL_4;
3188 case EL_EMC_WALL5: return GFX_EMC_WALL_5;
3189 case EL_EMC_WALL6: return GFX_EMC_WALL_6;
3190 case EL_EMC_WALL7: return GFX_EMC_WALL_7;
3191 case EL_EMC_WALL8: return GFX_EMC_WALL_8;
3192 case EL_TUBE_ALL: return GFX_TUBE_CROSS;
3193 case EL_TUBE_VERTICAL: return GFX_TUBE_VERTICAL;
3194 case EL_TUBE_HORIZONTAL: return GFX_TUBE_HORIZONTAL;
3195 case EL_TUBE_VERTICAL_LEFT: return GFX_TUBE_VERT_LEFT;
3196 case EL_TUBE_VERTICAL_RIGHT: return GFX_TUBE_VERT_RIGHT;
3197 case EL_TUBE_HORIZONTAL_UP: return GFX_TUBE_HORIZ_UP;
3198 case EL_TUBE_HORIZONTAL_DOWN: return GFX_TUBE_HORIZ_DOWN;
3199 case EL_TUBE_LEFT_UP: return GFX_TUBE_LEFT_UP;
3200 case EL_TUBE_LEFT_DOWN: return GFX_TUBE_LEFT_DOWN;
3201 case EL_TUBE_RIGHT_UP: return GFX_TUBE_RIGHT_UP;
3202 case EL_TUBE_RIGHT_DOWN: return GFX_TUBE_RIGHT_DOWN;
3203 case EL_SPRING: return GFX_SPRING;
3204 case EL_SPRING_MOVING: return GFX_SPRING;
3205 case EL_TRAP: return GFX_TRAP_INACTIVE;
3206 case EL_TRAP_ACTIVE: return GFX_TRAP_ACTIVE;
3207 case EL_BD_WALL: return GFX_BD_WALL;
3208 case EL_BD_ROCK: return GFX_BD_ROCK;
3209 case EL_DX_SUPABOMB: return GFX_DX_SUPABOMB;
3210 case EL_SP_MURPHY_CLONE: return GFX_SP_MURPHY_CLONE;
3214 if (IS_CHAR(element))
3215 return GFX_CHAR_START + (element - EL_CHAR_START);
3216 else if (element >= EL_SP_START && element <= EL_SP_END)
3218 int nr_element = element - EL_SP_START;
3219 int gfx_per_line = 8;
3221 (nr_element / gfx_per_line) * SP_PER_LINE +
3222 (nr_element % gfx_per_line);
3224 return GFX_START_ROCKSSP + nr_graphic;
3232 int el2gfx(int element)
3235 int graphic_OLD = el2gfx_OLD(element);
3240 int graphic_NEW = element_info[element].graphic[GFX_ACTION_DEFAULT];
3243 int graphic_OLD = el2gfx_OLD(element);
3245 if (element >= MAX_ELEMENTS)
3247 Error(ERR_WARN, "el2gfx: element == %d >= MAX_ELEMENTS", element);
3250 if (graphic_NEW != graphic_OLD)
3252 Error(ERR_WARN, "el2gfx: graphic_NEW (%d) != graphic_OLD (%d)",
3253 graphic_NEW, graphic_OLD);
3261 int el2img(int element)
3264 int graphic_NEW = element_info[element].graphic[GFX_ACTION_DEFAULT];
3271 case EL_BD_BUTTERFLY: return IMG_BD_BUTTERFLY;
3272 case EL_BD_FIREFLY: return IMG_BD_FIREFLY;
3273 case EL_SP_ELECTRON: return IMG_SP_ELECTRON;
3283 int el_dir2img(int element, int direction)
3285 return el_dir_act2img(element, direction, GFX_ACTION_DEFAULT);
3288 int el_dir_act2img(int element, int direction, int action)
3290 action = graphics_action_mapping[action];
3291 direction = MV_DIR_BIT(direction);
3293 return element_info[element].direction_graphic[action][direction];