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 static 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_PINGPONG) /* use border frames once */
722 int max_anim_frames = 2 * num_frames - 2;
724 frame = (sync_frame % (delay * max_anim_frames)) / delay;
725 frame = (frame < num_frames ? frame : max_anim_frames - frame);
727 else if (mode & ANIM_PINGPONG2) /* use border frames twice */
729 int max_anim_frames = 2 * num_frames;
731 frame = (sync_frame % (delay * max_anim_frames)) / delay;
732 frame = (frame < num_frames ? frame : max_anim_frames - frame - 1);
734 else /* mode == ANIM_NORMAL || mode == ANIM_REVERSE */
735 frame = (sync_frame % (delay * num_frames)) / delay;
737 if (mode & ANIM_REVERSE) /* use reverse animation direction */
738 frame = num_frames - frame - 1;
743 void DrawGraphicAnimationExt(int x, int y, int graphic,
744 int frames, int delay, int mode, int mask_mode)
746 int phase = getGraphicAnimationPhase(frames, delay, mode);
748 if (!(FrameCounter % delay) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
750 if (mask_mode == USE_MASKING)
751 DrawGraphicThruMask(SCREENX(x), SCREENY(y), graphic + phase);
753 DrawGraphic(SCREENX(x), SCREENY(y), graphic + phase);
757 void DrawNewGraphicAnimationExt(int x, int y, int graphic, int mask_mode)
759 int delay = new_graphic_info[graphic].anim_delay;
761 if (!(FrameCounter % delay) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
763 int frame = getNewGraphicAnimationFrame(graphic, -1);
765 if (mask_mode == USE_MASKING)
766 DrawNewGraphicThruMask(SCREENX(x), SCREENY(y), graphic, frame);
768 DrawNewGraphic(SCREENX(x), SCREENY(y), graphic, frame);
772 void DrawGraphicAnimation(int x, int y, int graphic,
773 int frames, int delay, int mode)
775 DrawGraphicAnimationExt(x, y, graphic, frames, delay, mode, NO_MASKING);
778 void DrawNewGraphicAnimation(int x, int y, int graphic)
780 DrawNewGraphicAnimationExt(x, y, graphic, NO_MASKING);
783 void DrawGraphicAnimationThruMask(int x, int y, int graphic,
784 int frames, int delay, int mode)
786 DrawGraphicAnimationExt(x, y, graphic, frames, delay, mode, USE_MASKING);
789 static void DrawGraphicAnimationShiftedThruMask(int sx, int sy,
792 int frames, int delay,
795 int phase = getGraphicAnimationPhase(frames, delay, mode);
797 DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic + phase, NO_CUTTING);
800 void getGraphicSource(int graphic, Bitmap **bitmap, int *x, int *y)
802 if (graphic >= 0 && graphic_info[graphic].bitmap != NULL)
804 *bitmap = graphic_info[graphic].bitmap;
805 *x = graphic_info[graphic].src_x;
806 *y = graphic_info[graphic].src_y;
808 else if (graphic >= GFX_START_ROCKSELEMENTS &&
809 graphic <= GFX_END_ROCKSELEMENTS)
811 graphic -= GFX_START_ROCKSELEMENTS;
812 *bitmap = pix[PIX_ELEMENTS];
813 *x = (graphic % GFX_PER_LINE) * TILEX;
814 *y = (graphic / GFX_PER_LINE) * TILEY;
816 else if (graphic >= GFX_START_ROCKSHEROES && graphic <= GFX_END_ROCKSHEROES)
818 graphic -= GFX_START_ROCKSHEROES;
819 *bitmap = pix[PIX_HEROES];
820 *x = (graphic % HEROES_PER_LINE) * TILEX;
821 *y = (graphic / HEROES_PER_LINE) * TILEY;
823 else if (graphic >= GFX_START_ROCKSSP && graphic <= GFX_END_ROCKSSP)
825 graphic -= GFX_START_ROCKSSP;
826 *bitmap = pix[PIX_SP];
827 *x = (graphic % SP_PER_LINE) * TILEX;
828 *y = (graphic / SP_PER_LINE) * TILEY;
830 else if (graphic >= GFX_START_ROCKSDC && graphic <= GFX_END_ROCKSDC)
832 graphic -= GFX_START_ROCKSDC;
833 *bitmap = pix[PIX_DC];
834 *x = (graphic % DC_PER_LINE) * TILEX;
835 *y = (graphic / DC_PER_LINE) * TILEY;
837 else if (graphic >= GFX_START_ROCKSMORE && graphic <= GFX_END_ROCKSMORE)
839 graphic -= GFX_START_ROCKSMORE;
840 *bitmap = pix[PIX_MORE];
841 *x = (graphic % MORE_PER_LINE) * TILEX;
842 *y = (graphic / MORE_PER_LINE) * TILEY;
844 else if (graphic >= GFX_START_ROCKSFONT && graphic <= GFX_END_ROCKSFONT)
846 graphic -= GFX_START_ROCKSFONT;
847 *bitmap = pix[PIX_FONT_EM];
848 *x = (graphic % FONT_CHARS_PER_LINE) * TILEX;
849 *y = (graphic / FONT_CHARS_PER_LINE) * TILEY;
853 *bitmap = pix[PIX_SP];
859 void DrawGraphic(int x, int y, int graphic)
862 if (!IN_SCR_FIELD(x, y))
864 printf("DrawGraphic(): x = %d, y = %d, graphic = %d\n", x, y, graphic);
865 printf("DrawGraphic(): This should never happen!\n");
870 DrawGraphicExt(drawto_field, FX + x * TILEX, FY + y * TILEY, graphic);
874 void DrawNewGraphic(int x, int y, int graphic, int frame)
877 if (!IN_SCR_FIELD(x, y))
879 printf("DrawNewGraphic(): x = %d, y = %d, graphic = %d\n", x, y, graphic);
880 printf("DrawNewGraphic(): This should never happen!\n");
885 DrawNewGraphicExt(drawto_field, FX + x * TILEX, FY + y * TILEY,
890 void DrawGraphicExt(DrawBuffer *dst_bitmap, int x, int y, int graphic)
895 getGraphicSource(graphic, &src_bitmap, &src_x, &src_y);
896 BlitBitmap(src_bitmap, dst_bitmap, src_x, src_y, TILEX, TILEY, x, y);
899 void DrawNewGraphicExt(DrawBuffer *dst_bitmap, int x, int y, int graphic,
902 Bitmap *src_bitmap = new_graphic_info[graphic].bitmap;
903 int src_x = new_graphic_info[graphic].src_x;
904 int src_y = new_graphic_info[graphic].src_y;
906 if (new_graphic_info[graphic].anim_vertical)
907 src_y += frame * TILEY;
909 src_x += frame * TILEX;
911 BlitBitmap(src_bitmap, dst_bitmap, src_x, src_y, TILEX, TILEY, x, y);
914 void DrawGraphicThruMask(int x, int y, int graphic)
917 if (!IN_SCR_FIELD(x, y))
919 printf("DrawGraphicThruMask(): x = %d,y = %d, graphic = %d\n",x,y,graphic);
920 printf("DrawGraphicThruMask(): This should never happen!\n");
925 DrawGraphicThruMaskExt(drawto_field, FX + x * TILEX, FY + y *TILEY, graphic);
929 void DrawNewGraphicThruMask(int x, int y, int graphic, int frame)
932 if (!IN_SCR_FIELD(x, y))
934 printf("DrawGraphicThruMask(): x = %d,y = %d, graphic = %d\n",x,y,graphic);
935 printf("DrawGraphicThruMask(): This should never happen!\n");
940 DrawNewGraphicThruMaskExt(drawto_field, FX + x * TILEX, FY + y *TILEY,
945 void DrawGraphicThruMaskExt(DrawBuffer *d, int dest_x, int dest_y, int graphic)
952 if (graphic == GFX_LEERRAUM)
955 getGraphicSource(graphic, &src_bitmap, &src_x, &src_y);
956 drawing_gc = src_bitmap->stored_clip_gc;
958 if (tile_clipmask[tile] != None)
960 SetClipMask(src_bitmap, tile_clip_gc, tile_clipmask[tile]);
961 SetClipOrigin(src_bitmap, tile_clip_gc, dest_x, dest_y);
962 BlitBitmapMasked(src_bitmap, d,
963 src_x, src_y, TILEX, TILEY, dest_x, dest_y);
969 printf("DrawGraphicThruMask(): tile '%d' needs clipping!\n", tile);
973 SetClipOrigin(src_bitmap, drawing_gc, dest_x - src_x, dest_y - src_y);
974 BlitBitmapMasked(src_bitmap, d,
975 src_x, src_y, TILEX, TILEY, dest_x, dest_y);
979 void DrawNewGraphicThruMaskExt(DrawBuffer *d, int dest_x, int dest_y,
980 int graphic, int frame)
982 Bitmap *src_bitmap = new_graphic_info[graphic].bitmap;
983 GC drawing_gc = src_bitmap->stored_clip_gc;
984 int src_x = new_graphic_info[graphic].src_x;
985 int src_y = new_graphic_info[graphic].src_y;
987 if (new_graphic_info[graphic].anim_vertical)
988 src_y += frame * TILEY;
990 src_x += frame * TILEX;
992 SetClipOrigin(src_bitmap, drawing_gc, dest_x - src_x, dest_y - src_y);
993 BlitBitmapMasked(src_bitmap, d, src_x, src_y, TILEX, TILEY, dest_x, dest_y);
996 void DrawMiniGraphic(int x, int y, int graphic)
998 DrawMiniGraphicExt(drawto, SX + x*MINI_TILEX, SY + y*MINI_TILEY, graphic);
999 MarkTileDirty(x/2, y/2);
1002 void getMiniGraphicSource(int graphic, Bitmap **bitmap, int *x, int *y)
1004 if (graphic >= GFX_START_ROCKSELEMENTS && graphic <= GFX_END_ROCKSELEMENTS)
1006 graphic -= GFX_START_ROCKSELEMENTS;
1007 *bitmap = pix[PIX_ELEMENTS];
1008 *x = MINI_GFX_STARTX + (graphic % MINI_GFX_PER_LINE) * MINI_TILEX;
1009 *y = MINI_GFX_STARTY + (graphic / MINI_GFX_PER_LINE) * MINI_TILEY;
1011 else if (graphic >= GFX_START_ROCKSSP && graphic <= GFX_END_ROCKSSP)
1013 graphic -= GFX_START_ROCKSSP;
1014 *bitmap = pix[PIX_SP];
1015 *x = MINI_SP_STARTX + (graphic % MINI_SP_PER_LINE) * MINI_TILEX;
1016 *y = MINI_SP_STARTY + (graphic / MINI_SP_PER_LINE) * MINI_TILEY;
1018 else if (graphic >= GFX_START_ROCKSDC && graphic <= GFX_END_ROCKSDC)
1020 graphic -= GFX_START_ROCKSDC;
1021 *bitmap = pix[PIX_DC];
1022 *x = MINI_DC_STARTX + (graphic % MINI_DC_PER_LINE) * MINI_TILEX;
1023 *y = MINI_DC_STARTY + (graphic / MINI_DC_PER_LINE) * MINI_TILEY;
1025 else if (graphic >= GFX_START_ROCKSMORE && graphic <= GFX_END_ROCKSMORE)
1027 graphic -= GFX_START_ROCKSMORE;
1028 *bitmap = pix[PIX_MORE];
1029 *x = MINI_MORE_STARTX + (graphic % MINI_MORE_PER_LINE) * MINI_TILEX;
1030 *y = MINI_MORE_STARTY + (graphic / MINI_MORE_PER_LINE) * MINI_TILEY;
1032 else if (graphic >= GFX_START_ROCKSFONT && graphic <= GFX_END_ROCKSFONT)
1034 graphic -= GFX_START_ROCKSFONT;
1035 *bitmap = pix[PIX_FONT_EM];
1036 *x = MINI_FONT_STARTX + (graphic % FONT_CHARS_PER_LINE) * FONT4_XSIZE;
1037 *y = MINI_FONT_STARTY + (graphic / FONT_CHARS_PER_LINE) * FONT4_YSIZE;
1041 *bitmap = pix[PIX_SP];
1042 *x = MINI_SP_STARTX;
1043 *y = MINI_SP_STARTY;
1047 void DrawMiniGraphicExt(DrawBuffer *d, int x, int y, int graphic)
1052 getMiniGraphicSource(graphic, &bitmap, &src_x, &src_y);
1053 BlitBitmap(bitmap, d, src_x, src_y, MINI_TILEX, MINI_TILEY, x, y);
1056 void DrawGraphicShifted(int x,int y, int dx,int dy, int graphic,
1057 int cut_mode, int mask_mode)
1059 int width = TILEX, height = TILEY;
1061 int src_x, src_y, dest_x, dest_y;
1068 DrawGraphic(x, y, graphic);
1072 if (dx || dy) /* Verschiebung der Grafik? */
1074 if (x < BX1) /* Element kommt von links ins Bild */
1081 else if (x > BX2) /* Element kommt von rechts ins Bild */
1087 else if (x==BX1 && dx < 0) /* Element verläßt links das Bild */
1093 else if (x==BX2 && dx > 0) /* Element verläßt rechts das Bild */
1095 else if (dx) /* allg. Bewegung in x-Richtung */
1096 MarkTileDirty(x + SIGN(dx), y);
1098 if (y < BY1) /* Element kommt von oben ins Bild */
1100 if (cut_mode==CUT_BELOW) /* Element oberhalb des Bildes */
1108 else if (y > BY2) /* Element kommt von unten ins Bild */
1114 else if (y==BY1 && dy < 0) /* Element verläßt oben das Bild */
1120 else if (dy > 0 && cut_mode == CUT_ABOVE)
1122 if (y == BY2) /* Element unterhalb des Bildes */
1128 MarkTileDirty(x, y + 1);
1129 } /* Element verläßt unten das Bild */
1130 else if (dy > 0 && (y == BY2 || cut_mode == CUT_BELOW))
1132 else if (dy) /* allg. Bewegung in y-Richtung */
1133 MarkTileDirty(x, y + SIGN(dy));
1136 getGraphicSource(graphic, &src_bitmap, &src_x, &src_y);
1137 drawing_gc = src_bitmap->stored_clip_gc;
1142 dest_x = FX + x * TILEX + dx;
1143 dest_y = FY + y * TILEY + dy;
1146 if (!IN_SCR_FIELD(x,y))
1148 printf("DrawGraphicShifted(): x = %d, y = %d, graphic = %d\n",x,y,graphic);
1149 printf("DrawGraphicShifted(): This should never happen!\n");
1154 if (mask_mode == USE_MASKING)
1156 if (tile_clipmask[tile] != None)
1158 SetClipMask(src_bitmap, tile_clip_gc, tile_clipmask[tile]);
1159 SetClipOrigin(src_bitmap, tile_clip_gc, dest_x, dest_y);
1160 BlitBitmapMasked(src_bitmap, drawto_field,
1161 src_x, src_y, TILEX, TILEY, dest_x, dest_y);
1167 printf("DrawGraphicShifted(): tile '%d' needs clipping!\n", tile);
1171 SetClipOrigin(src_bitmap, drawing_gc, dest_x - src_x, dest_y - src_y);
1172 BlitBitmapMasked(src_bitmap, drawto_field,
1173 src_x, src_y, width, height, dest_x, dest_y);
1177 BlitBitmap(src_bitmap, drawto_field,
1178 src_x, src_y, width, height, dest_x, dest_y);
1183 void DrawNewGraphicShifted(int x,int y, int dx,int dy, int graphic, int frame,
1184 int cut_mode, int mask_mode)
1191 int width = TILEX, height = TILEY;
1197 DrawNewGraphic(x, y, graphic, frame);
1201 if (dx || dy) /* Verschiebung der Grafik? */
1203 if (x < BX1) /* Element kommt von links ins Bild */
1210 else if (x > BX2) /* Element kommt von rechts ins Bild */
1216 else if (x==BX1 && dx < 0) /* Element verläßt links das Bild */
1222 else if (x==BX2 && dx > 0) /* Element verläßt rechts das Bild */
1224 else if (dx) /* allg. Bewegung in x-Richtung */
1225 MarkTileDirty(x + SIGN(dx), y);
1227 if (y < BY1) /* Element kommt von oben ins Bild */
1229 if (cut_mode==CUT_BELOW) /* Element oberhalb des Bildes */
1237 else if (y > BY2) /* Element kommt von unten ins Bild */
1243 else if (y==BY1 && dy < 0) /* Element verläßt oben das Bild */
1249 else if (dy > 0 && cut_mode == CUT_ABOVE)
1251 if (y == BY2) /* Element unterhalb des Bildes */
1257 MarkTileDirty(x, y + 1);
1258 } /* Element verläßt unten das Bild */
1259 else if (dy > 0 && (y == BY2 || cut_mode == CUT_BELOW))
1261 else if (dy) /* allg. Bewegung in y-Richtung */
1262 MarkTileDirty(x, y + SIGN(dy));
1265 src_bitmap = new_graphic_info[graphic].bitmap;
1266 drawing_gc = src_bitmap->stored_clip_gc;
1267 src_x = new_graphic_info[graphic].src_x;
1268 src_y = new_graphic_info[graphic].src_y;
1270 if (new_graphic_info[graphic].anim_vertical)
1271 src_y += frame * TILEY;
1273 src_x += frame * TILEX;
1278 dest_x = FX + x * TILEX + dx;
1279 dest_y = FY + y * TILEY + dy;
1282 if (!IN_SCR_FIELD(x,y))
1284 printf("DrawGraphicShifted(): x = %d, y = %d, graphic = %d\n",x,y,graphic);
1285 printf("DrawGraphicShifted(): This should never happen!\n");
1290 if (mask_mode == USE_MASKING)
1291 SetClipOrigin(src_bitmap, drawing_gc, dest_x - src_x, dest_y - src_y);
1293 BlitBitmap(src_bitmap, drawto_field, src_x, src_y, width, height,
1299 void DrawGraphicShiftedThruMask(int x,int y, int dx,int dy, int graphic,
1302 DrawGraphicShifted(x,y, dx,dy, graphic, cut_mode, USE_MASKING);
1305 void DrawNewGraphicShiftedThruMask(int x,int y, int dx,int dy, int graphic,
1306 int frame, int cut_mode)
1308 DrawNewGraphicShifted(x,y, dx,dy, graphic, frame, cut_mode, USE_MASKING);
1311 void DrawScreenElementExt(int x, int y, int dx, int dy, int element,
1312 int cut_mode, int mask_mode)
1314 int ux = LEVELX(x), uy = LEVELY(y);
1315 int graphic = el2gfx(element);
1316 int phase8 = ABS(MovPos[ux][uy]) / (TILEX / 8);
1317 int phase4 = phase8 / 2;
1318 int phase2 = phase8 / 4;
1319 int dir = MovDir[ux][uy];
1321 if (element == EL_PACMAN || element == EL_BUG || element == EL_SPACESHIP)
1323 graphic += 1 * !phase2;
1327 else if (dir == MV_LEFT)
1329 else if (dir == MV_DOWN)
1332 else if (element == EL_SP_SNIKSNAK)
1335 graphic = GFX_SP_SNIKSNAK_LEFT;
1336 else if (dir == MV_RIGHT)
1337 graphic = GFX_SP_SNIKSNAK_RIGHT;
1338 else if (dir == MV_UP)
1339 graphic = GFX_SP_SNIKSNAK_UP;
1341 graphic = GFX_SP_SNIKSNAK_DOWN;
1343 graphic += (phase8 < 4 ? phase8 : 7 - phase8);
1345 else if (element == EL_SP_ELECTRON)
1347 graphic = GFX2_SP_ELECTRON + getGraphicAnimationPhase(8, 2, ANIM_NORMAL);
1349 else if (element == EL_MOLE || element == EL_PENGUIN ||
1350 element == EL_PIG || element == EL_DRAGON)
1353 graphic = (element == EL_MOLE ? GFX_MOLE_LEFT :
1354 element == EL_PENGUIN ? GFX_PINGUIN_LEFT :
1355 element == EL_PIG ? GFX_SCHWEIN_LEFT : GFX_DRACHE_LEFT);
1356 else if (dir == MV_RIGHT)
1357 graphic = (element == EL_MOLE ? GFX_MOLE_RIGHT :
1358 element == EL_PENGUIN ? GFX_PINGUIN_RIGHT :
1359 element == EL_PIG ? GFX_SCHWEIN_RIGHT : GFX_DRACHE_RIGHT);
1360 else if (dir == MV_UP)
1361 graphic = (element == EL_MOLE ? GFX_MOLE_UP :
1362 element == EL_PENGUIN ? GFX_PINGUIN_UP :
1363 element == EL_PIG ? GFX_SCHWEIN_UP : GFX_DRACHE_UP);
1365 graphic = (element == EL_MOLE ? GFX_MOLE_DOWN :
1366 element == EL_PENGUIN ? GFX_PINGUIN_DOWN :
1367 element == EL_PIG ? GFX_SCHWEIN_DOWN : GFX_DRACHE_DOWN);
1371 else if (element == EL_SATELLITE)
1373 graphic = GFX_SONDE_START + getGraphicAnimationPhase(8, 2, ANIM_NORMAL);
1375 else if (element == EL_ACID)
1377 graphic = GFX_GEBLUBBER + getGraphicAnimationPhase(4, 10, ANIM_NORMAL);
1379 else if (element == EL_BD_BUTTERFLY || element == EL_BD_FIREFLY)
1383 else if (element == EL_BALLOON)
1387 else if ((element == EL_ROCK ||
1388 element == EL_SP_ZONK ||
1389 element == EL_BD_ROCK ||
1390 element == EL_SP_INFOTRON ||
1394 if (uy >= lev_fieldy-1 || !IS_BELT(Feld[ux][uy+1]))
1396 if (element == EL_ROCK ||
1397 element == EL_SP_ZONK ||
1398 element == EL_BD_ROCK)
1401 graphic += (4 - phase4) % 4;
1402 else if (dir == MV_RIGHT)
1405 graphic += phase2 * 2;
1407 else if (element != EL_SP_INFOTRON)
1411 else if (element == EL_MAGIC_WALL_ACTIVE ||
1412 element == EL_MAGIC_WALL_EMPTYING ||
1413 element == EL_BD_MAGIC_WALL_ACTIVE ||
1414 element == EL_BD_MAGIC_WALL_EMPTYING ||
1415 element == EL_MAGIC_WALL_FULL ||
1416 element == EL_BD_MAGIC_WALL_FULL)
1418 graphic += 3 + getGraphicAnimationPhase(4, 4, ANIM_REVERSE);
1420 else if (IS_AMOEBOID(element) || element == EL_AMOEBA_DRIPPING)
1422 graphic = (element == EL_AMOEBA_DEAD ? GFX_AMOEBE_TOT : GFX_AMOEBE_LEBT);
1423 graphic += (x + 2 * y + 4) % 4;
1425 else if (element == EL_WALL_GROWING)
1427 boolean links_massiv = FALSE, rechts_massiv = FALSE;
1429 if (!IN_LEV_FIELD(ux-1, uy) || IS_MAUER(Feld[ux-1][uy]))
1430 links_massiv = TRUE;
1431 if (!IN_LEV_FIELD(ux+1, uy) || IS_MAUER(Feld[ux+1][uy]))
1432 rechts_massiv = TRUE;
1434 if (links_massiv && rechts_massiv)
1435 graphic = GFX_MAUERWERK;
1436 else if (links_massiv)
1437 graphic = GFX_MAUER_R;
1438 else if (rechts_massiv)
1439 graphic = GFX_MAUER_L;
1442 else if ((element == EL_INVISIBLE_STEELWALL ||
1443 element == EL_INVISIBLE_WALL ||
1444 element == EL_INVISIBLE_SAND) && game.light_time_left)
1446 graphic = (element == EL_INVISIBLE_STEELWALL ? GFX_INVISIBLE_STEEL_ON :
1447 element == EL_INVISIBLE_WALL ? GFX_UNSICHTBAR_ON :
1448 GFX_SAND_INVISIBLE_ON);
1453 DrawGraphicShifted(x, y, dx, dy, graphic, cut_mode, mask_mode);
1454 else if (mask_mode == USE_MASKING)
1455 DrawGraphicThruMask(x, y, graphic);
1457 DrawGraphic(x, y, graphic);
1460 void DrawNewScreenElementExt(int x, int y, int dx, int dy, int element,
1461 int cut_mode, int mask_mode)
1463 int ux = LEVELX(x), uy = LEVELY(y);
1464 int move_dir = MovDir[ux][uy];
1465 int move_pos = ABS(MovPos[ux][uy]) / (TILEX / 8);
1466 int gfx_action = (IS_MOVING(ux,uy) ? GFX_ACTION_MOVING : GFX_ACTION_DEFAULT);
1467 int graphic = el_dir_act2img(element, move_dir, gfx_action);
1468 int frame = getNewGraphicAnimationFrame(graphic, move_pos);
1470 int phase8 = move_pos;
1471 int phase4 = phase8 / 2;
1472 int phase2 = phase8 / 4;
1475 if (element == EL_WALL_GROWING)
1477 boolean left_stopped = FALSE, right_stopped = FALSE;
1479 if (!IN_LEV_FIELD(ux-1, uy) || IS_MAUER(Feld[ux-1][uy]))
1480 left_stopped = TRUE;
1481 if (!IN_LEV_FIELD(ux+1, uy) || IS_MAUER(Feld[ux+1][uy]))
1482 right_stopped = TRUE;
1484 if (left_stopped && right_stopped)
1486 else if (left_stopped)
1487 graphic = IMG_WALL_GROWING_ACTIVE_RIGHT;
1488 else if (right_stopped)
1489 graphic = IMG_WALL_GROWING_ACTIVE_LEFT;
1492 else if ((element == EL_ROCK ||
1493 element == EL_SP_ZONK ||
1494 element == EL_BD_ROCK ||
1495 element == EL_SP_INFOTRON ||
1499 if (uy >= lev_fieldy-1 || !IS_BELT(Feld[ux][uy+1]))
1501 if (element == EL_ROCK ||
1502 element == EL_SP_ZONK ||
1503 element == EL_BD_ROCK)
1505 if (move_dir == MV_LEFT)
1506 graphic += (4 - phase4) % 4;
1507 else if (move_dir == MV_RIGHT)
1510 graphic += phase2 * 2;
1512 else if (element != EL_SP_INFOTRON)
1516 else if (IS_AMOEBOID(element) || element == EL_AMOEBA_DRIPPING)
1518 graphic = (element == EL_AMOEBA_DEAD ? GFX_AMOEBE_TOT : GFX_AMOEBE_LEBT);
1519 graphic += (x + 2 * y + 4) % 4;
1524 DrawNewGraphicShifted(x, y, dx, dy, graphic, frame, cut_mode, mask_mode);
1525 else if (mask_mode == USE_MASKING)
1526 DrawNewGraphicThruMask(x, y, graphic, frame);
1528 DrawNewGraphic(x, y, graphic, frame);
1531 void DrawLevelElementExt(int x, int y, int dx, int dy, int element,
1532 int cut_mode, int mask_mode)
1534 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1535 DrawScreenElementExt(SCREENX(x), SCREENY(y), dx, dy, element,
1536 cut_mode, mask_mode);
1539 void DrawNewLevelElementExt(int x, int y, int dx, int dy, int element,
1540 int cut_mode, int mask_mode)
1542 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1543 DrawNewScreenElementExt(SCREENX(x), SCREENY(y), dx, dy, element,
1544 cut_mode, mask_mode);
1547 void DrawScreenElementShifted(int x, int y, int dx, int dy, int element,
1550 DrawScreenElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
1553 void DrawNewScreenElementShifted(int x, int y, int dx, int dy, int element,
1556 DrawNewScreenElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
1559 void DrawLevelElementShifted(int x, int y, int dx, int dy, int element,
1562 DrawLevelElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
1565 void DrawNewLevelElementShifted(int x, int y, int dx, int dy, int element,
1568 DrawNewLevelElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
1571 void DrawScreenElementThruMask(int x, int y, int element)
1573 DrawScreenElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
1576 void DrawNewScreenElementThruMask(int x, int y, int element)
1578 DrawNewScreenElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
1581 void DrawLevelElementThruMask(int x, int y, int element)
1583 DrawLevelElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
1586 void DrawNewLevelElementThruMask(int x, int y, int element)
1588 DrawNewLevelElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
1591 void DrawLevelFieldThruMask(int x, int y)
1593 DrawLevelElementExt(x, y, 0, 0, Feld[x][y], NO_CUTTING, USE_MASKING);
1596 void DrawNewLevelFieldThruMask(int x, int y)
1598 DrawNewLevelElementExt(x, y, 0, 0, Feld[x][y], NO_CUTTING, USE_MASKING);
1601 void ErdreichAnbroeckeln(int x, int y)
1605 int i, width, height, cx,cy;
1606 int ux = LEVELX(x), uy = LEVELY(y);
1607 int element, graphic;
1609 static int xy[4][2] =
1617 if (!IN_LEV_FIELD(ux, uy))
1620 element = Feld[ux][uy];
1622 if (element == EL_SAND ||
1623 element == EL_LANDMINE ||
1624 element == EL_TRAP ||
1625 element == EL_TRAP_ACTIVE)
1627 if (!IN_SCR_FIELD(x, y))
1630 graphic = GFX_ERDENRAND;
1632 getGraphicSource(graphic, &src_bitmap, &src_x, &src_y);
1638 uxx = ux + xy[i][0];
1639 uyy = uy + xy[i][1];
1640 if (!IN_LEV_FIELD(uxx, uyy))
1641 element = EL_STEELWALL;
1643 element = Feld[uxx][uyy];
1645 if (element == EL_SAND ||
1646 element == EL_LANDMINE ||
1647 element == EL_TRAP ||
1648 element == EL_TRAP_ACTIVE)
1651 if (i == 1 || i == 2)
1655 cx = (i == 2 ? TILEX - snip : 0);
1663 cy = (i == 3 ? TILEY - snip : 0);
1666 BlitBitmap(src_bitmap, drawto_field, src_x + cx, src_y + cy,
1667 width, height, FX + x * TILEX + cx, FY + y * TILEY + cy);
1670 MarkTileDirty(x, y);
1674 graphic = GFX_ERDENRAND;
1676 getGraphicSource(graphic, &src_bitmap, &src_x, &src_y);
1680 int xx, yy, uxx, uyy;
1684 uxx = ux + xy[i][0];
1685 uyy = uy + xy[i][1];
1687 if (!IN_LEV_FIELD(uxx, uyy) ||
1688 (Feld[uxx][uyy] != EL_SAND &&
1689 Feld[uxx][uyy] != EL_LANDMINE &&
1690 Feld[uxx][uyy] != EL_TRAP &&
1691 Feld[uxx][uyy] != EL_TRAP_ACTIVE) ||
1692 !IN_SCR_FIELD(xx, yy))
1695 if (i == 1 || i == 2)
1699 cx = (i == 1 ? TILEX - snip : 0);
1707 cy = (i==0 ? TILEY-snip : 0);
1710 BlitBitmap(src_bitmap, drawto_field, src_x + cx, src_y + cy,
1711 width, height, FX + xx * TILEX + cx, FY + yy * TILEY + cy);
1713 MarkTileDirty(xx, yy);
1718 void DrawScreenElement(int x, int y, int element)
1720 DrawScreenElementExt(x, y, 0, 0, element, NO_CUTTING, NO_MASKING);
1721 ErdreichAnbroeckeln(x, y);
1724 void DrawNewScreenElement(int x, int y, int element)
1726 DrawNewScreenElementExt(x, y, 0, 0, element, NO_CUTTING, NO_MASKING);
1727 ErdreichAnbroeckeln(x, y);
1730 void DrawLevelElement(int x, int y, int element)
1732 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1733 DrawScreenElement(SCREENX(x), SCREENY(y), element);
1736 void DrawNewLevelElement(int x, int y, int element)
1738 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1739 DrawNewScreenElement(SCREENX(x), SCREENY(y), element);
1742 void DrawScreenField(int x, int y)
1744 int ux = LEVELX(x), uy = LEVELY(y);
1745 int element, content;
1747 if (!IN_LEV_FIELD(ux, uy))
1749 if (ux < -1 || ux > lev_fieldx || uy < -1 || uy > lev_fieldy)
1752 element = BorderElement;
1754 DrawScreenElement(x, y, element);
1758 element = Feld[ux][uy];
1759 content = Store[ux][uy];
1761 if (IS_MOVING(ux, uy))
1763 int horiz_move = (MovDir[ux][uy] == MV_LEFT || MovDir[ux][uy] == MV_RIGHT);
1764 boolean cut_mode = NO_CUTTING;
1766 if (element == EL_QUICKSAND_EMPTYING ||
1767 element == EL_MAGIC_WALL_EMPTYING ||
1768 element == EL_BD_MAGIC_WALL_EMPTYING ||
1769 element == EL_AMOEBA_DRIPPING)
1770 cut_mode = CUT_ABOVE;
1771 else if (element == EL_QUICKSAND_FILLING ||
1772 element == EL_MAGIC_WALL_FILLING ||
1773 element == EL_BD_MAGIC_WALL_FILLING)
1774 cut_mode = CUT_BELOW;
1776 if (cut_mode == CUT_ABOVE)
1777 DrawScreenElementShifted(x, y, 0, 0, element, NO_CUTTING);
1779 DrawScreenElement(x, y, EL_EMPTY);
1782 DrawScreenElementShifted(x, y, MovPos[ux][uy], 0, element, NO_CUTTING);
1783 else if (cut_mode == NO_CUTTING)
1784 DrawScreenElementShifted(x, y, 0, MovPos[ux][uy], element, cut_mode);
1786 DrawScreenElementShifted(x, y, 0, MovPos[ux][uy], content, cut_mode);
1788 if (content == EL_ACID)
1789 DrawLevelElementThruMask(ux, uy + 1, EL_ACID);
1791 else if (IS_BLOCKED(ux, uy))
1796 boolean cut_mode = NO_CUTTING;
1797 int element_old, content_old;
1799 Blocked2Moving(ux, uy, &oldx, &oldy);
1802 horiz_move = (MovDir[oldx][oldy] == MV_LEFT ||
1803 MovDir[oldx][oldy] == MV_RIGHT);
1805 element_old = Feld[oldx][oldy];
1806 content_old = Store[oldx][oldy];
1808 if (element_old == EL_QUICKSAND_EMPTYING ||
1809 element_old == EL_MAGIC_WALL_EMPTYING ||
1810 element_old == EL_BD_MAGIC_WALL_EMPTYING ||
1811 element_old == EL_AMOEBA_DRIPPING)
1812 cut_mode = CUT_ABOVE;
1814 DrawScreenElement(x, y, EL_EMPTY);
1817 DrawScreenElementShifted(sx, sy, MovPos[oldx][oldy], 0, element_old,
1819 else if (cut_mode == NO_CUTTING)
1820 DrawScreenElementShifted(sx, sy, 0, MovPos[oldx][oldy], element_old,
1823 DrawScreenElementShifted(sx, sy, 0, MovPos[oldx][oldy], content_old,
1826 else if (IS_DRAWABLE(element))
1827 DrawScreenElement(x, y, element);
1829 DrawScreenElement(x, y, EL_EMPTY);
1832 void DrawNewScreenField(int x, int y)
1834 int ux = LEVELX(x), uy = LEVELY(y);
1835 int element, content;
1837 if (!IN_LEV_FIELD(ux, uy))
1839 if (ux < -1 || ux > lev_fieldx || uy < -1 || uy > lev_fieldy)
1842 element = BorderElement;
1844 DrawNewScreenElement(x, y, element);
1848 element = Feld[ux][uy];
1849 content = Store[ux][uy];
1851 if (IS_MOVING(ux, uy))
1853 int horiz_move = (MovDir[ux][uy] == MV_LEFT || MovDir[ux][uy] == MV_RIGHT);
1854 boolean cut_mode = NO_CUTTING;
1856 if (element == EL_QUICKSAND_EMPTYING ||
1857 element == EL_MAGIC_WALL_EMPTYING ||
1858 element == EL_BD_MAGIC_WALL_EMPTYING ||
1859 element == EL_AMOEBA_DRIPPING)
1860 cut_mode = CUT_ABOVE;
1861 else if (element == EL_QUICKSAND_FILLING ||
1862 element == EL_MAGIC_WALL_FILLING ||
1863 element == EL_BD_MAGIC_WALL_FILLING)
1864 cut_mode = CUT_BELOW;
1866 if (cut_mode == CUT_ABOVE)
1867 DrawNewScreenElementShifted(x, y, 0, 0, element, NO_CUTTING);
1869 DrawNewScreenElement(x, y, EL_EMPTY);
1872 DrawNewScreenElementShifted(x, y, MovPos[ux][uy], 0, element, NO_CUTTING);
1873 else if (cut_mode == NO_CUTTING)
1874 DrawNewScreenElementShifted(x, y, 0, MovPos[ux][uy], element, cut_mode);
1876 DrawNewScreenElementShifted(x, y, 0, MovPos[ux][uy], content, cut_mode);
1878 if (content == EL_ACID)
1879 DrawNewLevelElementThruMask(ux, uy + 1, EL_ACID);
1881 else if (IS_BLOCKED(ux, uy))
1886 boolean cut_mode = NO_CUTTING;
1887 int element_old, content_old;
1889 Blocked2Moving(ux, uy, &oldx, &oldy);
1892 horiz_move = (MovDir[oldx][oldy] == MV_LEFT ||
1893 MovDir[oldx][oldy] == MV_RIGHT);
1895 element_old = Feld[oldx][oldy];
1896 content_old = Store[oldx][oldy];
1898 if (element_old == EL_QUICKSAND_EMPTYING ||
1899 element_old == EL_MAGIC_WALL_EMPTYING ||
1900 element_old == EL_BD_MAGIC_WALL_EMPTYING ||
1901 element_old == EL_AMOEBA_DRIPPING)
1902 cut_mode = CUT_ABOVE;
1904 DrawNewScreenElement(x, y, EL_EMPTY);
1907 DrawNewScreenElementShifted(sx, sy, MovPos[oldx][oldy], 0, element_old,
1909 else if (cut_mode == NO_CUTTING)
1910 DrawNewScreenElementShifted(sx, sy, 0, MovPos[oldx][oldy], element_old,
1913 DrawNewScreenElementShifted(sx, sy, 0, MovPos[oldx][oldy], content_old,
1916 else if (IS_DRAWABLE(element))
1917 DrawNewScreenElement(x, y, element);
1919 DrawNewScreenElement(x, y, EL_EMPTY);
1922 void DrawLevelField(int x, int y)
1924 if (IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1925 DrawScreenField(SCREENX(x), SCREENY(y));
1926 else if (IS_MOVING(x, y))
1930 Moving2Blocked(x, y, &newx, &newy);
1931 if (IN_SCR_FIELD(SCREENX(newx), SCREENY(newy)))
1932 DrawScreenField(SCREENX(newx), SCREENY(newy));
1934 else if (IS_BLOCKED(x, y))
1938 Blocked2Moving(x, y, &oldx, &oldy);
1939 if (IN_SCR_FIELD(SCREENX(oldx), SCREENY(oldy)))
1940 DrawScreenField(SCREENX(oldx), SCREENY(oldy));
1944 void DrawNewLevelField(int x, int y)
1946 if (IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1947 DrawNewScreenField(SCREENX(x), SCREENY(y));
1948 else if (IS_MOVING(x, y))
1952 Moving2Blocked(x, y, &newx, &newy);
1953 if (IN_SCR_FIELD(SCREENX(newx), SCREENY(newy)))
1954 DrawNewScreenField(SCREENX(newx), SCREENY(newy));
1956 else if (IS_BLOCKED(x, y))
1960 Blocked2Moving(x, y, &oldx, &oldy);
1961 if (IN_SCR_FIELD(SCREENX(oldx), SCREENY(oldy)))
1962 DrawNewScreenField(SCREENX(oldx), SCREENY(oldy));
1966 void DrawMiniElement(int x, int y, int element)
1972 DrawMiniGraphic(x, y, -1);
1976 graphic = el2gfx(element);
1977 DrawMiniGraphic(x, y, graphic);
1980 void DrawMiniElementOrWall(int sx, int sy, int scroll_x, int scroll_y)
1982 int x = sx + scroll_x, y = sy + scroll_y;
1984 if (x < -1 || x > lev_fieldx || y < -1 || y > lev_fieldy)
1985 DrawMiniElement(sx, sy, EL_EMPTY);
1986 else if (x > -1 && x < lev_fieldx && y > -1 && y < lev_fieldy)
1987 DrawMiniElement(sx, sy, Feld[x][y]);
1990 int steel_type, steel_position;
1993 { GFX_VSTEEL_UPPER_LEFT, GFX_ISTEEL_UPPER_LEFT },
1994 { GFX_VSTEEL_UPPER_RIGHT, GFX_ISTEEL_UPPER_RIGHT },
1995 { GFX_VSTEEL_LOWER_LEFT, GFX_ISTEEL_LOWER_LEFT },
1996 { GFX_VSTEEL_LOWER_RIGHT, GFX_ISTEEL_LOWER_RIGHT },
1997 { GFX_VSTEEL_VERTICAL, GFX_ISTEEL_VERTICAL },
1998 { GFX_VSTEEL_HORIZONTAL, GFX_ISTEEL_HORIZONTAL }
2001 steel_type = (BorderElement == EL_STEELWALL ? 0 : 1);
2002 steel_position = (x == -1 && y == -1 ? 0 :
2003 x == lev_fieldx && y == -1 ? 1 :
2004 x == -1 && y == lev_fieldy ? 2 :
2005 x == lev_fieldx && y == lev_fieldy ? 3 :
2006 x == -1 || x == lev_fieldx ? 4 :
2007 y == -1 || y == lev_fieldy ? 5 : -1);
2009 if (steel_position != -1)
2010 DrawMiniGraphic(sx, sy, border[steel_position][steel_type]);
2014 void DrawMicroElement(int xpos, int ypos, int element)
2018 if (element == EL_EMPTY)
2021 graphic = el2gfx(element);
2023 if (graphic >= GFX_START_ROCKSSP && graphic <= GFX_END_ROCKSSP)
2025 graphic -= GFX_START_ROCKSSP;
2026 BlitBitmap(pix[PIX_SP], drawto,
2027 MICRO_SP_STARTX + (graphic % MICRO_SP_PER_LINE) * MICRO_TILEX,
2028 MICRO_SP_STARTY + (graphic / MICRO_SP_PER_LINE) * MICRO_TILEY,
2029 MICRO_TILEX, MICRO_TILEY, xpos, ypos);
2031 else if (graphic >= GFX_START_ROCKSDC && graphic <= GFX_END_ROCKSDC)
2033 graphic -= GFX_START_ROCKSDC;
2034 BlitBitmap(pix[PIX_DC], drawto,
2035 MICRO_DC_STARTX + (graphic % MICRO_DC_PER_LINE) * MICRO_TILEX,
2036 MICRO_DC_STARTY + (graphic / MICRO_DC_PER_LINE) * MICRO_TILEY,
2037 MICRO_TILEX, MICRO_TILEY, xpos, ypos);
2039 else if (graphic >= GFX_START_ROCKSMORE && graphic <= GFX_END_ROCKSMORE)
2041 graphic -= GFX_START_ROCKSMORE;
2042 BlitBitmap(pix[PIX_MORE], drawto,
2043 MICRO_MORE_STARTX + (graphic % MICRO_MORE_PER_LINE)*MICRO_TILEX,
2044 MICRO_MORE_STARTY + (graphic / MICRO_MORE_PER_LINE)*MICRO_TILEY,
2045 MICRO_TILEX, MICRO_TILEY, xpos, ypos);
2047 else if (graphic >= GFX_CHAR_START && graphic <= GFX_CHAR_END)
2049 graphic -= GFX_CHAR_START;
2050 BlitBitmap(pix[PIX_FONT_EM], drawto,
2051 MICRO_FONT_STARTX + (graphic % MICRO_GFX_PER_LINE)* MICRO_TILEX,
2052 MICRO_FONT_STARTY + (graphic / MICRO_GFX_PER_LINE)* MICRO_TILEY,
2053 MICRO_TILEX, MICRO_TILEY, xpos, ypos);
2056 BlitBitmap(pix[PIX_ELEMENTS], drawto,
2057 MICRO_GFX_STARTX + (graphic % MICRO_GFX_PER_LINE) * MICRO_TILEX,
2058 MICRO_GFX_STARTY + (graphic / MICRO_GFX_PER_LINE) * MICRO_TILEY,
2059 MICRO_TILEX, MICRO_TILEY, xpos, ypos);
2068 for(x=BX1; x<=BX2; x++)
2069 for(y=BY1; y<=BY2; y++)
2070 DrawScreenField(x, y);
2072 redraw_mask |= REDRAW_FIELD;
2075 void DrawMiniLevel(int size_x, int size_y, int scroll_x, int scroll_y)
2079 for(x=0; x<size_x; x++)
2080 for(y=0; y<size_y; y++)
2081 DrawMiniElementOrWall(x, y, scroll_x, scroll_y);
2083 redraw_mask |= REDRAW_FIELD;
2086 static void DrawMicroLevelExt(int xpos, int ypos, int from_x, int from_y)
2090 ClearRectangle(drawto, xpos, ypos, MICROLEV_XSIZE, MICROLEV_YSIZE);
2092 if (lev_fieldx < STD_LEV_FIELDX)
2093 xpos += (STD_LEV_FIELDX - lev_fieldx) / 2 * MICRO_TILEX;
2094 if (lev_fieldy < STD_LEV_FIELDY)
2095 ypos += (STD_LEV_FIELDY - lev_fieldy) / 2 * MICRO_TILEY;
2097 xpos += MICRO_TILEX;
2098 ypos += MICRO_TILEY;
2100 for(x=-1; x<=STD_LEV_FIELDX; x++)
2102 for(y=-1; y<=STD_LEV_FIELDY; y++)
2104 int lx = from_x + x, ly = from_y + y;
2106 if (lx >= 0 && lx < lev_fieldx && ly >= 0 && ly < lev_fieldy)
2107 DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
2109 else if (lx >= -1 && lx < lev_fieldx+1 && ly >= -1 && ly < lev_fieldy+1)
2110 DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
2115 redraw_mask |= REDRAW_MICROLEVEL;
2118 #define MICROLABEL_EMPTY 0
2119 #define MICROLABEL_LEVEL_NAME 1
2120 #define MICROLABEL_CREATED_BY 2
2121 #define MICROLABEL_LEVEL_AUTHOR 3
2122 #define MICROLABEL_IMPORTED_FROM 4
2123 #define MICROLABEL_LEVEL_IMPORT_INFO 5
2125 #define MAX_MICROLABEL_SIZE (SXSIZE / FONT4_XSIZE)
2127 static void DrawMicroLevelLabelExt(int mode)
2129 char label_text[MAX_MICROLABEL_SIZE + 1];
2131 ClearRectangle(drawto, SX, MICROLABEL_YPOS, SXSIZE, FONT4_YSIZE);
2133 strncpy(label_text, (mode == MICROLABEL_LEVEL_NAME ? level.name :
2134 mode == MICROLABEL_CREATED_BY ? "created by" :
2135 mode == MICROLABEL_LEVEL_AUTHOR ? level.author :
2136 mode == MICROLABEL_IMPORTED_FROM ? "imported from" :
2137 mode == MICROLABEL_LEVEL_IMPORT_INFO ?
2138 leveldir_current->imported_from : ""),
2139 MAX_MICROLABEL_SIZE);
2140 label_text[MAX_MICROLABEL_SIZE] = '\0';
2142 if (strlen(label_text) > 0)
2144 int lxpos = SX + (SXSIZE - strlen(label_text) * FONT4_XSIZE) / 2;
2145 int lypos = MICROLABEL_YPOS;
2147 DrawText(lxpos, lypos, label_text, FS_SMALL, FC_SPECIAL2);
2150 redraw_mask |= REDRAW_MICROLEVEL;
2153 void DrawMicroLevel(int xpos, int ypos, boolean restart)
2155 static unsigned long scroll_delay = 0;
2156 static unsigned long label_delay = 0;
2157 static int from_x, from_y, scroll_direction;
2158 static int label_state, label_counter;
2162 from_x = from_y = 0;
2163 scroll_direction = MV_RIGHT;
2167 DrawMicroLevelExt(xpos, ypos, from_x, from_y);
2168 DrawMicroLevelLabelExt(label_state);
2170 /* initialize delay counters */
2171 DelayReached(&scroll_delay, 0);
2172 DelayReached(&label_delay, 0);
2177 /* scroll micro level, if needed */
2178 if ((lev_fieldx > STD_LEV_FIELDX || lev_fieldy > STD_LEV_FIELDY) &&
2179 DelayReached(&scroll_delay, MICROLEVEL_SCROLL_DELAY))
2181 switch (scroll_direction)
2187 scroll_direction = MV_UP;
2191 if (from_x < lev_fieldx - STD_LEV_FIELDX)
2194 scroll_direction = MV_DOWN;
2201 scroll_direction = MV_RIGHT;
2205 if (from_y < lev_fieldy - STD_LEV_FIELDY)
2208 scroll_direction = MV_LEFT;
2215 DrawMicroLevelExt(xpos, ypos, from_x, from_y);
2218 /* redraw micro level label, if needed */
2219 if (strcmp(level.name, NAMELESS_LEVEL_NAME) != 0 &&
2220 strcmp(level.author, ANONYMOUS_NAME) != 0 &&
2221 strcmp(level.author, leveldir_current->name) != 0 &&
2222 DelayReached(&label_delay, MICROLEVEL_LABEL_DELAY))
2224 int max_label_counter = 23;
2226 if (leveldir_current->imported_from != NULL)
2227 max_label_counter += 14;
2229 label_counter = (label_counter + 1) % max_label_counter;
2230 label_state = (label_counter >= 0 && label_counter <= 7 ?
2231 MICROLABEL_LEVEL_NAME :
2232 label_counter >= 9 && label_counter <= 12 ?
2233 MICROLABEL_CREATED_BY :
2234 label_counter >= 14 && label_counter <= 21 ?
2235 MICROLABEL_LEVEL_AUTHOR :
2236 label_counter >= 23 && label_counter <= 26 ?
2237 MICROLABEL_IMPORTED_FROM :
2238 label_counter >= 28 && label_counter <= 35 ?
2239 MICROLABEL_LEVEL_IMPORT_INFO : MICROLABEL_EMPTY);
2240 DrawMicroLevelLabelExt(label_state);
2244 int REQ_in_range(int x, int y)
2246 if (y > DY+249 && y < DY+278)
2248 if (x > DX+1 && x < DX+48)
2250 else if (x > DX+51 && x < DX+98)
2256 #define MAX_REQUEST_LINES 13
2257 #define MAX_REQUEST_LINE_LEN 7
2259 boolean Request(char *text, unsigned int req_state)
2261 int mx, my, ty, result = -1;
2262 unsigned int old_door_state;
2264 #if defined(PLATFORM_UNIX)
2265 /* pause network game while waiting for request to answer */
2266 if (options.network &&
2267 game_status == PLAYING &&
2268 req_state & REQUEST_WAIT_FOR)
2269 SendToServer_PausePlaying();
2272 old_door_state = GetDoorState();
2276 CloseDoor(DOOR_CLOSE_1);
2278 /* save old door content */
2279 BlitBitmap(pix[PIX_DB_DOOR], pix[PIX_DB_DOOR],
2280 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE,
2281 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1);
2283 /* clear door drawing field */
2284 ClearRectangle(drawto, DX, DY, DXSIZE, DYSIZE);
2286 /* write text for request */
2287 for(ty=0; ty < MAX_REQUEST_LINES; ty++)
2289 char text_line[MAX_REQUEST_LINE_LEN + 1];
2295 for(tl=0,tx=0; tx < MAX_REQUEST_LINE_LEN; tl++,tx++)
2298 if (!tc || tc == ' ')
2309 strncpy(text_line, text, tl);
2312 DrawTextExt(drawto, DX + 50 - (tl * 14)/2, DY + 8 + ty * 16,
2313 text_line, FS_SMALL, FC_YELLOW);
2315 text += tl + (tc == ' ' ? 1 : 0);
2318 if (req_state & REQ_ASK)
2320 MapGadget(tool_gadget[TOOL_CTRL_ID_YES]);
2321 MapGadget(tool_gadget[TOOL_CTRL_ID_NO]);
2323 else if (req_state & REQ_CONFIRM)
2325 MapGadget(tool_gadget[TOOL_CTRL_ID_CONFIRM]);
2327 else if (req_state & REQ_PLAYER)
2329 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_1]);
2330 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_2]);
2331 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_3]);
2332 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_4]);
2335 /* copy request gadgets to door backbuffer */
2336 BlitBitmap(drawto, pix[PIX_DB_DOOR],
2337 DX, DY, DXSIZE, DYSIZE,
2338 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
2340 OpenDoor(DOOR_OPEN_1);
2346 if (!(req_state & REQUEST_WAIT_FOR))
2349 if (game_status != MAINMENU)
2352 button_status = MB_RELEASED;
2354 request_gadget_id = -1;
2366 case EVENT_BUTTONPRESS:
2367 case EVENT_BUTTONRELEASE:
2368 case EVENT_MOTIONNOTIFY:
2370 if (event.type == EVENT_MOTIONNOTIFY)
2372 if (!PointerInWindow(window))
2373 continue; /* window and pointer are on different screens */
2378 motion_status = TRUE;
2379 mx = ((MotionEvent *) &event)->x;
2380 my = ((MotionEvent *) &event)->y;
2384 motion_status = FALSE;
2385 mx = ((ButtonEvent *) &event)->x;
2386 my = ((ButtonEvent *) &event)->y;
2387 if (event.type == EVENT_BUTTONPRESS)
2388 button_status = ((ButtonEvent *) &event)->button;
2390 button_status = MB_RELEASED;
2393 /* this sets 'request_gadget_id' */
2394 HandleGadgets(mx, my, button_status);
2396 switch(request_gadget_id)
2398 case TOOL_CTRL_ID_YES:
2401 case TOOL_CTRL_ID_NO:
2404 case TOOL_CTRL_ID_CONFIRM:
2405 result = TRUE | FALSE;
2408 case TOOL_CTRL_ID_PLAYER_1:
2411 case TOOL_CTRL_ID_PLAYER_2:
2414 case TOOL_CTRL_ID_PLAYER_3:
2417 case TOOL_CTRL_ID_PLAYER_4:
2428 case EVENT_KEYPRESS:
2429 switch(GetEventKey((KeyEvent *)&event, TRUE))
2442 if (req_state & REQ_PLAYER)
2446 case EVENT_KEYRELEASE:
2447 ClearPlayerAction();
2451 HandleOtherEvents(&event);
2455 else if (AnyJoystickButton() == JOY_BUTTON_NEW_PRESSED)
2457 int joy = AnyJoystick();
2459 if (joy & JOY_BUTTON_1)
2461 else if (joy & JOY_BUTTON_2)
2467 /* don't eat all CPU time */
2471 if (game_status != MAINMENU)
2476 if (!(req_state & REQ_STAY_OPEN))
2478 CloseDoor(DOOR_CLOSE_1);
2480 if (!(req_state & REQ_STAY_CLOSED) && (old_door_state & DOOR_OPEN_1))
2482 BlitBitmap(pix[PIX_DB_DOOR], pix[PIX_DB_DOOR],
2483 DOOR_GFX_PAGEX2,DOOR_GFX_PAGEY1, DXSIZE,DYSIZE,
2484 DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY1);
2485 OpenDoor(DOOR_OPEN_1);
2491 #if defined(PLATFORM_UNIX)
2492 /* continue network game after request */
2493 if (options.network &&
2494 game_status == PLAYING &&
2495 req_state & REQUEST_WAIT_FOR)
2496 SendToServer_ContinuePlaying();
2502 unsigned int OpenDoor(unsigned int door_state)
2504 unsigned int new_door_state;
2506 if (door_state & DOOR_COPY_BACK)
2508 BlitBitmap(pix[PIX_DB_DOOR], pix[PIX_DB_DOOR],
2509 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE + VYSIZE,
2510 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
2511 door_state &= ~DOOR_COPY_BACK;
2514 new_door_state = MoveDoor(door_state);
2516 return(new_door_state);
2519 unsigned int CloseDoor(unsigned int door_state)
2521 unsigned int new_door_state;
2523 BlitBitmap(backbuffer, pix[PIX_DB_DOOR],
2524 DX, DY, DXSIZE, DYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
2525 BlitBitmap(backbuffer, pix[PIX_DB_DOOR],
2526 VX, VY, VXSIZE, VYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2);
2528 new_door_state = MoveDoor(door_state);
2530 return(new_door_state);
2533 unsigned int GetDoorState()
2535 return MoveDoor(DOOR_GET_STATE);
2538 unsigned int SetDoorState(unsigned int door_state)
2540 return MoveDoor(door_state | DOOR_SET_STATE);
2543 unsigned int MoveDoor(unsigned int door_state)
2545 static int door1 = DOOR_OPEN_1;
2546 static int door2 = DOOR_CLOSE_2;
2547 static unsigned long door_delay = 0;
2548 int x, start, stepsize = 2;
2549 unsigned long door_delay_value = stepsize * 5;
2551 if (door_state == DOOR_GET_STATE)
2552 return(door1 | door2);
2554 if (door_state & DOOR_SET_STATE)
2556 if (door_state & DOOR_ACTION_1)
2557 door1 = door_state & DOOR_ACTION_1;
2558 if (door_state & DOOR_ACTION_2)
2559 door2 = door_state & DOOR_ACTION_2;
2561 return(door1 | door2);
2564 if (door1 == DOOR_OPEN_1 && door_state & DOOR_OPEN_1)
2565 door_state &= ~DOOR_OPEN_1;
2566 else if (door1 == DOOR_CLOSE_1 && door_state & DOOR_CLOSE_1)
2567 door_state &= ~DOOR_CLOSE_1;
2568 if (door2 == DOOR_OPEN_2 && door_state & DOOR_OPEN_2)
2569 door_state &= ~DOOR_OPEN_2;
2570 else if (door2 == DOOR_CLOSE_2 && door_state & DOOR_CLOSE_2)
2571 door_state &= ~DOOR_CLOSE_2;
2573 if (setup.quick_doors)
2576 door_delay_value = 0;
2577 StopSound(SND_MENU_DOOR_OPENING);
2578 StopSound(SND_MENU_DOOR_CLOSING);
2581 if (door_state & DOOR_ACTION)
2583 if (!(door_state & DOOR_NO_DELAY))
2585 /* opening door sound has priority over simultaneously closing door */
2586 if (door_state & (DOOR_OPEN_1 | DOOR_OPEN_2))
2587 PlaySoundStereo(SND_MENU_DOOR_OPENING, SOUND_MAX_RIGHT);
2588 else if (door_state & (DOOR_CLOSE_1 | DOOR_CLOSE_2))
2589 PlaySoundStereo(SND_MENU_DOOR_CLOSING, SOUND_MAX_RIGHT);
2592 start = ((door_state & DOOR_NO_DELAY) ? DXSIZE : 0);
2594 for(x=start; x<=DXSIZE; x+=stepsize)
2596 Bitmap *bitmap = pix[PIX_DOOR];
2597 GC gc = bitmap->stored_clip_gc;
2599 WaitUntilDelayReached(&door_delay, door_delay_value);
2601 if (door_state & DOOR_ACTION_1)
2603 int i = (door_state & DOOR_OPEN_1 ? DXSIZE-x : x);
2604 int j = (DXSIZE - i) / 3;
2606 BlitBitmap(pix[PIX_DB_DOOR], drawto,
2607 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1 + i/2,
2608 DXSIZE,DYSIZE - i/2, DX, DY);
2610 ClearRectangle(drawto, DX, DY + DYSIZE - i/2, DXSIZE,i/2);
2612 SetClipOrigin(bitmap, gc, DX - i, (DY + j) - DOOR_GFX_PAGEY1);
2613 BlitBitmapMasked(bitmap, drawto,
2614 DXSIZE, DOOR_GFX_PAGEY1, i, 77,
2615 DX + DXSIZE - i, DY + j);
2616 BlitBitmapMasked(bitmap, drawto,
2617 DXSIZE, DOOR_GFX_PAGEY1 + 140, i, 63,
2618 DX + DXSIZE - i, DY + 140 + j);
2619 SetClipOrigin(bitmap, gc, DX - DXSIZE + i, DY - (DOOR_GFX_PAGEY1 + j));
2620 BlitBitmapMasked(bitmap, drawto,
2621 DXSIZE - i, DOOR_GFX_PAGEY1 + j, i, 77 - j,
2623 BlitBitmapMasked(bitmap, drawto,
2624 DXSIZE-i, DOOR_GFX_PAGEY1 + 140, i, 63,
2627 BlitBitmapMasked(bitmap, drawto,
2628 DXSIZE - i, DOOR_GFX_PAGEY1 + 77, i, 63,
2630 BlitBitmapMasked(bitmap, drawto,
2631 DXSIZE - i, DOOR_GFX_PAGEY1 + 203, i, 77,
2633 SetClipOrigin(bitmap, gc, DX - i, (DY + j) - DOOR_GFX_PAGEY1);
2634 BlitBitmapMasked(bitmap, drawto,
2635 DXSIZE, DOOR_GFX_PAGEY1 + 77, i, 63,
2636 DX + DXSIZE - i, DY + 77 + j);
2637 BlitBitmapMasked(bitmap, drawto,
2638 DXSIZE, DOOR_GFX_PAGEY1 + 203, i, 77 - j,
2639 DX + DXSIZE - i, DY + 203 + j);
2641 redraw_mask |= REDRAW_DOOR_1;
2644 if (door_state & DOOR_ACTION_2)
2646 int i = (door_state & DOOR_OPEN_2 ? VXSIZE - x : x);
2647 int j = (VXSIZE - i) / 3;
2649 BlitBitmap(pix[PIX_DB_DOOR], drawto,
2650 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2 + i/2,
2651 VXSIZE, VYSIZE - i/2, VX, VY);
2653 ClearRectangle(drawto, VX, VY + VYSIZE-i/2, VXSIZE, i/2);
2655 SetClipOrigin(bitmap, gc, VX - i, (VY + j) - DOOR_GFX_PAGEY2);
2656 BlitBitmapMasked(bitmap, drawto,
2657 VXSIZE, DOOR_GFX_PAGEY2, i, VYSIZE / 2,
2658 VX + VXSIZE-i, VY+j);
2659 SetClipOrigin(bitmap, gc,
2660 VX - VXSIZE + i, VY - (DOOR_GFX_PAGEY2 + j));
2661 BlitBitmapMasked(bitmap, drawto,
2662 VXSIZE - i, DOOR_GFX_PAGEY2 + j, i, VYSIZE / 2 - j,
2665 BlitBitmapMasked(bitmap, drawto,
2666 VXSIZE - i, DOOR_GFX_PAGEY2 + VYSIZE / 2,
2667 i, VYSIZE / 2, VX, VY + VYSIZE / 2 - j);
2668 SetClipOrigin(bitmap, gc, VX - i, (VY + j) - DOOR_GFX_PAGEY2);
2669 BlitBitmapMasked(bitmap, drawto,
2670 VXSIZE, DOOR_GFX_PAGEY2 + VYSIZE / 2,
2672 VX + VXSIZE - i, VY + VYSIZE / 2 + j);
2674 redraw_mask |= REDRAW_DOOR_2;
2679 if (game_status == MAINMENU)
2684 if (setup.quick_doors)
2686 StopSound(SND_MENU_DOOR_OPENING);
2687 StopSound(SND_MENU_DOOR_CLOSING);
2690 if (door_state & DOOR_ACTION_1)
2691 door1 = door_state & DOOR_ACTION_1;
2692 if (door_state & DOOR_ACTION_2)
2693 door2 = door_state & DOOR_ACTION_2;
2695 return (door1 | door2);
2698 void DrawSpecialEditorDoor()
2700 /* draw bigger toolbox window */
2701 BlitBitmap(pix[PIX_DOOR], drawto,
2702 DOOR_GFX_PAGEX7, 0, 108, 56, EX - 4, EY - 12);
2704 redraw_mask |= REDRAW_ALL;
2707 void UndrawSpecialEditorDoor()
2709 /* draw normal tape recorder window */
2710 BlitBitmap(pix[PIX_BACK], drawto,
2711 562, 344, 108, 56, EX - 4, EY - 12);
2713 redraw_mask |= REDRAW_ALL;
2717 int ReadPixel(DrawBuffer *bitmap, int x, int y)
2719 XImage *pixel_image;
2720 unsigned long pixel_value;
2722 pixel_image = XGetImage(display, bitmap->drawable,
2723 x, y, 1, 1, AllPlanes, ZPixmap);
2724 pixel_value = XGetPixel(pixel_image, 0, 0);
2726 XDestroyImage(pixel_image);
2732 /* ---------- new tool button stuff ---------------------------------------- */
2734 /* graphic position values for tool buttons */
2735 #define TOOL_BUTTON_YES_XPOS 2
2736 #define TOOL_BUTTON_YES_YPOS 250
2737 #define TOOL_BUTTON_YES_GFX_YPOS 0
2738 #define TOOL_BUTTON_YES_XSIZE 46
2739 #define TOOL_BUTTON_YES_YSIZE 28
2740 #define TOOL_BUTTON_NO_XPOS 52
2741 #define TOOL_BUTTON_NO_YPOS TOOL_BUTTON_YES_YPOS
2742 #define TOOL_BUTTON_NO_GFX_YPOS TOOL_BUTTON_YES_GFX_YPOS
2743 #define TOOL_BUTTON_NO_XSIZE TOOL_BUTTON_YES_XSIZE
2744 #define TOOL_BUTTON_NO_YSIZE TOOL_BUTTON_YES_YSIZE
2745 #define TOOL_BUTTON_CONFIRM_XPOS TOOL_BUTTON_YES_XPOS
2746 #define TOOL_BUTTON_CONFIRM_YPOS TOOL_BUTTON_YES_YPOS
2747 #define TOOL_BUTTON_CONFIRM_GFX_YPOS 30
2748 #define TOOL_BUTTON_CONFIRM_XSIZE 96
2749 #define TOOL_BUTTON_CONFIRM_YSIZE TOOL_BUTTON_YES_YSIZE
2750 #define TOOL_BUTTON_PLAYER_XSIZE 30
2751 #define TOOL_BUTTON_PLAYER_YSIZE 30
2752 #define TOOL_BUTTON_PLAYER_GFX_XPOS 5
2753 #define TOOL_BUTTON_PLAYER_GFX_YPOS 185
2754 #define TOOL_BUTTON_PLAYER_XPOS (5 + TOOL_BUTTON_PLAYER_XSIZE / 2)
2755 #define TOOL_BUTTON_PLAYER_YPOS (215 - TOOL_BUTTON_PLAYER_YSIZE / 2)
2756 #define TOOL_BUTTON_PLAYER1_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2757 + 0 * TOOL_BUTTON_PLAYER_XSIZE)
2758 #define TOOL_BUTTON_PLAYER2_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2759 + 1 * TOOL_BUTTON_PLAYER_XSIZE)
2760 #define TOOL_BUTTON_PLAYER3_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2761 + 0 * TOOL_BUTTON_PLAYER_XSIZE)
2762 #define TOOL_BUTTON_PLAYER4_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2763 + 1 * TOOL_BUTTON_PLAYER_XSIZE)
2764 #define TOOL_BUTTON_PLAYER1_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2765 + 0 * TOOL_BUTTON_PLAYER_YSIZE)
2766 #define TOOL_BUTTON_PLAYER2_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2767 + 0 * TOOL_BUTTON_PLAYER_YSIZE)
2768 #define TOOL_BUTTON_PLAYER3_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2769 + 1 * TOOL_BUTTON_PLAYER_YSIZE)
2770 #define TOOL_BUTTON_PLAYER4_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2771 + 1 * TOOL_BUTTON_PLAYER_YSIZE)
2780 } toolbutton_info[NUM_TOOL_BUTTONS] =
2783 TOOL_BUTTON_YES_XPOS, TOOL_BUTTON_YES_GFX_YPOS,
2784 TOOL_BUTTON_YES_XPOS, TOOL_BUTTON_YES_YPOS,
2785 TOOL_BUTTON_YES_XSIZE, TOOL_BUTTON_YES_YSIZE,
2790 TOOL_BUTTON_NO_XPOS, TOOL_BUTTON_NO_GFX_YPOS,
2791 TOOL_BUTTON_NO_XPOS, TOOL_BUTTON_NO_YPOS,
2792 TOOL_BUTTON_NO_XSIZE, TOOL_BUTTON_NO_YSIZE,
2797 TOOL_BUTTON_CONFIRM_XPOS, TOOL_BUTTON_CONFIRM_GFX_YPOS,
2798 TOOL_BUTTON_CONFIRM_XPOS, TOOL_BUTTON_CONFIRM_YPOS,
2799 TOOL_BUTTON_CONFIRM_XSIZE, TOOL_BUTTON_CONFIRM_YSIZE,
2800 TOOL_CTRL_ID_CONFIRM,
2804 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2805 TOOL_BUTTON_PLAYER1_XPOS, TOOL_BUTTON_PLAYER1_YPOS,
2806 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2807 TOOL_CTRL_ID_PLAYER_1,
2811 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2812 TOOL_BUTTON_PLAYER2_XPOS, TOOL_BUTTON_PLAYER2_YPOS,
2813 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2814 TOOL_CTRL_ID_PLAYER_2,
2818 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2819 TOOL_BUTTON_PLAYER3_XPOS, TOOL_BUTTON_PLAYER3_YPOS,
2820 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2821 TOOL_CTRL_ID_PLAYER_3,
2825 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2826 TOOL_BUTTON_PLAYER4_XPOS, TOOL_BUTTON_PLAYER4_YPOS,
2827 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2828 TOOL_CTRL_ID_PLAYER_4,
2833 void CreateToolButtons()
2837 for (i=0; i<NUM_TOOL_BUTTONS; i++)
2839 Bitmap *gd_bitmap = pix[PIX_DOOR];
2840 Bitmap *deco_bitmap = None;
2841 int deco_x = 0, deco_y = 0, deco_xpos = 0, deco_ypos = 0;
2842 struct GadgetInfo *gi;
2843 unsigned long event_mask;
2844 int gd_xoffset, gd_yoffset;
2845 int gd_x1, gd_x2, gd_y;
2848 event_mask = GD_EVENT_RELEASED;
2850 gd_xoffset = toolbutton_info[i].xpos;
2851 gd_yoffset = toolbutton_info[i].ypos;
2852 gd_x1 = DOOR_GFX_PAGEX4 + gd_xoffset;
2853 gd_x2 = DOOR_GFX_PAGEX3 + gd_xoffset;
2854 gd_y = DOOR_GFX_PAGEY1 + gd_yoffset;
2856 if (id >= TOOL_CTRL_ID_PLAYER_1 && id <= TOOL_CTRL_ID_PLAYER_4)
2858 getMiniGraphicSource(GFX_SPIELER1 + id - TOOL_CTRL_ID_PLAYER_1,
2859 &deco_bitmap, &deco_x, &deco_y);
2860 deco_xpos = (toolbutton_info[i].width - MINI_TILEX) / 2;
2861 deco_ypos = (toolbutton_info[i].height - MINI_TILEY) / 2;
2864 gi = CreateGadget(GDI_CUSTOM_ID, id,
2865 GDI_INFO_TEXT, toolbutton_info[i].infotext,
2866 GDI_X, DX + toolbutton_info[i].x,
2867 GDI_Y, DY + toolbutton_info[i].y,
2868 GDI_WIDTH, toolbutton_info[i].width,
2869 GDI_HEIGHT, toolbutton_info[i].height,
2870 GDI_TYPE, GD_TYPE_NORMAL_BUTTON,
2871 GDI_STATE, GD_BUTTON_UNPRESSED,
2872 GDI_DESIGN_UNPRESSED, gd_bitmap, gd_x1, gd_y,
2873 GDI_DESIGN_PRESSED, gd_bitmap, gd_x2, gd_y,
2874 GDI_DECORATION_DESIGN, deco_bitmap, deco_x, deco_y,
2875 GDI_DECORATION_POSITION, deco_xpos, deco_ypos,
2876 GDI_DECORATION_SIZE, MINI_TILEX, MINI_TILEY,
2877 GDI_DECORATION_SHIFTING, 1, 1,
2878 GDI_EVENT_MASK, event_mask,
2879 GDI_CALLBACK_ACTION, HandleToolButtons,
2883 Error(ERR_EXIT, "cannot create gadget");
2885 tool_gadget[id] = gi;
2889 static void UnmapToolButtons()
2893 for (i=0; i<NUM_TOOL_BUTTONS; i++)
2894 UnmapGadget(tool_gadget[i]);
2897 static void HandleToolButtons(struct GadgetInfo *gi)
2899 request_gadget_id = gi->custom_id;
2902 int get_next_element(int element)
2906 case EL_QUICKSAND_FILLING: return EL_QUICKSAND_FULL;
2907 case EL_QUICKSAND_EMPTYING: return EL_QUICKSAND_EMPTY;
2908 case EL_MAGIC_WALL_FILLING: return EL_MAGIC_WALL_FULL;
2909 case EL_MAGIC_WALL_EMPTYING: return EL_MAGIC_WALL_ACTIVE;
2910 case EL_BD_MAGIC_WALL_FILLING: return EL_BD_MAGIC_WALL_FULL;
2911 case EL_BD_MAGIC_WALL_EMPTYING: return EL_BD_MAGIC_WALL_ACTIVE;
2912 case EL_AMOEBA_DRIPPING: return EL_AMOEBA_WET;
2914 default: return element;
2918 int el2gfx_OLD(int element)
2922 case EL_EMPTY: return -1;
2923 case EL_SAND: return GFX_ERDREICH;
2924 case EL_WALL: return GFX_MAUERWERK;
2925 case EL_WALL_CRUMBLED: return GFX_FELSBODEN;
2926 case EL_ROCK: return GFX_FELSBROCKEN;
2927 case EL_EMERALD: return GFX_EDELSTEIN;
2928 case EL_EXIT_CLOSED: return GFX_AUSGANG_ZU;
2929 case EL_EXIT_OPENING: return GFX_AUSGANG_ACT;
2930 case EL_EXIT_OPEN: return GFX_AUSGANG_AUF;
2931 case EL_SP_EXIT_OPEN: return GFX_SP_EXIT;
2932 case EL_PLAYER1: return GFX_SPIELER1;
2933 case EL_PLAYER2: return GFX_SPIELER2;
2934 case EL_PLAYER3: return GFX_SPIELER3;
2935 case EL_PLAYER4: return GFX_SPIELER4;
2936 case EL_BUG: return GFX_KAEFER;
2937 case EL_BUG_RIGHT: return GFX_KAEFER_RIGHT;
2938 case EL_BUG_UP: return GFX_KAEFER_UP;
2939 case EL_BUG_LEFT: return GFX_KAEFER_LEFT;
2940 case EL_BUG_DOWN: return GFX_KAEFER_DOWN;
2941 case EL_SPACESHIP: return GFX_FLIEGER;
2942 case EL_SPACESHIP_RIGHT: return GFX_FLIEGER_RIGHT;
2943 case EL_SPACESHIP_UP: return GFX_FLIEGER_UP;
2944 case EL_SPACESHIP_LEFT: return GFX_FLIEGER_LEFT;
2945 case EL_SPACESHIP_DOWN: return GFX_FLIEGER_DOWN;
2946 case EL_BD_BUTTERFLY: return GFX_BUTTERFLY;
2947 case EL_BD_BUTTERFLY_RIGHT: return GFX_BUTTERFLY_RIGHT;
2948 case EL_BD_BUTTERFLY_UP: return GFX_BUTTERFLY_UP;
2949 case EL_BD_BUTTERFLY_LEFT: return GFX_BUTTERFLY_LEFT;
2950 case EL_BD_BUTTERFLY_DOWN: return GFX_BUTTERFLY_DOWN;
2951 case EL_BD_FIREFLY: return GFX_FIREFLY;
2952 case EL_BD_FIREFLY_RIGHT: return GFX_FIREFLY_RIGHT;
2953 case EL_BD_FIREFLY_UP: return GFX_FIREFLY_UP;
2954 case EL_BD_FIREFLY_LEFT: return GFX_FIREFLY_LEFT;
2955 case EL_BD_FIREFLY_DOWN: return GFX_FIREFLY_DOWN;
2956 case EL_YAMYAM: return GFX_MAMPFER;
2957 case EL_ROBOT: return GFX_ROBOT;
2958 case EL_STEELWALL: return GFX_BETON;
2959 case EL_DIAMOND: return GFX_DIAMANT;
2960 case EL_QUICKSAND_EMPTY: return GFX_MORAST_LEER;
2961 case EL_QUICKSAND_FULL: return GFX_MORAST_VOLL;
2962 case EL_QUICKSAND_EMPTYING: return GFX_MORAST_LEER;
2963 case EL_AMOEBA_DROP: return GFX_TROPFEN;
2964 case EL_BOMB: return GFX_BOMBE;
2965 case EL_MAGIC_WALL: return GFX_MAGIC_WALL_OFF;
2966 case EL_MAGIC_WALL_ACTIVE: return GFX_MAGIC_WALL_EMPTY;
2967 case EL_MAGIC_WALL_EMPTYING: return GFX_MAGIC_WALL_EMPTY;
2968 case EL_MAGIC_WALL_FULL: return GFX_MAGIC_WALL_FULL;
2969 case EL_MAGIC_WALL_DEAD: return GFX_MAGIC_WALL_DEAD;
2970 case EL_ACID: return GFX_SALZSAEURE;
2971 case EL_AMOEBA_DEAD: return GFX_AMOEBE_TOT;
2972 case EL_AMOEBA_WET: return GFX_AMOEBE_NASS;
2973 case EL_AMOEBA_DRY: return GFX_AMOEBE_NORM;
2974 case EL_AMOEBA_FULL: return GFX_AMOEBE_VOLL;
2975 case EL_BD_AMOEBA: return GFX_AMOEBE_BD;
2976 case EL_AMOEBA_TO_DIAMOND: return GFX_AMOEBA2DIAM;
2977 case EL_AMOEBA_DRIPPING: return GFX_AMOEBE_NASS;
2978 case EL_NUT: return GFX_KOKOSNUSS;
2979 case EL_GAMEOFLIFE: return GFX_LIFE;
2980 case EL_BIOMAZE: return GFX_LIFE_ASYNC;
2981 case EL_DYNAMITE_ACTIVE: return GFX_DYNAMIT;
2982 case EL_STONEBLOCK: return GFX_BADEWANNE;
2983 case EL_ACIDPOOL_TOPLEFT: return GFX_BADEWANNE1;
2984 case EL_ACIDPOOL_TOPRIGHT: return GFX_BADEWANNE2;
2985 case EL_ACIDPOOL_BOTTOMLEFT: return GFX_BADEWANNE3;
2986 case EL_ACIDPOOL_BOTTOM: return GFX_BADEWANNE4;
2987 case EL_ACIDPOOL_BOTTOMRIGHT: return GFX_BADEWANNE5;
2988 case EL_ROBOT_WHEEL: return GFX_ABLENK_AUS;
2989 case EL_ROBOT_WHEEL_ACTIVE: return GFX_ABLENK_EIN;
2990 case EL_KEY1: return GFX_SCHLUESSEL1;
2991 case EL_KEY2: return GFX_SCHLUESSEL2;
2992 case EL_KEY3: return GFX_SCHLUESSEL3;
2993 case EL_KEY4: return GFX_SCHLUESSEL4;
2994 case EL_GATE1: return GFX_PFORTE1;
2995 case EL_GATE2: return GFX_PFORTE2;
2996 case EL_GATE3: return GFX_PFORTE3;
2997 case EL_GATE4: return GFX_PFORTE4;
2998 case EL_GATE1_GRAY: return GFX_PFORTE1X;
2999 case EL_GATE2_GRAY: return GFX_PFORTE2X;
3000 case EL_GATE3_GRAY: return GFX_PFORTE3X;
3001 case EL_GATE4_GRAY: return GFX_PFORTE4X;
3002 case EL_DYNAMITE: return GFX_DYNAMIT_AUS;
3003 case EL_PACMAN: return GFX_PACMAN;
3004 case EL_PACMAN_RIGHT: return GFX_PACMAN_RIGHT;
3005 case EL_PACMAN_UP: return GFX_PACMAN_UP;
3006 case EL_PACMAN_LEFT: return GFX_PACMAN_LEFT;
3007 case EL_PACMAN_DOWN: return GFX_PACMAN_DOWN;
3008 case EL_INVISIBLE_WALL: return GFX_UNSICHTBAR;
3009 case EL_INVISIBLE_WALL_ACTIVE: return GFX_UNSICHTBAR_ON;
3010 case EL_WALL_EMERALD: return GFX_ERZ_EDEL;
3011 case EL_WALL_DIAMOND: return GFX_ERZ_DIAM;
3012 case EL_LAMP: return GFX_BIRNE_AUS;
3013 case EL_LAMP_ACTIVE: return GFX_BIRNE_EIN;
3014 case EL_TIME_ORB_FULL: return GFX_ZEIT_VOLL;
3015 case EL_TIME_ORB_EMPTY: return GFX_ZEIT_LEER;
3016 case EL_WALL_GROWING: return GFX_MAUER_LEBT;
3017 case EL_WALL_GROWING_X: return GFX_MAUER_X;
3018 case EL_WALL_GROWING_Y: return GFX_MAUER_Y;
3019 case EL_WALL_GROWING_XY: return GFX_MAUER_XY;
3020 case EL_BD_DIAMOND: return GFX_EDELSTEIN_BD;
3021 case EL_EMERALD_YELLOW: return GFX_EDELSTEIN_GELB;
3022 case EL_EMERALD_RED: return GFX_EDELSTEIN_ROT;
3023 case EL_EMERALD_PURPLE: return GFX_EDELSTEIN_LILA;
3024 case EL_WALL_BD_DIAMOND: return GFX_ERZ_EDEL_BD;
3025 case EL_WALL_EMERALD_YELLOW: return GFX_ERZ_EDEL_GELB;
3026 case EL_WALL_EMERALD_RED: return GFX_ERZ_EDEL_ROT;
3027 case EL_WALL_EMERALD_PURPLE: return GFX_ERZ_EDEL_LILA;
3028 case EL_DARK_YAMYAM: return GFX_MAMPFER2;
3029 case EL_BD_MAGIC_WALL: return GFX_MAGIC_WALL_BD_OFF;
3030 case EL_BD_MAGIC_WALL_ACTIVE: return GFX_MAGIC_WALL_BD_EMPTY;
3031 case EL_BD_MAGIC_WALL_EMPTYING: return GFX_MAGIC_WALL_BD_EMPTY;
3032 case EL_BD_MAGIC_WALL_FULL: return GFX_MAGIC_WALL_BD_FULL;
3033 case EL_BD_MAGIC_WALL_DEAD: return GFX_MAGIC_WALL_BD_DEAD;
3034 case EL_DYNABOMB_PLAYER1_ACTIVE: return GFX_DYNABOMB;
3035 case EL_DYNABOMB_PLAYER2_ACTIVE: return GFX_DYNABOMB;
3036 case EL_DYNABOMB_PLAYER3_ACTIVE: return GFX_DYNABOMB;
3037 case EL_DYNABOMB_PLAYER4_ACTIVE: return GFX_DYNABOMB;
3038 case EL_DYNABOMB_NR: return GFX_DYNABOMB_NR;
3039 case EL_DYNABOMB_SZ: return GFX_DYNABOMB_SZ;
3040 case EL_DYNABOMB_XL: return GFX_DYNABOMB_XL;
3041 case EL_SOKOBAN_OBJECT: return GFX_SOKOBAN_OBJEKT;
3042 case EL_SOKOBAN_FIELD_EMPTY: return GFX_SOKOBAN_FELD_LEER;
3043 case EL_SOKOBAN_FIELD_FULL: return GFX_SOKOBAN_FELD_VOLL;
3044 case EL_MOLE: return GFX_MOLE;
3045 case EL_PENGUIN: return GFX_PINGUIN;
3046 case EL_PIG: return GFX_SCHWEIN;
3047 case EL_DRAGON: return GFX_DRACHE;
3048 case EL_SATELLITE: return GFX_SONDE;
3049 case EL_ARROW_BLUE_LEFT: return GFX_PFEIL_LEFT;
3050 case EL_ARROW_BLUE_RIGHT: return GFX_PFEIL_RIGHT;
3051 case EL_ARROW_BLUE_UP: return GFX_PFEIL_UP;
3052 case EL_ARROW_BLUE_DOWN: return GFX_PFEIL_DOWN;
3053 case EL_SPEED_PILL: return GFX_SPEED_PILL;
3054 case EL_SP_TERMINAL_ACTIVE: return GFX_SP_TERMINAL;
3055 case EL_SP_BUGGY_BASE_ACTIVE: return GFX_SP_BUG_ACTIVE;
3056 case EL_SP_ZONK: return GFX_SP_ZONK;
3057 /* ^^^^^^^^^^ non-standard position in supaplex graphic set! */
3058 case EL_INVISIBLE_STEELWALL: return GFX_INVISIBLE_STEEL;
3059 case EL_INVISIBLE_STEELWALL_ACTIVE: return GFX_INVISIBLE_STEEL_ON;
3060 case EL_BLACK_ORB: return GFX_BLACK_ORB;
3061 case EL_EM_GATE1: return GFX_EM_GATE_1;
3062 case EL_EM_GATE2: return GFX_EM_GATE_2;
3063 case EL_EM_GATE3: return GFX_EM_GATE_3;
3064 case EL_EM_GATE4: return GFX_EM_GATE_4;
3065 case EL_EM_GATE1_GRAY: return GFX_EM_GATE_1X;
3066 case EL_EM_GATE2_GRAY: return GFX_EM_GATE_2X;
3067 case EL_EM_GATE3_GRAY: return GFX_EM_GATE_3X;
3068 case EL_EM_GATE4_GRAY: return GFX_EM_GATE_4X;
3069 case EL_EM_KEY1_FILE: return GFX_EM_KEY_1;
3070 case EL_EM_KEY2_FILE: return GFX_EM_KEY_2;
3071 case EL_EM_KEY3_FILE: return GFX_EM_KEY_3;
3072 case EL_EM_KEY4_FILE: return GFX_EM_KEY_4;
3073 case EL_EM_KEY1: return GFX_EM_KEY_1;
3074 case EL_EM_KEY2: return GFX_EM_KEY_2;
3075 case EL_EM_KEY3: return GFX_EM_KEY_3;
3076 case EL_EM_KEY4: return GFX_EM_KEY_4;
3077 case EL_PEARL: return GFX_PEARL;
3078 case EL_CRYSTAL: return GFX_CRYSTAL;
3079 case EL_WALL_PEARL: return GFX_WALL_PEARL;
3080 case EL_WALL_CRYSTAL: return GFX_WALL_CRYSTAL;
3081 case EL_DOOR_WHITE: return GFX_DOOR_WHITE;
3082 case EL_DOOR_WHITE_GRAY: return GFX_DOOR_WHITE_GRAY;
3083 case EL_KEY_WHITE: return GFX_KEY_WHITE;
3084 case EL_SHIELD_NORMAL: return GFX_SHIELD_PASSIVE;
3085 case EL_SHIELD_DEADLY: return GFX_SHIELD_ACTIVE;
3086 case EL_EXTRA_TIME: return GFX_EXTRA_TIME;
3087 case EL_SWITCHGATE_OPEN: return GFX_SWITCHGATE_OPEN;
3088 case EL_SWITCHGATE_CLOSED: return GFX_SWITCHGATE_CLOSED;
3089 case EL_SWITCHGATE_SWITCH_UP: return GFX_SWITCHGATE_SWITCH_1;
3090 case EL_SWITCHGATE_SWITCH_DOWN: return GFX_SWITCHGATE_SWITCH_2;
3091 case EL_CONVEYOR_BELT1_LEFT: return GFX_BELT1_LEFT;
3092 case EL_CONVEYOR_BELT1_MIDDLE: return GFX_BELT1_MIDDLE;
3093 case EL_CONVEYOR_BELT1_RIGHT: return GFX_BELT1_RIGHT;
3094 case EL_CONVEYOR_BELT1_LEFT_ACTIVE: return GFX_BELT1_LEFT;
3095 case EL_CONVEYOR_BELT1_MIDDLE_ACTIVE:return GFX_BELT1_MIDDLE;
3096 case EL_CONVEYOR_BELT1_RIGHT_ACTIVE:return GFX_BELT1_RIGHT;
3097 case EL_CONVEYOR_BELT1_SWITCH_LEFT: return GFX_BELT1_SWITCH_LEFT;
3098 case EL_CONVEYOR_BELT1_SWITCH_MIDDLE:return GFX_BELT1_SWITCH_MIDDLE;
3099 case EL_CONVEYOR_BELT1_SWITCH_RIGHT:return GFX_BELT1_SWITCH_RIGHT;
3100 case EL_CONVEYOR_BELT2_LEFT: return GFX_BELT2_LEFT;
3101 case EL_CONVEYOR_BELT2_MIDDLE: return GFX_BELT2_MIDDLE;
3102 case EL_CONVEYOR_BELT2_RIGHT: return GFX_BELT2_RIGHT;
3103 case EL_CONVEYOR_BELT2_LEFT_ACTIVE: return GFX_BELT2_LEFT;
3104 case EL_CONVEYOR_BELT2_MIDDLE_ACTIVE:return GFX_BELT2_MIDDLE;
3105 case EL_CONVEYOR_BELT2_RIGHT_ACTIVE:return GFX_BELT2_RIGHT;
3106 case EL_CONVEYOR_BELT2_SWITCH_LEFT: return GFX_BELT2_SWITCH_LEFT;
3107 case EL_CONVEYOR_BELT2_SWITCH_MIDDLE:return GFX_BELT2_SWITCH_MIDDLE;
3108 case EL_CONVEYOR_BELT2_SWITCH_RIGHT:return GFX_BELT2_SWITCH_RIGHT;
3109 case EL_CONVEYOR_BELT3_LEFT: return GFX_BELT3_LEFT;
3110 case EL_CONVEYOR_BELT3_MIDDLE: return GFX_BELT3_MIDDLE;
3111 case EL_CONVEYOR_BELT3_RIGHT: return GFX_BELT3_RIGHT;
3112 case EL_CONVEYOR_BELT3_LEFT_ACTIVE: return GFX_BELT3_LEFT;
3113 case EL_CONVEYOR_BELT3_MIDDLE_ACTIVE:return GFX_BELT3_MIDDLE;
3114 case EL_CONVEYOR_BELT3_RIGHT_ACTIVE:return GFX_BELT3_RIGHT;
3115 case EL_CONVEYOR_BELT3_SWITCH_LEFT: return GFX_BELT3_SWITCH_LEFT;
3116 case EL_CONVEYOR_BELT3_SWITCH_MIDDLE:return GFX_BELT3_SWITCH_MIDDLE;
3117 case EL_CONVEYOR_BELT3_SWITCH_RIGHT:return GFX_BELT3_SWITCH_RIGHT;
3118 case EL_CONVEYOR_BELT4_LEFT: return GFX_BELT4_LEFT;
3119 case EL_CONVEYOR_BELT4_MIDDLE: return GFX_BELT4_MIDDLE;
3120 case EL_CONVEYOR_BELT4_RIGHT: return GFX_BELT4_RIGHT;
3121 case EL_CONVEYOR_BELT4_LEFT_ACTIVE: return GFX_BELT4_LEFT;
3122 case EL_CONVEYOR_BELT4_MIDDLE_ACTIVE:return GFX_BELT4_MIDDLE;
3123 case EL_CONVEYOR_BELT4_RIGHT_ACTIVE:return GFX_BELT4_RIGHT;
3124 case EL_CONVEYOR_BELT4_SWITCH_LEFT: return GFX_BELT4_SWITCH_LEFT;
3125 case EL_CONVEYOR_BELT4_SWITCH_MIDDLE:return GFX_BELT4_SWITCH_MIDDLE;
3126 case EL_CONVEYOR_BELT4_SWITCH_RIGHT:return GFX_BELT4_SWITCH_RIGHT;
3127 case EL_LANDMINE: return GFX_LANDMINE;
3128 case EL_ENVELOPE: return GFX_ENVELOPE;
3129 case EL_LIGHT_SWITCH: return GFX_LIGHT_SWITCH_OFF;
3130 case EL_LIGHT_SWITCH_ACTIVE: return GFX_LIGHT_SWITCH_ON;
3131 case EL_SIGN_EXCLAMATION: return GFX_SIGN_EXCLAMATION;
3132 case EL_SIGN_RADIOACTIVITY: return GFX_SIGN_RADIOACTIVITY;
3133 case EL_SIGN_STOP: return GFX_SIGN_STOP;
3134 case EL_SIGN_WHEELCHAIR: return GFX_SIGN_WHEELCHAIR;
3135 case EL_SIGN_PARKING: return GFX_SIGN_PARKING;
3136 case EL_SIGN_ONEWAY: return GFX_SIGN_ONEWAY;
3137 case EL_SIGN_HEART: return GFX_SIGN_HEART;
3138 case EL_SIGN_TRIANGLE: return GFX_SIGN_TRIANGLE;
3139 case EL_SIGN_ROUND: return GFX_SIGN_ROUND;
3140 case EL_SIGN_EXIT: return GFX_SIGN_EXIT;
3141 case EL_SIGN_YINYANG: return GFX_SIGN_YINYANG;
3142 case EL_SIGN_OTHER: return GFX_SIGN_OTHER;
3143 case EL_MOLE_LEFT: return GFX_MOLE_LEFT;
3144 case EL_MOLE_RIGHT: return GFX_MOLE_RIGHT;
3145 case EL_MOLE_UP: return GFX_MOLE_UP;
3146 case EL_MOLE_DOWN: return GFX_MOLE_DOWN;
3147 case EL_STEELWALL_SLANTED: return GFX_STEEL_SLANTED;
3148 case EL_INVISIBLE_SAND: return GFX_SAND_INVISIBLE;
3149 case EL_INVISIBLE_SAND_ACTIVE: return GFX_SAND_INVISIBLE_ON;
3150 case EL_DX_UNKNOWN_15: return GFX_DX_UNKNOWN_15;
3151 case EL_DX_UNKNOWN_42: return GFX_DX_UNKNOWN_42;
3152 case EL_TIMEGATE_OPEN: return GFX_TIMEGATE_OPEN;
3153 case EL_TIMEGATE_CLOSED: return GFX_TIMEGATE_CLOSED;
3154 case EL_TIMEGATE_SWITCH_ACTIVE: return GFX_TIMEGATE_SWITCH;
3155 case EL_TIMEGATE_SWITCH: return GFX_TIMEGATE_SWITCH;
3156 case EL_BALLOON: return GFX_BALLOON;
3157 case EL_BALLOON_SEND_LEFT: return GFX_BALLOON_SEND_LEFT;
3158 case EL_BALLOON_SEND_RIGHT: return GFX_BALLOON_SEND_RIGHT;
3159 case EL_BALLOON_SEND_UP: return GFX_BALLOON_SEND_UP;
3160 case EL_BALLOON_SEND_DOWN: return GFX_BALLOON_SEND_DOWN;
3161 case EL_BALLOON_SEND_ANY_DIRECTION: return GFX_BALLOON_SEND_ANY;
3162 case EL_EMC_STEELWALL1: return GFX_EMC_STEEL_WALL_1;
3163 case EL_EMC_STEELWALL2: return GFX_EMC_STEEL_WALL_2;
3164 case EL_EMC_STEELWALL3: return GFX_EMC_STEEL_WALL_3;
3165 case EL_EMC_STEELWALL4: return GFX_EMC_STEEL_WALL_4;
3166 case EL_EMC_WALL_PILLAR_UPPER: return GFX_EMC_WALL_1;
3167 case EL_EMC_WALL_PILLAR_MIDDLE: return GFX_EMC_WALL_2;
3168 case EL_EMC_WALL_PILLAR_LOWER: return GFX_EMC_WALL_3;
3169 case EL_EMC_WALL4: return GFX_EMC_WALL_4;
3170 case EL_EMC_WALL5: return GFX_EMC_WALL_5;
3171 case EL_EMC_WALL6: return GFX_EMC_WALL_6;
3172 case EL_EMC_WALL7: return GFX_EMC_WALL_7;
3173 case EL_EMC_WALL8: return GFX_EMC_WALL_8;
3174 case EL_TUBE_ALL: return GFX_TUBE_CROSS;
3175 case EL_TUBE_VERTICAL: return GFX_TUBE_VERTICAL;
3176 case EL_TUBE_HORIZONTAL: return GFX_TUBE_HORIZONTAL;
3177 case EL_TUBE_VERTICAL_LEFT: return GFX_TUBE_VERT_LEFT;
3178 case EL_TUBE_VERTICAL_RIGHT: return GFX_TUBE_VERT_RIGHT;
3179 case EL_TUBE_HORIZONTAL_UP: return GFX_TUBE_HORIZ_UP;
3180 case EL_TUBE_HORIZONTAL_DOWN: return GFX_TUBE_HORIZ_DOWN;
3181 case EL_TUBE_LEFT_UP: return GFX_TUBE_LEFT_UP;
3182 case EL_TUBE_LEFT_DOWN: return GFX_TUBE_LEFT_DOWN;
3183 case EL_TUBE_RIGHT_UP: return GFX_TUBE_RIGHT_UP;
3184 case EL_TUBE_RIGHT_DOWN: return GFX_TUBE_RIGHT_DOWN;
3185 case EL_SPRING: return GFX_SPRING;
3186 case EL_SPRING_MOVING: return GFX_SPRING;
3187 case EL_TRAP: return GFX_TRAP_INACTIVE;
3188 case EL_TRAP_ACTIVE: return GFX_TRAP_ACTIVE;
3189 case EL_BD_WALL: return GFX_BD_WALL;
3190 case EL_BD_ROCK: return GFX_BD_ROCK;
3191 case EL_DX_SUPABOMB: return GFX_DX_SUPABOMB;
3192 case EL_SP_MURPHY_CLONE: return GFX_SP_MURPHY_CLONE;
3196 if (IS_CHAR(element))
3197 return GFX_CHAR_START + (element - EL_CHAR_START);
3198 else if (element >= EL_SP_START && element <= EL_SP_END)
3200 int nr_element = element - EL_SP_START;
3201 int gfx_per_line = 8;
3203 (nr_element / gfx_per_line) * SP_PER_LINE +
3204 (nr_element % gfx_per_line);
3206 return GFX_START_ROCKSSP + nr_graphic;
3214 int el2gfx(int element)
3217 int graphic_OLD = el2gfx_OLD(element);
3222 int graphic_NEW = element_info[element].graphic[GFX_ACTION_DEFAULT];
3225 int graphic_OLD = el2gfx_OLD(element);
3227 if (element >= MAX_ELEMENTS)
3229 Error(ERR_WARN, "el2gfx: element == %d >= MAX_ELEMENTS", element);
3232 if (graphic_NEW != graphic_OLD)
3234 Error(ERR_WARN, "el2gfx: graphic_NEW (%d) != graphic_OLD (%d)",
3235 graphic_NEW, graphic_OLD);
3243 int el2img(int element)
3246 int graphic_NEW = element_info[element].graphic[GFX_ACTION_DEFAULT];
3253 case EL_BD_BUTTERFLY: return IMG_BD_BUTTERFLY;
3254 case EL_BD_FIREFLY: return IMG_BD_FIREFLY;
3255 case EL_SP_ELECTRON: return IMG_SP_ELECTRON;
3261 return IMG_EMPTY_SPACE;
3265 int el_dir2img(int element, int direction)
3267 return el_dir_act2img(element, direction, GFX_ACTION_DEFAULT);
3270 int el_dir_act2img(int element, int direction, int action)
3272 action = graphics_action_mapping[action];
3273 direction = MV_DIR_BIT(direction);
3275 return element_info[element].direction_graphic[action][direction];