1 /***********************************************************
2 * Rocks'n'Diamonds -- McDuffin Strikes Back! *
3 *----------------------------------------------------------*
4 * (c) 1995-2002 Artsoft Entertainment *
6 * Detmolder Strasse 189 *
9 * e-mail: info@artsoft.org *
10 *----------------------------------------------------------*
12 ***********************************************************/
14 #include "libgame/libgame.h"
23 /* tool button identifiers */
24 #define TOOL_CTRL_ID_YES 0
25 #define TOOL_CTRL_ID_NO 1
26 #define TOOL_CTRL_ID_CONFIRM 2
27 #define TOOL_CTRL_ID_PLAYER_1 3
28 #define TOOL_CTRL_ID_PLAYER_2 4
29 #define TOOL_CTRL_ID_PLAYER_3 5
30 #define TOOL_CTRL_ID_PLAYER_4 6
32 #define NUM_TOOL_BUTTONS 7
34 /* forward declaration for internal use */
35 static void UnmapToolButtons();
36 static void HandleToolButtons(struct GadgetInfo *);
38 static struct GadgetInfo *tool_gadget[NUM_TOOL_BUTTONS];
39 static int request_gadget_id = -1;
41 void SetDrawtoField(int mode)
43 if (mode == DRAW_BUFFERED && setup.soft_scrolling)
54 drawto_field = fieldbuffer;
56 else /* DRAW_DIRECT, DRAW_BACKBUFFER */
67 drawto_field = (mode == DRAW_DIRECT ? window : backbuffer);
71 void RedrawPlayfield(boolean force_redraw, int x, int y, int width, int height)
73 if (game_status == GAME_MODE_PLAYING)
79 width = gfx.sxsize + 2 * TILEX;
80 height = gfx.sysize + 2 * TILEY;
83 if (force_redraw || setup.direct_draw)
86 int x1 = (x - SX) / TILEX, y1 = (y - SY) / TILEY;
87 int x2 = (x - SX + width) / TILEX, y2 = (y - SY + height) / TILEY;
89 if (setup.direct_draw)
90 SetDrawtoField(DRAW_BACKBUFFER);
92 for(xx=BX1; xx<=BX2; xx++)
93 for(yy=BY1; yy<=BY2; yy++)
94 if (xx >= x1 && xx <= x2 && yy >= y1 && yy <= y2)
95 DrawScreenField(xx, yy);
98 if (setup.direct_draw)
99 SetDrawtoField(DRAW_DIRECT);
102 if (setup.soft_scrolling)
104 int fx = FX, fy = FY;
106 fx += (ScreenMovDir & (MV_LEFT|MV_RIGHT) ? ScreenGfxPos : 0);
107 fy += (ScreenMovDir & (MV_UP|MV_DOWN) ? ScreenGfxPos : 0);
109 BlitBitmap(fieldbuffer, backbuffer, fx,fy, SXSIZE,SYSIZE, SX,SY);
113 BlitBitmap(drawto, window, x, y, width, height, x, y);
119 DrawBuffer *buffer = (drawto_field == window ? backbuffer : drawto_field);
121 if (setup.direct_draw && game_status == GAME_MODE_PLAYING)
122 redraw_mask &= ~REDRAW_MAIN;
124 if (redraw_mask & REDRAW_TILES && redraw_tiles > REDRAWTILES_THRESHOLD)
125 redraw_mask |= REDRAW_FIELD;
127 if (redraw_mask & REDRAW_FIELD)
128 redraw_mask &= ~REDRAW_TILES;
130 if (redraw_mask == REDRAW_NONE)
133 if (global.fps_slowdown && game_status == GAME_MODE_PLAYING)
135 static boolean last_frame_skipped = FALSE;
136 boolean skip_even_when_not_scrolling = TRUE;
137 boolean just_scrolling = (ScreenMovDir != 0);
138 boolean verbose = FALSE;
140 if (global.fps_slowdown_factor > 1 &&
141 (FrameCounter % global.fps_slowdown_factor) &&
142 (just_scrolling || skip_even_when_not_scrolling))
144 redraw_mask &= ~REDRAW_MAIN;
146 last_frame_skipped = TRUE;
149 printf("FRAME SKIPPED\n");
153 if (last_frame_skipped)
154 redraw_mask |= REDRAW_FIELD;
156 last_frame_skipped = FALSE;
159 printf("frame not skipped\n");
163 /* synchronize X11 graphics at this point; if we would synchronize the
164 display immediately after the buffer switching (after the XFlush),
165 this could mean that we have to wait for the graphics to complete,
166 although we could go on doing calculations for the next frame */
170 if (redraw_mask & REDRAW_ALL)
172 BlitBitmap(backbuffer, window, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
176 if (redraw_mask & REDRAW_FIELD)
178 if (game_status != GAME_MODE_PLAYING ||
179 redraw_mask & REDRAW_FROM_BACKBUFFER)
181 BlitBitmap(backbuffer, window,
182 REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE, REAL_SX, REAL_SY);
186 int fx = FX, fy = FY;
188 if (setup.soft_scrolling)
190 fx += (ScreenMovDir & (MV_LEFT | MV_RIGHT) ? ScreenGfxPos : 0);
191 fy += (ScreenMovDir & (MV_UP | MV_DOWN) ? ScreenGfxPos : 0);
194 if (setup.soft_scrolling ||
195 ABS(ScreenMovPos) + ScrollStepSize == TILEX ||
196 ABS(ScreenMovPos) == ScrollStepSize ||
197 redraw_tiles > REDRAWTILES_THRESHOLD)
199 BlitBitmap(buffer, window, fx, fy, SXSIZE, SYSIZE, SX, SY);
203 printf("redrawing all (ScreenGfxPos == %d) because %s\n",
205 (setup.soft_scrolling ?
206 "setup.soft_scrolling" :
207 ABS(ScreenGfxPos) + ScrollStepSize == TILEX ?
208 "ABS(ScreenGfxPos) + ScrollStepSize == TILEX" :
209 ABS(ScreenGfxPos) == ScrollStepSize ?
210 "ABS(ScreenGfxPos) == ScrollStepSize" :
211 "redraw_tiles > REDRAWTILES_THRESHOLD"));
217 redraw_mask &= ~REDRAW_MAIN;
220 if (redraw_mask & REDRAW_DOORS)
222 if (redraw_mask & REDRAW_DOOR_1)
223 BlitBitmap(backbuffer, window, DX, DY, DXSIZE, DYSIZE, DX, DY);
224 if (redraw_mask & REDRAW_DOOR_2)
226 if ((redraw_mask & REDRAW_DOOR_2) == REDRAW_DOOR_2)
227 BlitBitmap(backbuffer, window, VX,VY, VXSIZE,VYSIZE, VX,VY);
230 if (redraw_mask & REDRAW_VIDEO_1)
231 BlitBitmap(backbuffer, window,
232 VX+VIDEO_DISPLAY1_XPOS,VY+VIDEO_DISPLAY1_YPOS,
233 VIDEO_DISPLAY_XSIZE,VIDEO_DISPLAY_YSIZE,
234 VX+VIDEO_DISPLAY1_XPOS,VY+VIDEO_DISPLAY1_YPOS);
235 if (redraw_mask & REDRAW_VIDEO_2)
236 BlitBitmap(backbuffer, window,
237 VX+VIDEO_DISPLAY2_XPOS,VY+VIDEO_DISPLAY2_YPOS,
238 VIDEO_DISPLAY_XSIZE,VIDEO_DISPLAY_YSIZE,
239 VX+VIDEO_DISPLAY2_XPOS,VY+VIDEO_DISPLAY2_YPOS);
240 if (redraw_mask & REDRAW_VIDEO_3)
241 BlitBitmap(backbuffer, window,
242 VX+VIDEO_CONTROL_XPOS,VY+VIDEO_CONTROL_YPOS,
243 VIDEO_CONTROL_XSIZE,VIDEO_CONTROL_YSIZE,
244 VX+VIDEO_CONTROL_XPOS,VY+VIDEO_CONTROL_YPOS);
248 if (redraw_mask & REDRAW_DOOR_3)
249 BlitBitmap(backbuffer, window, EX, EY, EXSIZE, EYSIZE, EX, EY);
251 redraw_mask &= ~REDRAW_DOORS;
254 if (redraw_mask & REDRAW_MICROLEVEL)
256 BlitBitmap(backbuffer, window, SX, SY + 10 * TILEY, SXSIZE, 7 * TILEY,
257 SX, SY + 10 * TILEY);
259 redraw_mask &= ~REDRAW_MICROLEVEL;
262 if (redraw_mask & REDRAW_TILES)
264 for(x=0; x<SCR_FIELDX; x++)
265 for(y=0; y<SCR_FIELDY; y++)
266 if (redraw[redraw_x1 + x][redraw_y1 + y])
267 BlitBitmap(buffer, window,
268 FX + x * TILEX, FX + y * TILEY, TILEX, TILEY,
269 SX + x * TILEX, SY + y * TILEY);
272 if (redraw_mask & REDRAW_FPS) /* display frames per second */
277 sprintf(info1, " (only every %d. frame)", global.fps_slowdown_factor);
278 if (!global.fps_slowdown)
281 sprintf(text, "%.1f fps%s", global.frames_per_second, info1);
282 DrawTextExt(window, SX, SY, text, FONT_TEXT_2, BLIT_OPAQUE);
287 for(x=0; x<MAX_BUF_XSIZE; x++)
288 for(y=0; y<MAX_BUF_YSIZE; y++)
291 redraw_mask = REDRAW_NONE;
297 long fading_delay = 300;
299 if (setup.fading && (redraw_mask & REDRAW_FIELD))
306 ClearRectangle(window, REAL_SX,REAL_SY,FULL_SXSIZE,FULL_SYSIZE);
309 for(i=0;i<2*FULL_SYSIZE;i++)
311 for(y=0;y<FULL_SYSIZE;y++)
313 BlitBitmap(backbuffer, window,
314 REAL_SX,REAL_SY+i, FULL_SXSIZE,1, REAL_SX,REAL_SY+i);
322 for(i=1;i<FULL_SYSIZE;i+=2)
323 BlitBitmap(backbuffer, window,
324 REAL_SX,REAL_SY+i, FULL_SXSIZE,1, REAL_SX,REAL_SY+i);
330 SetClipOrigin(clip_gc[PIX_FADEMASK], 0, 0);
331 BlitBitmapMasked(backbuffer, window,
332 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE,
337 SetClipOrigin(clip_gc[PIX_FADEMASK], -1, -1);
338 BlitBitmapMasked(backbuffer, window,
339 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE,
344 SetClipOrigin(clip_gc[PIX_FADEMASK], 0, -1);
345 BlitBitmapMasked(backbuffer, window,
346 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE,
351 SetClipOrigin(clip_gc[PIX_FADEMASK], -1, 0);
352 BlitBitmapMasked(backbuffer, window,
353 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE,
358 redraw_mask &= ~REDRAW_MAIN;
365 void SetMainBackgroundImage(int graphic)
367 SetMainBackgroundBitmap(graphic == IMG_UNDEFINED ? NULL :
368 graphic_info[graphic].bitmap ?
369 graphic_info[graphic].bitmap :
370 graphic_info[IMG_BACKGROUND].bitmap);
373 void SetDoorBackgroundImage(int graphic)
375 SetDoorBackgroundBitmap(graphic == IMG_UNDEFINED ? NULL :
376 graphic_info[graphic].bitmap ?
377 graphic_info[graphic].bitmap :
378 graphic_info[IMG_BACKGROUND].bitmap);
381 void DrawBackground(int dest_x, int dest_y, int width, int height)
383 ClearRectangleOnBackground(backbuffer, dest_x, dest_y, width, height);
385 redraw_mask |= REDRAW_FIELD;
390 DrawBackground(REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE);
392 if (setup.soft_scrolling && game_status == GAME_MODE_PLAYING)
394 ClearRectangle(fieldbuffer, 0, 0, FXSIZE, FYSIZE);
395 SetDrawtoField(DRAW_BUFFERED);
398 SetDrawtoField(DRAW_BACKBUFFER);
400 if (setup.direct_draw && game_status == GAME_MODE_PLAYING)
402 ClearRectangle(window, REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE);
403 SetDrawtoField(DRAW_DIRECT);
407 void MarkTileDirty(int x, int y)
409 int xx = redraw_x1 + x;
410 int yy = redraw_y1 + y;
415 redraw[xx][yy] = TRUE;
416 redraw_mask |= REDRAW_TILES;
419 void SetBorderElement()
423 BorderElement = EL_EMPTY;
425 for(y=0; y<lev_fieldy && BorderElement == EL_EMPTY; y++)
427 for(x=0; x<lev_fieldx; x++)
429 if (!IS_INDESTRUCTIBLE(Feld[x][y]))
430 BorderElement = EL_STEELWALL;
432 if (y != 0 && y != lev_fieldy - 1 && x != lev_fieldx - 1)
438 void SetRandomAnimationValue(int x, int y)
440 gfx.anim_random_frame = GfxRandom[x][y];
443 inline int getGraphicAnimationFrame(int graphic, int sync_frame)
445 /* animation synchronized with global frame counter, not move position */
446 if (graphic_info[graphic].anim_global_sync || sync_frame < 0)
447 sync_frame = FrameCounter;
449 return getAnimationFrame(graphic_info[graphic].anim_frames,
450 graphic_info[graphic].anim_delay,
451 graphic_info[graphic].anim_mode,
452 graphic_info[graphic].anim_start_frame,
456 inline void DrawGraphicAnimationExt(DrawBuffer *dst_bitmap, int x, int y,
457 int graphic, int sync_frame, int mask_mode)
459 int frame = getGraphicAnimationFrame(graphic, sync_frame);
461 if (mask_mode == USE_MASKING)
462 DrawGraphicThruMaskExt(dst_bitmap, x, y, graphic, frame);
464 DrawGraphicExt(dst_bitmap, x, y, graphic, frame);
467 inline void DrawGraphicAnimation(int x, int y, int graphic)
469 int lx = LEVELX(x), ly = LEVELY(y);
471 if (!IN_SCR_FIELD(x, y))
474 DrawGraphicAnimationExt(drawto_field, FX + x * TILEX, FY + y * TILEY,
475 graphic, GfxFrame[lx][ly], NO_MASKING);
479 void DrawLevelGraphicAnimation(int x, int y, int graphic)
481 DrawGraphicAnimation(SCREENX(x), SCREENY(y), graphic);
484 void DrawLevelElementAnimation(int x, int y, int element)
487 int graphic = el_act_dir2img(element, GfxAction[x][y], MovDir[x][y]);
489 DrawGraphicAnimation(SCREENX(x), SCREENY(y), graphic);
491 DrawGraphicAnimation(SCREENX(x), SCREENY(y), el2img(element));
495 inline void DrawLevelGraphicAnimationIfNeeded(int x, int y, int graphic)
497 int sx = SCREENX(x), sy = SCREENY(y);
499 if (!IN_LEV_FIELD(x, y) || !IN_SCR_FIELD(sx, sy))
502 if (!IS_NEW_FRAME(GfxFrame[x][y], graphic))
505 DrawGraphicAnimation(sx, sy, graphic);
508 void DrawLevelElementAnimationIfNeeded(int x, int y, int element)
510 int sx = SCREENX(x), sy = SCREENY(y);
513 if (!IN_LEV_FIELD(x, y) || !IN_SCR_FIELD(sx, sy))
516 graphic = el_act_dir2img(element, GfxAction[x][y], MovDir[x][y]);
518 if (!IS_NEW_FRAME(GfxFrame[x][y], graphic))
521 DrawGraphicAnimation(sx, sy, graphic);
524 void DrawAllPlayers()
528 for(i=0; i<MAX_PLAYERS; i++)
529 if (stored_player[i].active)
530 DrawPlayer(&stored_player[i]);
533 void DrawPlayerField(int x, int y)
535 if (!IS_PLAYER(x, y))
538 DrawPlayer(PLAYERINFO(x, y));
541 void DrawPlayer(struct PlayerInfo *player)
543 int jx = player->jx, jy = player->jy;
544 int last_jx = player->last_jx, last_jy = player->last_jy;
545 int next_jx = jx + (jx - last_jx), next_jy = jy + (jy - last_jy);
546 int sx = SCREENX(jx), sy = SCREENY(jy);
547 int sxx = 0, syy = 0;
548 int element = Feld[jx][jy], last_element = Feld[last_jx][last_jy];
551 boolean player_is_moving = (last_jx != jx || last_jy != jy ? TRUE : FALSE);
552 int move_dir = player->MovDir;
553 int action = ACTION_DEFAULT;
555 if (!player->active || !IN_SCR_FIELD(SCREENX(last_jx), SCREENY(last_jy)))
559 if (!IN_LEV_FIELD(jx,jy))
561 printf("DrawPlayerField(): x = %d, y = %d\n",jx,jy);
562 printf("DrawPlayerField(): sx = %d, sy = %d\n",sx,sy);
563 printf("DrawPlayerField(): This should never happen!\n");
568 if (element == EL_EXPLOSION)
571 action = (player->Pushing ? ACTION_PUSHING :
572 player->is_digging ? ACTION_DIGGING :
573 player->is_collecting ? ACTION_COLLECTING :
574 player->is_moving ? ACTION_MOVING :
575 player->snapped ? ACTION_SNAPPING : ACTION_DEFAULT);
577 InitPlayerGfxAnimation(player, action, move_dir);
579 /* ----------------------------------------------------------------------- */
580 /* draw things in the field the player is leaving, if needed */
581 /* ----------------------------------------------------------------------- */
583 if (player_is_moving)
585 if (Back[last_jx][last_jy] && IS_DRAWABLE(last_element))
587 DrawLevelElement(last_jx, last_jy, Back[last_jx][last_jy]);
589 if (last_element == EL_DYNAMITE_ACTIVE ||
590 last_element == EL_SP_DISK_RED_ACTIVE)
591 DrawDynamite(last_jx, last_jy);
593 DrawLevelFieldThruMask(last_jx, last_jy);
595 else if (last_element == EL_DYNAMITE_ACTIVE ||
596 last_element == EL_SP_DISK_RED_ACTIVE)
597 DrawDynamite(last_jx, last_jy);
599 DrawLevelField(last_jx, last_jy);
601 if (player->Pushing && IN_SCR_FIELD(SCREENX(next_jx), SCREENY(next_jy)))
604 DrawLevelElement(next_jx, next_jy, EL_EMPTY);
608 if (Feld[next_jx][next_jy] == EL_SOKOBAN_FIELD_FULL)
609 DrawLevelElement(next_jx, next_jy, EL_SOKOBAN_FIELD_EMPTY);
611 DrawLevelElement(next_jx, next_jy, EL_EMPTY);
614 DrawLevelField(next_jx, next_jy);
619 if (!IN_SCR_FIELD(sx, sy))
622 if (setup.direct_draw)
623 SetDrawtoField(DRAW_BUFFERED);
625 /* ----------------------------------------------------------------------- */
626 /* draw things behind the player, if needed */
627 /* ----------------------------------------------------------------------- */
630 DrawLevelElement(jx, jy, Back[jx][jy]);
631 else if (IS_ACTIVE_BOMB(element))
632 DrawLevelElement(jx, jy, EL_EMPTY);
635 if (player_is_moving && GfxElement[jx][jy] != EL_UNDEFINED)
637 if (GfxElement[jx][jy] == EL_SAND)
638 DrawLevelFieldCrumbledSandDigging(jx, jy, move_dir, player->StepFrame);
641 int old_element = GfxElement[jx][jy];
642 int old_graphic = el_act_dir2img(old_element, action, move_dir);
643 int frame = getGraphicAnimationFrame(old_graphic, player->StepFrame);
645 DrawGraphic(sx, sy, old_graphic, frame);
650 GfxElement[jx][jy] = EL_UNDEFINED;
652 DrawLevelField(jx, jy);
656 /* ----------------------------------------------------------------------- */
657 /* draw player himself */
658 /* ----------------------------------------------------------------------- */
660 if (player->use_murphy_graphic)
662 static int last_horizontal_dir = MV_LEFT;
665 if (move_dir == MV_LEFT || move_dir == MV_RIGHT)
666 last_horizontal_dir = move_dir;
668 direction = (player->snapped ? move_dir : last_horizontal_dir);
670 graphic = el_act_dir2img(EL_SP_MURPHY, player->GfxAction, direction);
673 graphic = el_act_dir2img(player->element_nr, player->GfxAction, move_dir);
675 frame = getGraphicAnimationFrame(graphic, player->Frame);
679 if (move_dir == MV_LEFT || move_dir == MV_RIGHT)
680 sxx = player->GfxPos;
682 syy = player->GfxPos;
685 if (!setup.soft_scrolling && ScreenMovPos)
688 DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, frame, NO_CUTTING);
690 if (SHIELD_ON(player))
692 int graphic = (player->shield_deadly_time_left ? IMG_SHIELD_DEADLY_ACTIVE :
693 IMG_SHIELD_NORMAL_ACTIVE);
694 int frame = getGraphicAnimationFrame(graphic, -1);
696 DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, frame, NO_CUTTING);
699 /* ----------------------------------------------------------------------- */
700 /* draw things the player is pushing, if needed */
701 /* ----------------------------------------------------------------------- */
703 if (player->Pushing && player_is_moving)
705 int px = SCREENX(next_jx), py = SCREENY(next_jy);
707 if (Back[next_jx][next_jy])
708 DrawLevelElement(next_jx, next_jy, Back[next_jx][next_jy]);
711 if ((sxx || syy) && element == EL_SOKOBAN_OBJECT)
712 DrawGraphicShiftedThruMask(px, py, sxx, syy, IMG_SOKOBAN_OBJECT, 0,
716 (element == EL_SOKOBAN_FIELD_EMPTY ||
717 Feld[next_jx][next_jy] == EL_SOKOBAN_FIELD_FULL))
718 DrawGraphicShiftedThruMask(px, py, sxx, syy, IMG_SOKOBAN_OBJECT, 0,
724 int element = Feld[jx][jy];
726 int element = Feld[next_jx][next_jy];
729 int graphic = el2img(element);
732 if ((sxx || syy) && IS_PUSHABLE(element))
734 graphic = el_act_dir2img(element, ACTION_MOVING, move_dir);
735 frame = getGraphicAnimationFrame(graphic, player->Frame);
738 DrawGraphicShifted(px, py, sxx, syy, graphic, frame,
739 NO_CUTTING, NO_MASKING);
743 /* ----------------------------------------------------------------------- */
744 /* draw things in front of player (active dynamite or dynabombs) */
745 /* ----------------------------------------------------------------------- */
747 if (IS_ACTIVE_BOMB(element))
749 graphic = el2img(element);
750 frame = getGraphicAnimationFrame(graphic, GfxFrame[jx][jy]);
752 if (game.emulation == EMU_SUPAPLEX)
753 DrawGraphic(sx, sy, IMG_SP_DISK_RED, frame);
755 DrawGraphicThruMask(sx, sy, graphic, frame);
758 if (player_is_moving && last_element == EL_EXPLOSION)
761 int graphic = el_act2img(GfxElement[last_jx][last_jy], ACTION_EXPLODING);
763 int stored = Store[last_jx][last_jy];
764 int graphic = (game.emulation != EMU_SUPAPLEX ? IMG_EXPLOSION :
765 stored == EL_SP_INFOTRON ? IMG_SP_EXPLOSION_INFOTRON :
768 int delay = (game.emulation == EMU_SUPAPLEX ? 3 : 2);
769 int phase = ExplodePhase[last_jx][last_jy] - 1;
770 int frame = getGraphicAnimationFrame(graphic, phase - delay);
773 DrawGraphicThruMask(SCREENX(last_jx), SCREENY(last_jy), graphic, frame);
776 /* ----------------------------------------------------------------------- */
777 /* draw elements the player is just walking/passing through/under */
778 /* ----------------------------------------------------------------------- */
780 /* handle the field the player is leaving ... */
781 if (player_is_moving && IS_ACCESSIBLE_INSIDE(last_element))
782 DrawLevelField(last_jx, last_jy);
783 else if (player_is_moving && IS_ACCESSIBLE_UNDER(last_element))
784 DrawLevelFieldThruMask(last_jx, last_jy);
786 /* ... and the field the player is entering */
787 if (IS_ACCESSIBLE_INSIDE(element))
788 DrawLevelField(jx, jy);
789 else if (IS_ACCESSIBLE_UNDER(element))
790 DrawLevelFieldThruMask(jx, jy);
792 if (setup.direct_draw)
794 int dest_x = SX + SCREENX(MIN(jx, last_jx)) * TILEX;
795 int dest_y = SY + SCREENY(MIN(jy, last_jy)) * TILEY;
796 int x_size = TILEX * (1 + ABS(jx - last_jx));
797 int y_size = TILEY * (1 + ABS(jy - last_jy));
799 BlitBitmap(drawto_field, window,
800 dest_x, dest_y, x_size, y_size, dest_x, dest_y);
801 SetDrawtoField(DRAW_DIRECT);
804 MarkTileDirty(sx,sy);
807 void getGraphicSource(int graphic, int frame, Bitmap **bitmap, int *x, int *y)
809 struct GraphicInfo *g = &graphic_info[graphic];
813 if (g->offset_y == 0) /* frames are ordered horizontally */
815 int max_width = g->anim_frames_per_line * g->width;
817 *x = (g->src_x + frame * g->offset_x) % max_width;
818 *y = g->src_y + (g->src_x + frame * g->offset_x) / max_width * g->height;
820 else if (g->offset_x == 0) /* frames are ordered vertically */
822 int max_height = g->anim_frames_per_line * g->height;
824 *x = g->src_x + (g->src_y + frame * g->offset_y) / max_height * g->width;
825 *y = (g->src_y + frame * g->offset_y) % max_height;
827 else /* frames are ordered diagonally */
829 *x = g->src_x + frame * g->offset_x;
830 *y = g->src_y + frame * g->offset_y;
834 void DrawGraphic(int x, int y, int graphic, int frame)
837 if (!IN_SCR_FIELD(x, y))
839 printf("DrawGraphic(): x = %d, y = %d, graphic = %d\n", x, y, graphic);
840 printf("DrawGraphic(): This should never happen!\n");
845 DrawGraphicExt(drawto_field, FX + x * TILEX, FY + y * TILEY, graphic, frame);
849 void DrawGraphicExt(DrawBuffer *dst_bitmap, int x, int y, int graphic,
855 getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
856 BlitBitmap(src_bitmap, dst_bitmap, src_x, src_y, TILEX, TILEY, x, y);
859 void DrawGraphicThruMask(int x, int y, int graphic, int frame)
862 if (!IN_SCR_FIELD(x, y))
864 printf("DrawGraphicThruMask(): x = %d,y = %d, graphic = %d\n",x,y,graphic);
865 printf("DrawGraphicThruMask(): This should never happen!\n");
870 DrawGraphicThruMaskExt(drawto_field, FX + x * TILEX, FY + y *TILEY, graphic,
875 void DrawGraphicThruMaskExt(DrawBuffer *d, int dest_x, int dest_y, int graphic,
883 getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
884 drawing_gc = src_bitmap->stored_clip_gc;
886 GC drawing_gc = src_bitmap->stored_clip_gc;
887 Bitmap *src_bitmap = graphic_info[graphic].bitmap;
888 int src_x = graphic_info[graphic].src_x;
889 int src_y = graphic_info[graphic].src_y;
890 int offset_x = graphic_info[graphic].offset_x;
891 int offset_y = graphic_info[graphic].offset_y;
893 src_x += frame * offset_x;
894 src_y += frame * offset_y;
898 SetClipOrigin(src_bitmap, drawing_gc, dest_x - src_x, dest_y - src_y);
899 BlitBitmapMasked(src_bitmap, d, src_x, src_y, TILEX, TILEY, dest_x, dest_y);
902 void DrawMiniGraphic(int x, int y, int graphic)
904 DrawMiniGraphicExt(drawto, SX + x * MINI_TILEX,SY + y * MINI_TILEY, graphic);
905 MarkTileDirty(x / 2, y / 2);
908 void getMiniGraphicSource(int graphic, Bitmap **bitmap, int *x, int *y)
910 struct GraphicInfo *g = &graphic_info[graphic];
912 int mini_starty = g->bitmap->height * 2 / 3;
915 *x = mini_startx + g->src_x / 2;
916 *y = mini_starty + g->src_y / 2;
919 void DrawMiniGraphicExt(DrawBuffer *d, int x, int y, int graphic)
924 getMiniGraphicSource(graphic, &src_bitmap, &src_x, &src_y);
925 BlitBitmap(src_bitmap, d, src_x, src_y, MINI_TILEX, MINI_TILEY, x, y);
928 void DrawGraphicShifted(int x,int y, int dx,int dy, int graphic, int frame,
929 int cut_mode, int mask_mode)
934 int width = TILEX, height = TILEY;
940 DrawGraphic(x, y, graphic, frame);
944 if (dx || dy) /* shifted graphic */
946 if (x < BX1) /* object enters playfield from the left */
953 else if (x > BX2) /* object enters playfield from the right */
959 else if (x==BX1 && dx < 0) /* object leaves playfield to the left */
965 else if (x==BX2 && dx > 0) /* object leaves playfield to the right */
967 else if (dx) /* general horizontal movement */
968 MarkTileDirty(x + SIGN(dx), y);
970 if (y < BY1) /* object enters playfield from the top */
972 if (cut_mode==CUT_BELOW) /* object completely above top border */
980 else if (y > BY2) /* object enters playfield from the bottom */
986 else if (y==BY1 && dy < 0) /* object leaves playfield to the top */
992 else if (dy > 0 && cut_mode == CUT_ABOVE)
994 if (y == BY2) /* object completely above bottom border */
1000 MarkTileDirty(x, y + 1);
1001 } /* object leaves playfield to the bottom */
1002 else if (dy > 0 && (y == BY2 || cut_mode == CUT_BELOW))
1004 else if (dy) /* general vertical movement */
1005 MarkTileDirty(x, y + SIGN(dy));
1009 getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
1011 src_bitmap = graphic_info[graphic].bitmap;
1012 src_x = graphic_info[graphic].src_x;
1013 src_y = graphic_info[graphic].src_y;
1014 offset_x = graphic_info[graphic].offset_x;
1015 offset_y = graphic_info[graphic].offset_y;
1017 src_x += frame * offset_x;
1018 src_y += frame * offset_y;
1021 drawing_gc = src_bitmap->stored_clip_gc;
1026 dest_x = FX + x * TILEX + dx;
1027 dest_y = FY + y * TILEY + dy;
1030 if (!IN_SCR_FIELD(x,y))
1032 printf("DrawGraphicShifted(): x = %d, y = %d, graphic = %d\n",x,y,graphic);
1033 printf("DrawGraphicShifted(): This should never happen!\n");
1038 if (mask_mode == USE_MASKING)
1040 SetClipOrigin(src_bitmap, drawing_gc, dest_x - src_x, dest_y - src_y);
1041 BlitBitmapMasked(src_bitmap, drawto_field, src_x, src_y, width, height,
1045 BlitBitmap(src_bitmap, drawto_field, src_x, src_y, width, height,
1051 void DrawGraphicShiftedThruMask(int x, int y, int dx, int dy, int graphic,
1052 int frame, int cut_mode)
1054 DrawGraphicShifted(x,y, dx,dy, graphic, frame, cut_mode, USE_MASKING);
1057 void DrawScreenElementExt(int x, int y, int dx, int dy, int element,
1058 int cut_mode, int mask_mode)
1060 int lx = LEVELX(x), ly = LEVELY(y);
1064 if (IN_LEV_FIELD(lx, ly))
1066 SetRandomAnimationValue(lx, ly);
1068 graphic = el_act_dir2img(element, GfxAction[lx][ly], MovDir[lx][ly]);
1069 frame = getGraphicAnimationFrame(graphic, GfxFrame[lx][ly]);
1071 else /* border element */
1073 graphic = el2img(element);
1074 frame = getGraphicAnimationFrame(graphic, -1);
1077 if (element == EL_EXPANDABLE_WALL)
1079 boolean left_stopped = FALSE, right_stopped = FALSE;
1081 if (!IN_LEV_FIELD(lx - 1, ly) || IS_WALL(Feld[lx - 1][ly]))
1082 left_stopped = TRUE;
1083 if (!IN_LEV_FIELD(lx + 1, ly) || IS_WALL(Feld[lx + 1][ly]))
1084 right_stopped = TRUE;
1086 if (left_stopped && right_stopped)
1088 else if (left_stopped)
1090 graphic = IMG_EXPANDABLE_WALL_GROWING_RIGHT;
1091 frame = graphic_info[graphic].anim_frames - 1;
1093 else if (right_stopped)
1095 graphic = IMG_EXPANDABLE_WALL_GROWING_LEFT;
1096 frame = graphic_info[graphic].anim_frames - 1;
1101 DrawGraphicShifted(x, y, dx, dy, graphic, frame, cut_mode, mask_mode);
1102 else if (mask_mode == USE_MASKING)
1103 DrawGraphicThruMask(x, y, graphic, frame);
1105 DrawGraphic(x, y, graphic, frame);
1108 void DrawLevelElementExt(int x, int y, int dx, int dy, int element,
1109 int cut_mode, int mask_mode)
1111 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1112 DrawScreenElementExt(SCREENX(x), SCREENY(y), dx, dy, element,
1113 cut_mode, mask_mode);
1116 void DrawScreenElementShifted(int x, int y, int dx, int dy, int element,
1119 DrawScreenElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
1122 void DrawLevelElementShifted(int x, int y, int dx, int dy, int element,
1125 DrawLevelElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
1128 void DrawLevelElementThruMask(int x, int y, int element)
1130 DrawLevelElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
1133 void DrawLevelFieldThruMask(int x, int y)
1135 DrawLevelElementExt(x, y, 0, 0, Feld[x][y], NO_CUTTING, USE_MASKING);
1138 static void DrawLevelFieldCrumbledSandExt(int x, int y, int graphic, int frame)
1142 int sx = SCREENX(x), sy = SCREENY(y);
1144 int width, height, cx, cy, i;
1145 int snip = TILEX / 8; /* number of border pixels from "crumbled graphic" */
1146 static int xy[4][2] =
1154 if (!IN_LEV_FIELD(x, y))
1157 element = (GfxElement[x][y] != EL_UNDEFINED ? GfxElement[x][y] : Feld[x][y]);
1159 /* crumble field itself */
1160 if (CAN_BE_CRUMBLED(element) && !IS_MOVING(x, y))
1162 if (!IN_SCR_FIELD(sx, sy))
1165 getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
1169 int xx = x + xy[i][0];
1170 int yy = y + xy[i][1];
1172 element = (IN_LEV_FIELD(xx, yy) ? Feld[xx][yy] : BorderElement);
1174 /* check if neighbour field is of same type */
1175 if (CAN_BE_CRUMBLED(element) && !IS_MOVING(xx, yy))
1178 if (i == 1 || i == 2)
1182 cx = (i == 2 ? TILEX - snip : 0);
1190 cy = (i == 3 ? TILEY - snip : 0);
1193 BlitBitmap(src_bitmap, drawto_field, src_x + cx, src_y + cy,
1194 width, height, FX + sx * TILEX + cx, FY + sy * TILEY + cy);
1197 MarkTileDirty(sx, sy);
1199 else /* crumble neighbour fields */
1201 getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
1205 int xx = x + xy[i][0];
1206 int yy = y + xy[i][1];
1207 int sxx = sx + xy[i][0];
1208 int syy = sy + xy[i][1];
1210 if (!IN_LEV_FIELD(xx, yy) ||
1211 !IN_SCR_FIELD(sxx, syy) ||
1212 !CAN_BE_CRUMBLED(Feld[xx][yy]) ||
1216 if (i == 1 || i == 2)
1220 cx = (i == 1 ? TILEX - snip : 0);
1228 cy = (i==0 ? TILEY-snip : 0);
1231 BlitBitmap(src_bitmap, drawto_field, src_x + cx, src_y + cy,
1232 width, height, FX + sxx * TILEX + cx, FY + syy * TILEY + cy);
1234 MarkTileDirty(sxx, syy);
1239 void DrawLevelFieldCrumbledSand(int x, int y)
1241 DrawLevelFieldCrumbledSandExt(x, y, IMG_SAND_CRUMBLED, 0);
1244 void DrawLevelFieldCrumbledSandDigging(int x, int y, int direction,
1247 int graphic1 = el_act_dir2img(EL_SAND, ACTION_DIGGING, direction);
1248 int graphic2 = el_act_dir2img(EL_SAND_CRUMBLED, ACTION_DIGGING, direction);
1249 int frame1 = getGraphicAnimationFrame(graphic1, step_frame);
1250 int frame2 = getGraphicAnimationFrame(graphic2, step_frame);
1251 int sx = SCREENX(x), sy = SCREENY(y);
1253 DrawGraphic(sx, sy, graphic1, frame1);
1254 DrawLevelFieldCrumbledSandExt(x, y, graphic2, frame2);
1257 void DrawLevelFieldCrumbledSandNeighbours(int x, int y)
1259 int sx = SCREENX(x), sy = SCREENY(y);
1260 static int xy[4][2] =
1271 int xx = x + xy[i][0];
1272 int yy = y + xy[i][1];
1273 int sxx = sx + xy[i][0];
1274 int syy = sy + xy[i][1];
1276 if (!IN_LEV_FIELD(xx, yy) ||
1277 !IN_SCR_FIELD(sxx, syy) ||
1278 !CAN_BE_CRUMBLED(Feld[xx][yy]) ||
1282 DrawLevelField(xx, yy);
1286 static int getBorderElement(int x, int y)
1290 { EL_STEELWALL_TOPLEFT, EL_INVISIBLE_STEELWALL_TOPLEFT },
1291 { EL_STEELWALL_TOPRIGHT, EL_INVISIBLE_STEELWALL_TOPRIGHT },
1292 { EL_STEELWALL_BOTTOMLEFT, EL_INVISIBLE_STEELWALL_BOTTOMLEFT },
1293 { EL_STEELWALL_BOTTOMRIGHT, EL_INVISIBLE_STEELWALL_BOTTOMRIGHT },
1294 { EL_STEELWALL_VERTICAL, EL_INVISIBLE_STEELWALL_VERTICAL },
1295 { EL_STEELWALL_HORIZONTAL, EL_INVISIBLE_STEELWALL_HORIZONTAL },
1296 { EL_STEELWALL, EL_INVISIBLE_STEELWALL }
1298 int steel_type = (BorderElement == EL_STEELWALL ? 0 : 1);
1299 int steel_position = (x == -1 && y == -1 ? 0 :
1300 x == lev_fieldx && y == -1 ? 1 :
1301 x == -1 && y == lev_fieldy ? 2 :
1302 x == lev_fieldx && y == lev_fieldy ? 3 :
1303 x == -1 || x == lev_fieldx ? 4 :
1304 y == -1 || y == lev_fieldy ? 5 : 6);
1306 return border[steel_position][steel_type];
1309 void DrawScreenElement(int x, int y, int element)
1311 DrawScreenElementExt(x, y, 0, 0, element, NO_CUTTING, NO_MASKING);
1312 DrawLevelFieldCrumbledSand(LEVELX(x), LEVELY(y));
1315 void DrawLevelElement(int x, int y, int element)
1317 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1318 DrawScreenElement(SCREENX(x), SCREENY(y), element);
1321 void DrawScreenField(int x, int y)
1323 int lx = LEVELX(x), ly = LEVELY(y);
1324 int element, content;
1326 if (!IN_LEV_FIELD(lx, ly))
1328 if (lx < -1 || lx > lev_fieldx || ly < -1 || ly > lev_fieldy)
1331 element = getBorderElement(lx, ly);
1333 DrawScreenElement(x, y, element);
1337 element = Feld[lx][ly];
1338 content = Store[lx][ly];
1340 if (IS_MOVING(lx, ly))
1342 int horiz_move = (MovDir[lx][ly] == MV_LEFT || MovDir[lx][ly] == MV_RIGHT);
1343 boolean cut_mode = NO_CUTTING;
1345 if (element == EL_QUICKSAND_EMPTYING ||
1346 element == EL_MAGIC_WALL_EMPTYING ||
1347 element == EL_BD_MAGIC_WALL_EMPTYING ||
1348 element == EL_AMOEBA_DROPPING)
1349 cut_mode = CUT_ABOVE;
1350 else if (element == EL_QUICKSAND_FILLING ||
1351 element == EL_MAGIC_WALL_FILLING ||
1352 element == EL_BD_MAGIC_WALL_FILLING)
1353 cut_mode = CUT_BELOW;
1355 if (cut_mode == CUT_ABOVE)
1356 DrawScreenElementShifted(x, y, 0, 0, element, NO_CUTTING);
1358 DrawScreenElement(x, y, EL_EMPTY);
1361 DrawScreenElementShifted(x, y, MovPos[lx][ly], 0, element, NO_CUTTING);
1362 else if (cut_mode == NO_CUTTING)
1363 DrawScreenElementShifted(x, y, 0, MovPos[lx][ly], element, cut_mode);
1365 DrawScreenElementShifted(x, y, 0, MovPos[lx][ly], content, cut_mode);
1367 if (content == EL_ACID)
1368 DrawLevelElementThruMask(lx, ly + 1, EL_ACID);
1370 else if (IS_BLOCKED(lx, ly))
1375 boolean cut_mode = NO_CUTTING;
1376 int element_old, content_old;
1378 Blocked2Moving(lx, ly, &oldx, &oldy);
1381 horiz_move = (MovDir[oldx][oldy] == MV_LEFT ||
1382 MovDir[oldx][oldy] == MV_RIGHT);
1384 element_old = Feld[oldx][oldy];
1385 content_old = Store[oldx][oldy];
1387 if (element_old == EL_QUICKSAND_EMPTYING ||
1388 element_old == EL_MAGIC_WALL_EMPTYING ||
1389 element_old == EL_BD_MAGIC_WALL_EMPTYING ||
1390 element_old == EL_AMOEBA_DROPPING)
1391 cut_mode = CUT_ABOVE;
1393 DrawScreenElement(x, y, EL_EMPTY);
1396 DrawScreenElementShifted(sx, sy, MovPos[oldx][oldy], 0, element_old,
1398 else if (cut_mode == NO_CUTTING)
1399 DrawScreenElementShifted(sx, sy, 0, MovPos[oldx][oldy], element_old,
1402 DrawScreenElementShifted(sx, sy, 0, MovPos[oldx][oldy], content_old,
1405 else if (IS_DRAWABLE(element))
1406 DrawScreenElement(x, y, element);
1408 DrawScreenElement(x, y, EL_EMPTY);
1411 void DrawLevelField(int x, int y)
1413 if (IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1414 DrawScreenField(SCREENX(x), SCREENY(y));
1415 else if (IS_MOVING(x, y))
1419 Moving2Blocked(x, y, &newx, &newy);
1420 if (IN_SCR_FIELD(SCREENX(newx), SCREENY(newy)))
1421 DrawScreenField(SCREENX(newx), SCREENY(newy));
1423 else if (IS_BLOCKED(x, y))
1427 Blocked2Moving(x, y, &oldx, &oldy);
1428 if (IN_SCR_FIELD(SCREENX(oldx), SCREENY(oldy)))
1429 DrawScreenField(SCREENX(oldx), SCREENY(oldy));
1433 void DrawMiniElement(int x, int y, int element)
1437 graphic = el2edimg(element);
1438 DrawMiniGraphic(x, y, graphic);
1441 void DrawMiniElementOrWall(int sx, int sy, int scroll_x, int scroll_y)
1443 int x = sx + scroll_x, y = sy + scroll_y;
1445 if (x < -1 || x > lev_fieldx || y < -1 || y > lev_fieldy)
1446 DrawMiniElement(sx, sy, EL_EMPTY);
1447 else if (x > -1 && x < lev_fieldx && y > -1 && y < lev_fieldy)
1448 DrawMiniElement(sx, sy, Feld[x][y]);
1450 DrawMiniGraphic(sx, sy, el2edimg(getBorderElement(x, y)));
1453 void getMicroGraphicSource(int graphic, Bitmap **bitmap, int *x, int *y)
1455 Bitmap *src_bitmap = graphic_info[graphic].bitmap;
1456 int mini_startx = src_bitmap->width * 3 / 4;
1457 int mini_starty = src_bitmap->height * 2 / 3;
1458 int src_x = mini_startx + graphic_info[graphic].src_x / 8;
1459 int src_y = mini_starty + graphic_info[graphic].src_y / 8;
1461 *bitmap = src_bitmap;
1466 void DrawMicroElement(int xpos, int ypos, int element)
1470 int graphic = el2preimg(element);
1472 getMicroGraphicSource(graphic, &src_bitmap, &src_x, &src_y);
1473 BlitBitmap(src_bitmap, drawto, src_x, src_y, MICRO_TILEX, MICRO_TILEY,
1481 SetDrawBackgroundMask(REDRAW_NONE);
1484 for(x=BX1; x<=BX2; x++)
1485 for(y=BY1; y<=BY2; y++)
1486 DrawScreenField(x, y);
1488 redraw_mask |= REDRAW_FIELD;
1491 void DrawMiniLevel(int size_x, int size_y, int scroll_x, int scroll_y)
1495 for(x=0; x<size_x; x++)
1496 for(y=0; y<size_y; y++)
1497 DrawMiniElementOrWall(x, y, scroll_x, scroll_y);
1499 redraw_mask |= REDRAW_FIELD;
1502 static void DrawMicroLevelExt(int xpos, int ypos, int from_x, int from_y)
1506 DrawBackground(xpos, ypos, MICROLEV_XSIZE, MICROLEV_YSIZE);
1508 if (lev_fieldx < STD_LEV_FIELDX)
1509 xpos += (STD_LEV_FIELDX - lev_fieldx) / 2 * MICRO_TILEX;
1510 if (lev_fieldy < STD_LEV_FIELDY)
1511 ypos += (STD_LEV_FIELDY - lev_fieldy) / 2 * MICRO_TILEY;
1513 xpos += MICRO_TILEX;
1514 ypos += MICRO_TILEY;
1516 for(x=-1; x<=STD_LEV_FIELDX; x++)
1518 for(y=-1; y<=STD_LEV_FIELDY; y++)
1520 int lx = from_x + x, ly = from_y + y;
1522 if (lx >= 0 && lx < lev_fieldx && ly >= 0 && ly < lev_fieldy)
1523 DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
1525 else if (lx >= -1 && lx < lev_fieldx+1 && ly >= -1 && ly < lev_fieldy+1
1526 && BorderElement != EL_EMPTY)
1527 DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
1528 getBorderElement(lx, ly));
1532 redraw_mask |= REDRAW_MICROLEVEL;
1535 #define MICROLABEL_EMPTY 0
1536 #define MICROLABEL_LEVEL_NAME 1
1537 #define MICROLABEL_CREATED_BY 2
1538 #define MICROLABEL_LEVEL_AUTHOR 3
1539 #define MICROLABEL_IMPORTED_FROM 4
1540 #define MICROLABEL_LEVEL_IMPORT_INFO 5
1542 static void DrawMicroLevelLabelExt(int mode)
1544 char label_text[MAX_OUTPUT_LINESIZE + 1];
1545 int max_len_label_text;
1546 int font_nr = FONT_TEXT_2;
1548 if (mode == MICROLABEL_CREATED_BY || mode == MICROLABEL_IMPORTED_FROM)
1549 font_nr = FONT_TEXT_3;
1551 max_len_label_text = SXSIZE / getFontWidth(font_nr);
1553 DrawBackground(SX, MICROLABEL_YPOS, SXSIZE, getFontHeight(font_nr));
1555 strncpy(label_text, (mode == MICROLABEL_LEVEL_NAME ? level.name :
1556 mode == MICROLABEL_CREATED_BY ? "created by" :
1557 mode == MICROLABEL_LEVEL_AUTHOR ? level.author :
1558 mode == MICROLABEL_IMPORTED_FROM ? "imported from" :
1559 mode == MICROLABEL_LEVEL_IMPORT_INFO ?
1560 leveldir_current->imported_from : ""),
1561 max_len_label_text);
1562 label_text[max_len_label_text] = '\0';
1564 if (strlen(label_text) > 0)
1566 int text_width = strlen(label_text) * getFontWidth(font_nr);
1567 int lxpos = SX + (SXSIZE - text_width) / 2;
1568 int lypos = MICROLABEL_YPOS;
1570 DrawText(lxpos, lypos, label_text, font_nr);
1573 redraw_mask |= REDRAW_MICROLEVEL;
1576 void DrawMicroLevel(int xpos, int ypos, boolean restart)
1578 static unsigned long scroll_delay = 0;
1579 static unsigned long label_delay = 0;
1580 static int from_x, from_y, scroll_direction;
1581 static int label_state, label_counter;
1582 int last_game_status = game_status; /* save current game status */
1584 /* force PREVIEW font on preview level */
1585 game_status = GAME_MODE_PSEUDO_PREVIEW;
1589 from_x = from_y = 0;
1590 scroll_direction = MV_RIGHT;
1594 DrawMicroLevelExt(xpos, ypos, from_x, from_y);
1595 DrawMicroLevelLabelExt(label_state);
1597 /* initialize delay counters */
1598 DelayReached(&scroll_delay, 0);
1599 DelayReached(&label_delay, 0);
1601 if (leveldir_current->name)
1603 int len = strlen(leveldir_current->name);
1604 int lxpos = SX + (SXSIZE - len * getFontWidth(FONT_TEXT_1)) / 2;
1605 int lypos = SY + 352;
1607 DrawText(lxpos, lypos, leveldir_current->name, FONT_TEXT_1);
1610 game_status = last_game_status; /* restore current game status */
1615 /* scroll micro level, if needed */
1616 if ((lev_fieldx > STD_LEV_FIELDX || lev_fieldy > STD_LEV_FIELDY) &&
1617 DelayReached(&scroll_delay, MICROLEVEL_SCROLL_DELAY))
1619 switch (scroll_direction)
1625 scroll_direction = MV_UP;
1629 if (from_x < lev_fieldx - STD_LEV_FIELDX)
1632 scroll_direction = MV_DOWN;
1639 scroll_direction = MV_RIGHT;
1643 if (from_y < lev_fieldy - STD_LEV_FIELDY)
1646 scroll_direction = MV_LEFT;
1653 DrawMicroLevelExt(xpos, ypos, from_x, from_y);
1656 /* redraw micro level label, if needed */
1657 if (strcmp(level.name, NAMELESS_LEVEL_NAME) != 0 &&
1658 strcmp(level.author, ANONYMOUS_NAME) != 0 &&
1659 strcmp(level.author, leveldir_current->name) != 0 &&
1660 DelayReached(&label_delay, MICROLEVEL_LABEL_DELAY))
1662 int max_label_counter = 23;
1664 if (leveldir_current->imported_from != NULL)
1665 max_label_counter += 14;
1667 label_counter = (label_counter + 1) % max_label_counter;
1668 label_state = (label_counter >= 0 && label_counter <= 7 ?
1669 MICROLABEL_LEVEL_NAME :
1670 label_counter >= 9 && label_counter <= 12 ?
1671 MICROLABEL_CREATED_BY :
1672 label_counter >= 14 && label_counter <= 21 ?
1673 MICROLABEL_LEVEL_AUTHOR :
1674 label_counter >= 23 && label_counter <= 26 ?
1675 MICROLABEL_IMPORTED_FROM :
1676 label_counter >= 28 && label_counter <= 35 ?
1677 MICROLABEL_LEVEL_IMPORT_INFO : MICROLABEL_EMPTY);
1678 DrawMicroLevelLabelExt(label_state);
1681 game_status = last_game_status; /* restore current game status */
1684 int REQ_in_range(int x, int y)
1686 if (y > DY+249 && y < DY+278)
1688 if (x > DX+1 && x < DX+48)
1690 else if (x > DX+51 && x < DX+98)
1696 #define MAX_REQUEST_LINES 13
1697 #define MAX_REQUEST_LINE_LEN 7
1699 boolean Request(char *text, unsigned int req_state)
1701 int mx, my, ty, result = -1;
1702 unsigned int old_door_state;
1703 int last_game_status = game_status; /* save current game status */
1705 #if defined(PLATFORM_UNIX)
1706 /* pause network game while waiting for request to answer */
1707 if (options.network &&
1708 game_status == GAME_MODE_PLAYING &&
1709 req_state & REQUEST_WAIT_FOR)
1710 SendToServer_PausePlaying();
1713 old_door_state = GetDoorState();
1717 CloseDoor(DOOR_CLOSE_1);
1719 /* save old door content */
1720 BlitBitmap(bitmap_db_door, bitmap_db_door,
1721 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE,
1722 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1);
1724 SetDrawBackgroundMask(REDRAW_FIELD | REDRAW_DOOR_1);
1726 /* clear door drawing field */
1727 DrawBackground(DX, DY, DXSIZE, DYSIZE);
1729 /* force DOOR font on preview level */
1730 game_status = GAME_MODE_PSEUDO_DOOR;
1732 /* write text for request */
1733 for(ty=0; ty < MAX_REQUEST_LINES; ty++)
1735 char text_line[MAX_REQUEST_LINE_LEN + 1];
1741 for(tl=0,tx=0; tx < MAX_REQUEST_LINE_LEN; tl++,tx++)
1744 if (!tc || tc == ' ')
1755 strncpy(text_line, text, tl);
1758 DrawText(DX + (DXSIZE - tl * getFontWidth(FONT_TEXT_2)) / 2,
1759 DY + 8 + ty * (getFontHeight(FONT_TEXT_2) + 2),
1760 text_line, FONT_TEXT_2);
1762 text += tl + (tc == ' ' ? 1 : 0);
1765 game_status = last_game_status; /* restore current game status */
1767 if (req_state & REQ_ASK)
1769 MapGadget(tool_gadget[TOOL_CTRL_ID_YES]);
1770 MapGadget(tool_gadget[TOOL_CTRL_ID_NO]);
1772 else if (req_state & REQ_CONFIRM)
1774 MapGadget(tool_gadget[TOOL_CTRL_ID_CONFIRM]);
1776 else if (req_state & REQ_PLAYER)
1778 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_1]);
1779 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_2]);
1780 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_3]);
1781 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_4]);
1784 /* copy request gadgets to door backbuffer */
1785 BlitBitmap(drawto, bitmap_db_door,
1786 DX, DY, DXSIZE, DYSIZE,
1787 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
1789 OpenDoor(DOOR_OPEN_1);
1795 if (!(req_state & REQUEST_WAIT_FOR))
1797 SetDrawBackgroundMask(REDRAW_FIELD);
1802 if (game_status != GAME_MODE_MAIN)
1805 button_status = MB_RELEASED;
1807 request_gadget_id = -1;
1809 SetDrawBackgroundMask(REDRAW_FIELD | REDRAW_DOOR_1);
1821 case EVENT_BUTTONPRESS:
1822 case EVENT_BUTTONRELEASE:
1823 case EVENT_MOTIONNOTIFY:
1825 if (event.type == EVENT_MOTIONNOTIFY)
1827 if (!PointerInWindow(window))
1828 continue; /* window and pointer are on different screens */
1833 motion_status = TRUE;
1834 mx = ((MotionEvent *) &event)->x;
1835 my = ((MotionEvent *) &event)->y;
1839 motion_status = FALSE;
1840 mx = ((ButtonEvent *) &event)->x;
1841 my = ((ButtonEvent *) &event)->y;
1842 if (event.type == EVENT_BUTTONPRESS)
1843 button_status = ((ButtonEvent *) &event)->button;
1845 button_status = MB_RELEASED;
1848 /* this sets 'request_gadget_id' */
1849 HandleGadgets(mx, my, button_status);
1851 switch(request_gadget_id)
1853 case TOOL_CTRL_ID_YES:
1856 case TOOL_CTRL_ID_NO:
1859 case TOOL_CTRL_ID_CONFIRM:
1860 result = TRUE | FALSE;
1863 case TOOL_CTRL_ID_PLAYER_1:
1866 case TOOL_CTRL_ID_PLAYER_2:
1869 case TOOL_CTRL_ID_PLAYER_3:
1872 case TOOL_CTRL_ID_PLAYER_4:
1883 case EVENT_KEYPRESS:
1884 switch(GetEventKey((KeyEvent *)&event, TRUE))
1897 if (req_state & REQ_PLAYER)
1901 case EVENT_KEYRELEASE:
1902 ClearPlayerAction();
1906 HandleOtherEvents(&event);
1910 else if (AnyJoystickButton() == JOY_BUTTON_NEW_PRESSED)
1912 int joy = AnyJoystick();
1914 if (joy & JOY_BUTTON_1)
1916 else if (joy & JOY_BUTTON_2)
1922 /* don't eat all CPU time */
1926 if (game_status != GAME_MODE_MAIN)
1931 if (!(req_state & REQ_STAY_OPEN))
1933 CloseDoor(DOOR_CLOSE_1);
1935 if (!(req_state & REQ_STAY_CLOSED) && (old_door_state & DOOR_OPEN_1))
1937 BlitBitmap(bitmap_db_door, bitmap_db_door,
1938 DOOR_GFX_PAGEX2,DOOR_GFX_PAGEY1, DXSIZE,DYSIZE,
1939 DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY1);
1940 OpenDoor(DOOR_OPEN_1);
1946 SetDrawBackgroundMask(REDRAW_FIELD);
1948 #if defined(PLATFORM_UNIX)
1949 /* continue network game after request */
1950 if (options.network &&
1951 game_status == GAME_MODE_PLAYING &&
1952 req_state & REQUEST_WAIT_FOR)
1953 SendToServer_ContinuePlaying();
1959 unsigned int OpenDoor(unsigned int door_state)
1961 unsigned int new_door_state;
1963 if (door_state & DOOR_COPY_BACK)
1965 BlitBitmap(bitmap_db_door, bitmap_db_door,
1966 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE + VYSIZE,
1967 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
1968 door_state &= ~DOOR_COPY_BACK;
1971 new_door_state = MoveDoor(door_state);
1973 return(new_door_state);
1976 unsigned int CloseDoor(unsigned int door_state)
1978 unsigned int new_door_state;
1980 BlitBitmap(backbuffer, bitmap_db_door,
1981 DX, DY, DXSIZE, DYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
1982 BlitBitmap(backbuffer, bitmap_db_door,
1983 VX, VY, VXSIZE, VYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2);
1985 new_door_state = MoveDoor(door_state);
1987 return(new_door_state);
1990 unsigned int GetDoorState()
1992 return MoveDoor(DOOR_GET_STATE);
1995 unsigned int SetDoorState(unsigned int door_state)
1997 return MoveDoor(door_state | DOOR_SET_STATE);
2000 unsigned int MoveDoor(unsigned int door_state)
2002 static int door1 = DOOR_OPEN_1;
2003 static int door2 = DOOR_CLOSE_2;
2004 static unsigned long door_delay = 0;
2005 int x, start, stepsize = door.step_offset;
2006 unsigned long door_delay_value = door.step_delay;
2008 if (door_state == DOOR_GET_STATE)
2009 return(door1 | door2);
2011 if (door_state & DOOR_SET_STATE)
2013 if (door_state & DOOR_ACTION_1)
2014 door1 = door_state & DOOR_ACTION_1;
2015 if (door_state & DOOR_ACTION_2)
2016 door2 = door_state & DOOR_ACTION_2;
2018 return(door1 | door2);
2021 if (door1 == DOOR_OPEN_1 && door_state & DOOR_OPEN_1)
2022 door_state &= ~DOOR_OPEN_1;
2023 else if (door1 == DOOR_CLOSE_1 && door_state & DOOR_CLOSE_1)
2024 door_state &= ~DOOR_CLOSE_1;
2025 if (door2 == DOOR_OPEN_2 && door_state & DOOR_OPEN_2)
2026 door_state &= ~DOOR_OPEN_2;
2027 else if (door2 == DOOR_CLOSE_2 && door_state & DOOR_CLOSE_2)
2028 door_state &= ~DOOR_CLOSE_2;
2030 if (setup.quick_doors)
2033 door_delay_value = 0;
2035 StopSound(SND_DOOR_OPENING);
2036 StopSound(SND_DOOR_CLOSING);
2039 if (global.autoplay_leveldir)
2041 door_state |= DOOR_NO_DELAY;
2042 door_state &= ~DOOR_CLOSE_ALL;
2045 if (door_state & DOOR_ACTION)
2047 if (!(door_state & DOOR_NO_DELAY))
2049 /* opening door sound has priority over simultaneously closing door */
2050 if (door_state & (DOOR_OPEN_1 | DOOR_OPEN_2))
2051 PlaySoundStereo(SND_DOOR_OPENING, SOUND_MIDDLE);
2052 else if (door_state & (DOOR_CLOSE_1 | DOOR_CLOSE_2))
2053 PlaySoundStereo(SND_DOOR_CLOSING, SOUND_MIDDLE);
2056 start = ((door_state & DOOR_NO_DELAY) ? DXSIZE : 0);
2058 for(x=start; x<=DXSIZE; x+=stepsize)
2060 Bitmap *bitmap = graphic_info[IMG_GLOBAL_DOOR].bitmap;
2061 GC gc = bitmap->stored_clip_gc;
2063 if (!(door_state & DOOR_NO_DELAY))
2064 WaitUntilDelayReached(&door_delay, door_delay_value);
2066 if (door_state & DOOR_ACTION_1)
2068 int i = (door_state & DOOR_OPEN_1 ? DXSIZE-x : x);
2069 int j = (DXSIZE - i) / 3;
2071 BlitBitmap(bitmap_db_door, drawto,
2072 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1 + i/2,
2073 DXSIZE,DYSIZE - i/2, DX, DY);
2075 ClearRectangle(drawto, DX, DY + DYSIZE - i/2, DXSIZE,i/2);
2077 SetClipOrigin(bitmap, gc, DX - i, (DY + j) - DOOR_GFX_PAGEY1);
2078 BlitBitmapMasked(bitmap, drawto,
2079 DXSIZE, DOOR_GFX_PAGEY1, i, 77,
2080 DX + DXSIZE - i, DY + j);
2081 BlitBitmapMasked(bitmap, drawto,
2082 DXSIZE, DOOR_GFX_PAGEY1 + 140, i, 63,
2083 DX + DXSIZE - i, DY + 140 + j);
2084 SetClipOrigin(bitmap, gc, DX - DXSIZE + i, DY - (DOOR_GFX_PAGEY1 + j));
2085 BlitBitmapMasked(bitmap, drawto,
2086 DXSIZE - i, DOOR_GFX_PAGEY1 + j, i, 77 - j,
2088 BlitBitmapMasked(bitmap, drawto,
2089 DXSIZE-i, DOOR_GFX_PAGEY1 + 140, i, 63,
2092 BlitBitmapMasked(bitmap, drawto,
2093 DXSIZE - i, DOOR_GFX_PAGEY1 + 77, i, 63,
2095 BlitBitmapMasked(bitmap, drawto,
2096 DXSIZE - i, DOOR_GFX_PAGEY1 + 203, i, 77,
2098 SetClipOrigin(bitmap, gc, DX - i, (DY + j) - DOOR_GFX_PAGEY1);
2099 BlitBitmapMasked(bitmap, drawto,
2100 DXSIZE, DOOR_GFX_PAGEY1 + 77, i, 63,
2101 DX + DXSIZE - i, DY + 77 + j);
2102 BlitBitmapMasked(bitmap, drawto,
2103 DXSIZE, DOOR_GFX_PAGEY1 + 203, i, 77 - j,
2104 DX + DXSIZE - i, DY + 203 + j);
2106 redraw_mask |= REDRAW_DOOR_1;
2109 if (door_state & DOOR_ACTION_2)
2111 int i = (door_state & DOOR_OPEN_2 ? VXSIZE - x : x);
2112 int j = (VXSIZE - i) / 3;
2114 BlitBitmap(bitmap_db_door, drawto,
2115 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2 + i/2,
2116 VXSIZE, VYSIZE - i/2, VX, VY);
2118 ClearRectangle(drawto, VX, VY + VYSIZE-i/2, VXSIZE, i/2);
2120 SetClipOrigin(bitmap, gc, VX - i, (VY + j) - DOOR_GFX_PAGEY2);
2121 BlitBitmapMasked(bitmap, drawto,
2122 VXSIZE, DOOR_GFX_PAGEY2, i, VYSIZE / 2,
2123 VX + VXSIZE-i, VY+j);
2124 SetClipOrigin(bitmap, gc,
2125 VX - VXSIZE + i, VY - (DOOR_GFX_PAGEY2 + j));
2126 BlitBitmapMasked(bitmap, drawto,
2127 VXSIZE - i, DOOR_GFX_PAGEY2 + j, i, VYSIZE / 2 - j,
2130 BlitBitmapMasked(bitmap, drawto,
2131 VXSIZE - i, DOOR_GFX_PAGEY2 + VYSIZE / 2,
2132 i, VYSIZE / 2, VX, VY + VYSIZE / 2 - j);
2133 SetClipOrigin(bitmap, gc, VX - i, (VY + j) - DOOR_GFX_PAGEY2);
2134 BlitBitmapMasked(bitmap, drawto,
2135 VXSIZE, DOOR_GFX_PAGEY2 + VYSIZE / 2,
2137 VX + VXSIZE - i, VY + VYSIZE / 2 + j);
2139 redraw_mask |= REDRAW_DOOR_2;
2144 if (game_status == GAME_MODE_MAIN)
2149 if (setup.quick_doors)
2151 StopSound(SND_DOOR_OPENING);
2152 StopSound(SND_DOOR_CLOSING);
2155 if (door_state & DOOR_ACTION_1)
2156 door1 = door_state & DOOR_ACTION_1;
2157 if (door_state & DOOR_ACTION_2)
2158 door2 = door_state & DOOR_ACTION_2;
2160 return (door1 | door2);
2163 void DrawSpecialEditorDoor()
2165 /* draw bigger toolbox window */
2166 BlitBitmap(graphic_info[IMG_GLOBAL_DOOR].bitmap, drawto,
2167 DOOR_GFX_PAGEX7, 0, EXSIZE + 8, 8,
2169 BlitBitmap(graphic_info[IMG_GLOBAL_BORDER].bitmap, drawto,
2170 EX - 4, VY - 4, EXSIZE + 8, EYSIZE - VYSIZE + 4,
2173 redraw_mask |= REDRAW_ALL;
2176 void UndrawSpecialEditorDoor()
2178 /* draw normal tape recorder window */
2179 BlitBitmap(graphic_info[IMG_GLOBAL_BORDER].bitmap, drawto,
2180 EX - 4, EY - 12, EXSIZE + 8, EYSIZE - VYSIZE + 12,
2183 redraw_mask |= REDRAW_ALL;
2187 /* ---------- new tool button stuff ---------------------------------------- */
2189 /* graphic position values for tool buttons */
2190 #define TOOL_BUTTON_YES_XPOS 2
2191 #define TOOL_BUTTON_YES_YPOS 250
2192 #define TOOL_BUTTON_YES_GFX_YPOS 0
2193 #define TOOL_BUTTON_YES_XSIZE 46
2194 #define TOOL_BUTTON_YES_YSIZE 28
2195 #define TOOL_BUTTON_NO_XPOS 52
2196 #define TOOL_BUTTON_NO_YPOS TOOL_BUTTON_YES_YPOS
2197 #define TOOL_BUTTON_NO_GFX_YPOS TOOL_BUTTON_YES_GFX_YPOS
2198 #define TOOL_BUTTON_NO_XSIZE TOOL_BUTTON_YES_XSIZE
2199 #define TOOL_BUTTON_NO_YSIZE TOOL_BUTTON_YES_YSIZE
2200 #define TOOL_BUTTON_CONFIRM_XPOS TOOL_BUTTON_YES_XPOS
2201 #define TOOL_BUTTON_CONFIRM_YPOS TOOL_BUTTON_YES_YPOS
2202 #define TOOL_BUTTON_CONFIRM_GFX_YPOS 30
2203 #define TOOL_BUTTON_CONFIRM_XSIZE 96
2204 #define TOOL_BUTTON_CONFIRM_YSIZE TOOL_BUTTON_YES_YSIZE
2205 #define TOOL_BUTTON_PLAYER_XSIZE 30
2206 #define TOOL_BUTTON_PLAYER_YSIZE 30
2207 #define TOOL_BUTTON_PLAYER_GFX_XPOS 5
2208 #define TOOL_BUTTON_PLAYER_GFX_YPOS 185
2209 #define TOOL_BUTTON_PLAYER_XPOS (5 + TOOL_BUTTON_PLAYER_XSIZE / 2)
2210 #define TOOL_BUTTON_PLAYER_YPOS (215 - TOOL_BUTTON_PLAYER_YSIZE / 2)
2211 #define TOOL_BUTTON_PLAYER1_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2212 + 0 * TOOL_BUTTON_PLAYER_XSIZE)
2213 #define TOOL_BUTTON_PLAYER2_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2214 + 1 * TOOL_BUTTON_PLAYER_XSIZE)
2215 #define TOOL_BUTTON_PLAYER3_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2216 + 0 * TOOL_BUTTON_PLAYER_XSIZE)
2217 #define TOOL_BUTTON_PLAYER4_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2218 + 1 * TOOL_BUTTON_PLAYER_XSIZE)
2219 #define TOOL_BUTTON_PLAYER1_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2220 + 0 * TOOL_BUTTON_PLAYER_YSIZE)
2221 #define TOOL_BUTTON_PLAYER2_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2222 + 0 * TOOL_BUTTON_PLAYER_YSIZE)
2223 #define TOOL_BUTTON_PLAYER3_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2224 + 1 * TOOL_BUTTON_PLAYER_YSIZE)
2225 #define TOOL_BUTTON_PLAYER4_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2226 + 1 * TOOL_BUTTON_PLAYER_YSIZE)
2235 } toolbutton_info[NUM_TOOL_BUTTONS] =
2238 TOOL_BUTTON_YES_XPOS, TOOL_BUTTON_YES_GFX_YPOS,
2239 TOOL_BUTTON_YES_XPOS, TOOL_BUTTON_YES_YPOS,
2240 TOOL_BUTTON_YES_XSIZE, TOOL_BUTTON_YES_YSIZE,
2245 TOOL_BUTTON_NO_XPOS, TOOL_BUTTON_NO_GFX_YPOS,
2246 TOOL_BUTTON_NO_XPOS, TOOL_BUTTON_NO_YPOS,
2247 TOOL_BUTTON_NO_XSIZE, TOOL_BUTTON_NO_YSIZE,
2252 TOOL_BUTTON_CONFIRM_XPOS, TOOL_BUTTON_CONFIRM_GFX_YPOS,
2253 TOOL_BUTTON_CONFIRM_XPOS, TOOL_BUTTON_CONFIRM_YPOS,
2254 TOOL_BUTTON_CONFIRM_XSIZE, TOOL_BUTTON_CONFIRM_YSIZE,
2255 TOOL_CTRL_ID_CONFIRM,
2259 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2260 TOOL_BUTTON_PLAYER1_XPOS, TOOL_BUTTON_PLAYER1_YPOS,
2261 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2262 TOOL_CTRL_ID_PLAYER_1,
2266 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2267 TOOL_BUTTON_PLAYER2_XPOS, TOOL_BUTTON_PLAYER2_YPOS,
2268 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2269 TOOL_CTRL_ID_PLAYER_2,
2273 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2274 TOOL_BUTTON_PLAYER3_XPOS, TOOL_BUTTON_PLAYER3_YPOS,
2275 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2276 TOOL_CTRL_ID_PLAYER_3,
2280 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2281 TOOL_BUTTON_PLAYER4_XPOS, TOOL_BUTTON_PLAYER4_YPOS,
2282 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2283 TOOL_CTRL_ID_PLAYER_4,
2288 void CreateToolButtons()
2292 for (i=0; i<NUM_TOOL_BUTTONS; i++)
2294 Bitmap *gd_bitmap = graphic_info[IMG_GLOBAL_DOOR].bitmap;
2295 Bitmap *deco_bitmap = None;
2296 int deco_x = 0, deco_y = 0, deco_xpos = 0, deco_ypos = 0;
2297 struct GadgetInfo *gi;
2298 unsigned long event_mask;
2299 int gd_xoffset, gd_yoffset;
2300 int gd_x1, gd_x2, gd_y;
2303 event_mask = GD_EVENT_RELEASED;
2305 gd_xoffset = toolbutton_info[i].xpos;
2306 gd_yoffset = toolbutton_info[i].ypos;
2307 gd_x1 = DOOR_GFX_PAGEX4 + gd_xoffset;
2308 gd_x2 = DOOR_GFX_PAGEX3 + gd_xoffset;
2309 gd_y = DOOR_GFX_PAGEY1 + gd_yoffset;
2311 if (id >= TOOL_CTRL_ID_PLAYER_1 && id <= TOOL_CTRL_ID_PLAYER_4)
2313 int player_nr = id - TOOL_CTRL_ID_PLAYER_1;
2315 getMiniGraphicSource(PLAYER_NR_GFX(IMG_PLAYER_1, player_nr),
2316 &deco_bitmap, &deco_x, &deco_y);
2317 deco_xpos = (toolbutton_info[i].width - MINI_TILEX) / 2;
2318 deco_ypos = (toolbutton_info[i].height - MINI_TILEY) / 2;
2321 gi = CreateGadget(GDI_CUSTOM_ID, id,
2322 GDI_INFO_TEXT, toolbutton_info[i].infotext,
2323 GDI_X, DX + toolbutton_info[i].x,
2324 GDI_Y, DY + toolbutton_info[i].y,
2325 GDI_WIDTH, toolbutton_info[i].width,
2326 GDI_HEIGHT, toolbutton_info[i].height,
2327 GDI_TYPE, GD_TYPE_NORMAL_BUTTON,
2328 GDI_STATE, GD_BUTTON_UNPRESSED,
2329 GDI_DESIGN_UNPRESSED, gd_bitmap, gd_x1, gd_y,
2330 GDI_DESIGN_PRESSED, gd_bitmap, gd_x2, gd_y,
2331 GDI_DECORATION_DESIGN, deco_bitmap, deco_x, deco_y,
2332 GDI_DECORATION_POSITION, deco_xpos, deco_ypos,
2333 GDI_DECORATION_SIZE, MINI_TILEX, MINI_TILEY,
2334 GDI_DECORATION_SHIFTING, 1, 1,
2335 GDI_EVENT_MASK, event_mask,
2336 GDI_CALLBACK_ACTION, HandleToolButtons,
2340 Error(ERR_EXIT, "cannot create gadget");
2342 tool_gadget[id] = gi;
2346 void FreeToolButtons()
2350 for (i=0; i<NUM_TOOL_BUTTONS; i++)
2351 FreeGadget(tool_gadget[i]);
2354 static void UnmapToolButtons()
2358 for (i=0; i<NUM_TOOL_BUTTONS; i++)
2359 UnmapGadget(tool_gadget[i]);
2362 static void HandleToolButtons(struct GadgetInfo *gi)
2364 request_gadget_id = gi->custom_id;
2367 int get_next_element(int element)
2371 case EL_QUICKSAND_FILLING: return EL_QUICKSAND_FULL;
2372 case EL_QUICKSAND_EMPTYING: return EL_QUICKSAND_EMPTY;
2373 case EL_MAGIC_WALL_FILLING: return EL_MAGIC_WALL_FULL;
2374 case EL_MAGIC_WALL_EMPTYING: return EL_MAGIC_WALL_ACTIVE;
2375 case EL_BD_MAGIC_WALL_FILLING: return EL_BD_MAGIC_WALL_FULL;
2376 case EL_BD_MAGIC_WALL_EMPTYING: return EL_BD_MAGIC_WALL_ACTIVE;
2377 case EL_AMOEBA_DROPPING: return EL_AMOEBA_WET;
2379 default: return element;
2383 int el_act_dir2img(int element, int action, int direction)
2385 element = GFX_ELEMENT(element);
2386 direction = MV_DIR_BIT(direction);
2388 return element_info[element].direction_graphic[action][direction];
2391 int el_act2img(int element, int action)
2393 element = GFX_ELEMENT(element);
2395 return element_info[element].graphic[action];
2398 int el_dir2img(int element, int direction)
2400 element = GFX_ELEMENT(element);
2402 return el_act_dir2img(element, ACTION_DEFAULT, direction);
2405 int el2img(int element)
2407 element = GFX_ELEMENT(element);
2409 return element_info[element].graphic[ACTION_DEFAULT];
2412 int el2edimg(int element)
2414 element = GFX_ELEMENT(element);
2416 return element_info[element].special_graphic[GFX_SPECIAL_ARG_EDITOR];
2419 int el2preimg(int element)
2421 element = GFX_ELEMENT(element);
2423 return element_info[element].special_graphic[GFX_SPECIAL_ARG_PREVIEW];