1 /***********************************************************
2 * Rocks'n'Diamonds -- McDuffin Strikes Back! *
3 *----------------------------------------------------------*
4 * (c) 1995-2002 Artsoft Entertainment *
6 * Detmolder Strasse 189 *
9 * e-mail: info@artsoft.org *
10 *----------------------------------------------------------*
12 ***********************************************************/
14 #include "libgame/libgame.h"
23 /* tool button identifiers */
24 #define TOOL_CTRL_ID_YES 0
25 #define TOOL_CTRL_ID_NO 1
26 #define TOOL_CTRL_ID_CONFIRM 2
27 #define TOOL_CTRL_ID_PLAYER_1 3
28 #define TOOL_CTRL_ID_PLAYER_2 4
29 #define TOOL_CTRL_ID_PLAYER_3 5
30 #define TOOL_CTRL_ID_PLAYER_4 6
32 #define NUM_TOOL_BUTTONS 7
34 /* forward declaration for internal use */
35 static void UnmapToolButtons();
36 static void HandleToolButtons(struct GadgetInfo *);
37 static int el_act_dir2crm(int, int, int);
39 static struct GadgetInfo *tool_gadget[NUM_TOOL_BUTTONS];
40 static int request_gadget_id = -1;
42 void SetDrawtoField(int mode)
44 if (mode == DRAW_BUFFERED && setup.soft_scrolling)
55 drawto_field = fieldbuffer;
57 else /* DRAW_DIRECT, DRAW_BACKBUFFER */
68 drawto_field = (mode == DRAW_DIRECT ? window : backbuffer);
72 void RedrawPlayfield(boolean force_redraw, int x, int y, int width, int height)
74 if (game_status == GAME_MODE_PLAYING)
80 width = gfx.sxsize + 2 * TILEX;
81 height = gfx.sysize + 2 * TILEY;
84 if (force_redraw || setup.direct_draw)
87 int x1 = (x - SX) / TILEX, y1 = (y - SY) / TILEY;
88 int x2 = (x - SX + width) / TILEX, y2 = (y - SY + height) / TILEY;
90 if (setup.direct_draw)
91 SetDrawtoField(DRAW_BACKBUFFER);
93 for(xx=BX1; xx<=BX2; xx++)
94 for(yy=BY1; yy<=BY2; yy++)
95 if (xx >= x1 && xx <= x2 && yy >= y1 && yy <= y2)
96 DrawScreenField(xx, yy);
99 if (setup.direct_draw)
100 SetDrawtoField(DRAW_DIRECT);
103 if (setup.soft_scrolling)
105 int fx = FX, fy = FY;
107 fx += (ScreenMovDir & (MV_LEFT|MV_RIGHT) ? ScreenGfxPos : 0);
108 fy += (ScreenMovDir & (MV_UP|MV_DOWN) ? ScreenGfxPos : 0);
110 BlitBitmap(fieldbuffer, backbuffer, fx,fy, SXSIZE,SYSIZE, SX,SY);
114 BlitBitmap(drawto, window, x, y, width, height, x, y);
120 DrawBuffer *buffer = (drawto_field == window ? backbuffer : drawto_field);
122 if (setup.direct_draw && game_status == GAME_MODE_PLAYING)
123 redraw_mask &= ~REDRAW_MAIN;
125 if (redraw_mask & REDRAW_TILES && redraw_tiles > REDRAWTILES_THRESHOLD)
126 redraw_mask |= REDRAW_FIELD;
128 if (redraw_mask & REDRAW_FIELD)
129 redraw_mask &= ~REDRAW_TILES;
131 if (redraw_mask == REDRAW_NONE)
134 if (global.fps_slowdown && game_status == GAME_MODE_PLAYING)
136 static boolean last_frame_skipped = FALSE;
137 boolean skip_even_when_not_scrolling = TRUE;
138 boolean just_scrolling = (ScreenMovDir != 0);
139 boolean verbose = FALSE;
141 if (global.fps_slowdown_factor > 1 &&
142 (FrameCounter % global.fps_slowdown_factor) &&
143 (just_scrolling || skip_even_when_not_scrolling))
145 redraw_mask &= ~REDRAW_MAIN;
147 last_frame_skipped = TRUE;
150 printf("FRAME SKIPPED\n");
154 if (last_frame_skipped)
155 redraw_mask |= REDRAW_FIELD;
157 last_frame_skipped = FALSE;
160 printf("frame not skipped\n");
164 /* synchronize X11 graphics at this point; if we would synchronize the
165 display immediately after the buffer switching (after the XFlush),
166 this could mean that we have to wait for the graphics to complete,
167 although we could go on doing calculations for the next frame */
171 if (redraw_mask & REDRAW_ALL)
173 BlitBitmap(backbuffer, window, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
177 if (redraw_mask & REDRAW_FIELD)
179 if (game_status != GAME_MODE_PLAYING ||
180 redraw_mask & REDRAW_FROM_BACKBUFFER)
182 BlitBitmap(backbuffer, window,
183 REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE, REAL_SX, REAL_SY);
187 int fx = FX, fy = FY;
189 if (setup.soft_scrolling)
191 fx += (ScreenMovDir & (MV_LEFT | MV_RIGHT) ? ScreenGfxPos : 0);
192 fy += (ScreenMovDir & (MV_UP | MV_DOWN) ? ScreenGfxPos : 0);
195 if (setup.soft_scrolling ||
196 ABS(ScreenMovPos) + ScrollStepSize == TILEX ||
197 ABS(ScreenMovPos) == ScrollStepSize ||
198 redraw_tiles > REDRAWTILES_THRESHOLD)
200 BlitBitmap(buffer, window, fx, fy, SXSIZE, SYSIZE, SX, SY);
204 printf("redrawing all (ScreenGfxPos == %d) because %s\n",
206 (setup.soft_scrolling ?
207 "setup.soft_scrolling" :
208 ABS(ScreenGfxPos) + ScrollStepSize == TILEX ?
209 "ABS(ScreenGfxPos) + ScrollStepSize == TILEX" :
210 ABS(ScreenGfxPos) == ScrollStepSize ?
211 "ABS(ScreenGfxPos) == ScrollStepSize" :
212 "redraw_tiles > REDRAWTILES_THRESHOLD"));
218 redraw_mask &= ~REDRAW_MAIN;
221 if (redraw_mask & REDRAW_DOORS)
223 if (redraw_mask & REDRAW_DOOR_1)
224 BlitBitmap(backbuffer, window, DX, DY, DXSIZE, DYSIZE, DX, DY);
225 if (redraw_mask & REDRAW_DOOR_2)
227 if ((redraw_mask & REDRAW_DOOR_2) == REDRAW_DOOR_2)
228 BlitBitmap(backbuffer, window, VX,VY, VXSIZE,VYSIZE, VX,VY);
231 if (redraw_mask & REDRAW_VIDEO_1)
232 BlitBitmap(backbuffer, window,
233 VX+VIDEO_DISPLAY1_XPOS,VY+VIDEO_DISPLAY1_YPOS,
234 VIDEO_DISPLAY_XSIZE,VIDEO_DISPLAY_YSIZE,
235 VX+VIDEO_DISPLAY1_XPOS,VY+VIDEO_DISPLAY1_YPOS);
236 if (redraw_mask & REDRAW_VIDEO_2)
237 BlitBitmap(backbuffer, window,
238 VX+VIDEO_DISPLAY2_XPOS,VY+VIDEO_DISPLAY2_YPOS,
239 VIDEO_DISPLAY_XSIZE,VIDEO_DISPLAY_YSIZE,
240 VX+VIDEO_DISPLAY2_XPOS,VY+VIDEO_DISPLAY2_YPOS);
241 if (redraw_mask & REDRAW_VIDEO_3)
242 BlitBitmap(backbuffer, window,
243 VX+VIDEO_CONTROL_XPOS,VY+VIDEO_CONTROL_YPOS,
244 VIDEO_CONTROL_XSIZE,VIDEO_CONTROL_YSIZE,
245 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);
252 redraw_mask &= ~REDRAW_DOORS;
255 if (redraw_mask & REDRAW_MICROLEVEL)
257 BlitBitmap(backbuffer, window, SX, SY + 10 * TILEY, SXSIZE, 7 * TILEY,
258 SX, SY + 10 * TILEY);
260 redraw_mask &= ~REDRAW_MICROLEVEL;
263 if (redraw_mask & REDRAW_TILES)
265 for(x=0; x<SCR_FIELDX; x++)
266 for(y=0; y<SCR_FIELDY; y++)
267 if (redraw[redraw_x1 + x][redraw_y1 + y])
268 BlitBitmap(buffer, window,
269 FX + x * TILEX, FX + y * TILEY, TILEX, TILEY,
270 SX + x * TILEX, SY + y * TILEY);
273 if (redraw_mask & REDRAW_FPS) /* display frames per second */
278 sprintf(info1, " (only every %d. frame)", global.fps_slowdown_factor);
279 if (!global.fps_slowdown)
282 sprintf(text, "%.1f fps%s", global.frames_per_second, info1);
283 DrawTextExt(window, SX, SY, text, FONT_TEXT_2, BLIT_OPAQUE);
288 for(x=0; x<MAX_BUF_XSIZE; x++)
289 for(y=0; y<MAX_BUF_YSIZE; y++)
292 redraw_mask = REDRAW_NONE;
298 long fading_delay = 300;
300 if (setup.fading && (redraw_mask & REDRAW_FIELD))
307 ClearRectangle(window, REAL_SX,REAL_SY,FULL_SXSIZE,FULL_SYSIZE);
310 for(i=0;i<2*FULL_SYSIZE;i++)
312 for(y=0;y<FULL_SYSIZE;y++)
314 BlitBitmap(backbuffer, window,
315 REAL_SX,REAL_SY+i, FULL_SXSIZE,1, REAL_SX,REAL_SY+i);
323 for(i=1;i<FULL_SYSIZE;i+=2)
324 BlitBitmap(backbuffer, window,
325 REAL_SX,REAL_SY+i, FULL_SXSIZE,1, REAL_SX,REAL_SY+i);
331 SetClipOrigin(clip_gc[PIX_FADEMASK], 0, 0);
332 BlitBitmapMasked(backbuffer, window,
333 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE,
338 SetClipOrigin(clip_gc[PIX_FADEMASK], -1, -1);
339 BlitBitmapMasked(backbuffer, window,
340 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE,
345 SetClipOrigin(clip_gc[PIX_FADEMASK], 0, -1);
346 BlitBitmapMasked(backbuffer, window,
347 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE,
352 SetClipOrigin(clip_gc[PIX_FADEMASK], -1, 0);
353 BlitBitmapMasked(backbuffer, window,
354 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE,
359 redraw_mask &= ~REDRAW_MAIN;
366 void SetMainBackgroundImage(int graphic)
368 SetMainBackgroundBitmap(graphic == IMG_UNDEFINED ? NULL :
369 graphic_info[graphic].bitmap ?
370 graphic_info[graphic].bitmap :
371 graphic_info[IMG_BACKGROUND].bitmap);
374 void SetDoorBackgroundImage(int graphic)
376 SetDoorBackgroundBitmap(graphic == IMG_UNDEFINED ? NULL :
377 graphic_info[graphic].bitmap ?
378 graphic_info[graphic].bitmap :
379 graphic_info[IMG_BACKGROUND].bitmap);
382 void DrawBackground(int dest_x, int dest_y, int width, int height)
384 ClearRectangleOnBackground(backbuffer, dest_x, dest_y, width, height);
386 redraw_mask |= REDRAW_FIELD;
391 DrawBackground(REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE);
393 if (setup.soft_scrolling && game_status == GAME_MODE_PLAYING)
395 ClearRectangle(fieldbuffer, 0, 0, FXSIZE, FYSIZE);
396 SetDrawtoField(DRAW_BUFFERED);
399 SetDrawtoField(DRAW_BACKBUFFER);
401 if (setup.direct_draw && game_status == GAME_MODE_PLAYING)
403 ClearRectangle(window, REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE);
404 SetDrawtoField(DRAW_DIRECT);
408 void MarkTileDirty(int x, int y)
410 int xx = redraw_x1 + x;
411 int yy = redraw_y1 + y;
416 redraw[xx][yy] = TRUE;
417 redraw_mask |= REDRAW_TILES;
420 void SetBorderElement()
424 BorderElement = EL_EMPTY;
426 for(y=0; y<lev_fieldy && BorderElement == EL_EMPTY; y++)
428 for(x=0; x<lev_fieldx; x++)
430 if (!IS_INDESTRUCTIBLE(Feld[x][y]))
431 BorderElement = EL_STEELWALL;
433 if (y != 0 && y != lev_fieldy - 1 && x != lev_fieldx - 1)
439 void SetRandomAnimationValue(int x, int y)
441 gfx.anim_random_frame = GfxRandom[x][y];
444 inline int getGraphicAnimationFrame(int graphic, int sync_frame)
446 /* animation synchronized with global frame counter, not move position */
447 if (graphic_info[graphic].anim_global_sync || sync_frame < 0)
448 sync_frame = FrameCounter;
450 return getAnimationFrame(graphic_info[graphic].anim_frames,
451 graphic_info[graphic].anim_delay,
452 graphic_info[graphic].anim_mode,
453 graphic_info[graphic].anim_start_frame,
457 inline void DrawGraphicAnimationExt(DrawBuffer *dst_bitmap, int x, int y,
458 int graphic, int sync_frame, int mask_mode)
460 int frame = getGraphicAnimationFrame(graphic, sync_frame);
462 if (mask_mode == USE_MASKING)
463 DrawGraphicThruMaskExt(dst_bitmap, x, y, graphic, frame);
465 DrawGraphicExt(dst_bitmap, x, y, graphic, frame);
468 inline void DrawGraphicAnimation(int x, int y, int graphic)
470 int lx = LEVELX(x), ly = LEVELY(y);
472 if (!IN_SCR_FIELD(x, y))
475 DrawGraphicAnimationExt(drawto_field, FX + x * TILEX, FY + y * TILEY,
476 graphic, GfxFrame[lx][ly], NO_MASKING);
480 void DrawLevelGraphicAnimation(int x, int y, int graphic)
482 DrawGraphicAnimation(SCREENX(x), SCREENY(y), graphic);
485 void DrawLevelElementAnimation(int x, int y, int element)
488 int graphic = el_act_dir2img(element, GfxAction[x][y], MovDir[x][y]);
490 DrawGraphicAnimation(SCREENX(x), SCREENY(y), graphic);
492 DrawGraphicAnimation(SCREENX(x), SCREENY(y), el2img(element));
496 inline void DrawLevelGraphicAnimationIfNeeded(int x, int y, int graphic)
498 int sx = SCREENX(x), sy = SCREENY(y);
500 if (!IN_LEV_FIELD(x, y) || !IN_SCR_FIELD(sx, sy))
503 if (!IS_NEW_FRAME(GfxFrame[x][y], graphic))
506 DrawGraphicAnimation(sx, sy, graphic);
509 void DrawLevelElementAnimationIfNeeded(int x, int y, int element)
511 int sx = SCREENX(x), sy = SCREENY(y);
514 if (!IN_LEV_FIELD(x, y) || !IN_SCR_FIELD(sx, sy))
517 graphic = el_act_dir2img(element, GfxAction[x][y], MovDir[x][y]);
519 if (!IS_NEW_FRAME(GfxFrame[x][y], graphic))
522 DrawGraphicAnimation(sx, sy, graphic);
525 void DrawAllPlayers()
529 for(i=0; i<MAX_PLAYERS; i++)
530 if (stored_player[i].active)
531 DrawPlayer(&stored_player[i]);
534 void DrawPlayerField(int x, int y)
536 if (!IS_PLAYER(x, y))
539 DrawPlayer(PLAYERINFO(x, y));
542 void DrawPlayer(struct PlayerInfo *player)
545 int jx = player->jx, jy = player->jy;
546 int last_jx = player->last_jx, last_jy = player->last_jy;
547 int next_jx = jx + (jx - last_jx), next_jy = jy + (jy - last_jy);
548 int sx = SCREENX(jx), sy = SCREENY(jy);
549 int sxx = 0, syy = 0;
550 int element = Feld[jx][jy], last_element = Feld[last_jx][last_jy];
553 boolean player_is_moving = (last_jx != jx || last_jy != jy ? TRUE : FALSE);
554 int move_dir = player->MovDir;
555 int action = ACTION_DEFAULT;
557 int jx = player->jx, jy = player->jy;
558 int move_dir = player->MovDir;
559 int dx = (move_dir == MV_LEFT ? -1 : move_dir == MV_RIGHT ? +1 : 0);
560 int dy = (move_dir == MV_UP ? -1 : move_dir == MV_DOWN ? +1 : 0);
561 int last_jx = (player->is_moving ? jx - dx : jx);
562 int last_jy = (player->is_moving ? jy - dy : jy);
563 int next_jx = jx + dx;
564 int next_jy = jy + dy;
565 int sx = SCREENX(jx), sy = SCREENY(jy);
566 int sxx = 0, syy = 0;
567 int element = Feld[jx][jy], last_element = Feld[last_jx][last_jy];
570 boolean player_is_moving = (player->MovPos ? TRUE : FALSE);
571 int action = ACTION_DEFAULT;
574 if (!player->active || !IN_SCR_FIELD(SCREENX(last_jx), SCREENY(last_jy)))
578 if (!IN_LEV_FIELD(jx,jy))
580 printf("DrawPlayerField(): x = %d, y = %d\n",jx,jy);
581 printf("DrawPlayerField(): sx = %d, sy = %d\n",sx,sy);
582 printf("DrawPlayerField(): This should never happen!\n");
587 if (element == EL_EXPLOSION)
590 action = (player->Pushing ? ACTION_PUSHING :
591 player->is_digging ? ACTION_DIGGING :
592 player->is_collecting ? ACTION_COLLECTING :
593 player->is_moving ? ACTION_MOVING :
594 player->snapped ? ACTION_SNAPPING : ACTION_DEFAULT);
596 InitPlayerGfxAnimation(player, action, move_dir);
598 /* ----------------------------------------------------------------------- */
599 /* draw things in the field the player is leaving, if needed */
600 /* ----------------------------------------------------------------------- */
603 if (player->is_moving)
605 if (player_is_moving)
608 if (Back[last_jx][last_jy] && IS_DRAWABLE(last_element))
610 DrawLevelElement(last_jx, last_jy, Back[last_jx][last_jy]);
612 if (last_element == EL_DYNAMITE_ACTIVE ||
613 last_element == EL_SP_DISK_RED_ACTIVE)
614 DrawDynamite(last_jx, last_jy);
616 DrawLevelFieldThruMask(last_jx, last_jy);
618 else if (last_element == EL_DYNAMITE_ACTIVE ||
619 last_element == EL_SP_DISK_RED_ACTIVE)
620 DrawDynamite(last_jx, last_jy);
622 DrawLevelField(last_jx, last_jy);
624 if (player->Pushing && IN_SCR_FIELD(SCREENX(next_jx), SCREENY(next_jy)))
628 DrawLevelElement(next_jx, next_jy, EL_EMPTY);
632 if (Feld[next_jx][next_jy] == EL_SOKOBAN_FIELD_FULL)
633 DrawLevelElement(next_jx, next_jy, EL_SOKOBAN_FIELD_EMPTY);
635 DrawLevelElement(next_jx, next_jy, EL_EMPTY);
638 DrawLevelField(next_jx, next_jy);
644 if (!IN_SCR_FIELD(sx, sy))
647 if (setup.direct_draw)
648 SetDrawtoField(DRAW_BUFFERED);
650 /* ----------------------------------------------------------------------- */
651 /* draw things behind the player, if needed */
652 /* ----------------------------------------------------------------------- */
655 DrawLevelElement(jx, jy, Back[jx][jy]);
656 else if (IS_ACTIVE_BOMB(element))
657 DrawLevelElement(jx, jy, EL_EMPTY);
660 if (player_is_moving && GfxElement[jx][jy] != EL_UNDEFINED)
663 if (CAN_BE_CRUMBLED(GfxElement[jx][jy]))
664 DrawLevelFieldCrumbledSandDigging(jx, jy, move_dir, player->StepFrame);
666 if (GfxElement[jx][jy] == EL_SAND)
667 DrawLevelFieldCrumbledSandDigging(jx, jy, move_dir, player->StepFrame);
671 int old_element = GfxElement[jx][jy];
672 int old_graphic = el_act_dir2img(old_element, action, move_dir);
673 int frame = getGraphicAnimationFrame(old_graphic, player->StepFrame);
675 DrawGraphic(sx, sy, old_graphic, frame);
680 GfxElement[jx][jy] = EL_UNDEFINED;
682 DrawLevelField(jx, jy);
686 /* ----------------------------------------------------------------------- */
687 /* draw player himself */
688 /* ----------------------------------------------------------------------- */
690 if (player->use_murphy_graphic)
692 static int last_horizontal_dir = MV_LEFT;
695 if (move_dir == MV_LEFT || move_dir == MV_RIGHT)
696 last_horizontal_dir = move_dir;
698 direction = (player->snapped ? move_dir : last_horizontal_dir);
700 graphic = el_act_dir2img(EL_SP_MURPHY, player->GfxAction, direction);
703 graphic = el_act_dir2img(player->element_nr, player->GfxAction, move_dir);
705 frame = getGraphicAnimationFrame(graphic, player->Frame);
709 if (move_dir == MV_LEFT || move_dir == MV_RIGHT)
710 sxx = player->GfxPos;
712 syy = player->GfxPos;
715 if (!setup.soft_scrolling && ScreenMovPos)
718 DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, frame, NO_CUTTING);
720 if (SHIELD_ON(player))
722 int graphic = (player->shield_deadly_time_left ? IMG_SHIELD_DEADLY_ACTIVE :
723 IMG_SHIELD_NORMAL_ACTIVE);
724 int frame = getGraphicAnimationFrame(graphic, -1);
726 DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, frame, NO_CUTTING);
729 /* ----------------------------------------------------------------------- */
730 /* draw things the player is pushing, if needed */
731 /* ----------------------------------------------------------------------- */
734 printf("::: %d, %d [%d, %d] [%d]\n",
735 player->Pushing, player_is_moving, player->GfxAction,
736 player->is_moving, player_is_moving);
740 if (player->Pushing && player->is_moving)
742 if (player->Pushing && player_is_moving)
745 int px = SCREENX(next_jx), py = SCREENY(next_jy);
747 if (Back[next_jx][next_jy])
748 DrawLevelElement(next_jx, next_jy, Back[next_jx][next_jy]);
751 if ((sxx || syy) && element == EL_SOKOBAN_OBJECT)
752 DrawGraphicShiftedThruMask(px, py, sxx, syy, IMG_SOKOBAN_OBJECT, 0,
756 (element == EL_SOKOBAN_FIELD_EMPTY ||
757 Feld[next_jx][next_jy] == EL_SOKOBAN_FIELD_FULL))
758 DrawGraphicShiftedThruMask(px, py, sxx, syy, IMG_SOKOBAN_OBJECT, 0,
764 int element = MovingOrBlocked2Element(next_jx, next_jy);
767 int element = Feld[jx][jy];
769 int element = Feld[next_jx][next_jy];
774 int graphic = el2img(element);
778 if ((sxx || syy) && IS_PUSHABLE(element))
781 graphic = el_act_dir2img(element, ACTION_PUSHING, move_dir);
782 frame = getGraphicAnimationFrame(graphic, player->Frame);
786 printf("::: pushing %d: %d ...\n", sxx, frame);
789 DrawGraphicShifted(px, py, sxx, syy, graphic, frame,
790 NO_CUTTING, NO_MASKING);
795 /* ----------------------------------------------------------------------- */
796 /* draw things in front of player (active dynamite or dynabombs) */
797 /* ----------------------------------------------------------------------- */
799 if (IS_ACTIVE_BOMB(element))
801 graphic = el2img(element);
802 frame = getGraphicAnimationFrame(graphic, GfxFrame[jx][jy]);
804 if (game.emulation == EMU_SUPAPLEX)
805 DrawGraphic(sx, sy, IMG_SP_DISK_RED, frame);
807 DrawGraphicThruMask(sx, sy, graphic, frame);
810 if (player_is_moving && last_element == EL_EXPLOSION)
813 int graphic = el_act2img(GfxElement[last_jx][last_jy], ACTION_EXPLODING);
815 int stored = Store[last_jx][last_jy];
816 int graphic = (game.emulation != EMU_SUPAPLEX ? IMG_EXPLOSION :
817 stored == EL_SP_INFOTRON ? IMG_SP_EXPLOSION_INFOTRON :
820 int delay = (game.emulation == EMU_SUPAPLEX ? 3 : 2);
821 int phase = ExplodePhase[last_jx][last_jy] - 1;
822 int frame = getGraphicAnimationFrame(graphic, phase - delay);
825 DrawGraphicThruMask(SCREENX(last_jx), SCREENY(last_jy), graphic, frame);
828 /* ----------------------------------------------------------------------- */
829 /* draw elements the player is just walking/passing through/under */
830 /* ----------------------------------------------------------------------- */
832 /* handle the field the player is leaving ... */
833 if (player_is_moving && IS_ACCESSIBLE_INSIDE(last_element))
834 DrawLevelField(last_jx, last_jy);
835 else if (player_is_moving && IS_ACCESSIBLE_UNDER(last_element))
836 DrawLevelFieldThruMask(last_jx, last_jy);
838 /* ... and the field the player is entering */
839 if (IS_ACCESSIBLE_INSIDE(element))
840 DrawLevelField(jx, jy);
841 else if (IS_ACCESSIBLE_UNDER(element))
842 DrawLevelFieldThruMask(jx, jy);
844 if (setup.direct_draw)
846 int dest_x = SX + SCREENX(MIN(jx, last_jx)) * TILEX;
847 int dest_y = SY + SCREENY(MIN(jy, last_jy)) * TILEY;
848 int x_size = TILEX * (1 + ABS(jx - last_jx));
849 int y_size = TILEY * (1 + ABS(jy - last_jy));
851 BlitBitmap(drawto_field, window,
852 dest_x, dest_y, x_size, y_size, dest_x, dest_y);
853 SetDrawtoField(DRAW_DIRECT);
856 MarkTileDirty(sx,sy);
859 void getGraphicSource(int graphic, int frame, Bitmap **bitmap, int *x, int *y)
861 struct GraphicInfo *g = &graphic_info[graphic];
865 if (g->offset_y == 0) /* frames are ordered horizontally */
867 int max_width = g->anim_frames_per_line * g->width;
869 *x = (g->src_x + frame * g->offset_x) % max_width;
870 *y = g->src_y + (g->src_x + frame * g->offset_x) / max_width * g->height;
872 else if (g->offset_x == 0) /* frames are ordered vertically */
874 int max_height = g->anim_frames_per_line * g->height;
876 *x = g->src_x + (g->src_y + frame * g->offset_y) / max_height * g->width;
877 *y = (g->src_y + frame * g->offset_y) % max_height;
879 else /* frames are ordered diagonally */
881 *x = g->src_x + frame * g->offset_x;
882 *y = g->src_y + frame * g->offset_y;
886 void DrawGraphic(int x, int y, int graphic, int frame)
889 if (!IN_SCR_FIELD(x, y))
891 printf("DrawGraphic(): x = %d, y = %d, graphic = %d\n", x, y, graphic);
892 printf("DrawGraphic(): This should never happen!\n");
897 DrawGraphicExt(drawto_field, FX + x * TILEX, FY + y * TILEY, graphic, frame);
901 void DrawGraphicExt(DrawBuffer *dst_bitmap, int x, int y, int graphic,
907 getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
908 BlitBitmap(src_bitmap, dst_bitmap, src_x, src_y, TILEX, TILEY, x, y);
911 void DrawGraphicThruMask(int x, int y, int graphic, int frame)
914 if (!IN_SCR_FIELD(x, y))
916 printf("DrawGraphicThruMask(): x = %d,y = %d, graphic = %d\n",x,y,graphic);
917 printf("DrawGraphicThruMask(): This should never happen!\n");
922 DrawGraphicThruMaskExt(drawto_field, FX + x * TILEX, FY + y *TILEY, graphic,
927 void DrawGraphicThruMaskExt(DrawBuffer *d, int dest_x, int dest_y, int graphic,
935 getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
936 drawing_gc = src_bitmap->stored_clip_gc;
938 GC drawing_gc = src_bitmap->stored_clip_gc;
939 Bitmap *src_bitmap = graphic_info[graphic].bitmap;
940 int src_x = graphic_info[graphic].src_x;
941 int src_y = graphic_info[graphic].src_y;
942 int offset_x = graphic_info[graphic].offset_x;
943 int offset_y = graphic_info[graphic].offset_y;
945 src_x += frame * offset_x;
946 src_y += frame * offset_y;
950 SetClipOrigin(src_bitmap, drawing_gc, dest_x - src_x, dest_y - src_y);
951 BlitBitmapMasked(src_bitmap, d, src_x, src_y, TILEX, TILEY, dest_x, dest_y);
954 void DrawMiniGraphic(int x, int y, int graphic)
956 DrawMiniGraphicExt(drawto, SX + x * MINI_TILEX,SY + y * MINI_TILEY, graphic);
957 MarkTileDirty(x / 2, y / 2);
960 void getMiniGraphicSource(int graphic, Bitmap **bitmap, int *x, int *y)
962 struct GraphicInfo *g = &graphic_info[graphic];
964 int mini_starty = g->bitmap->height * 2 / 3;
967 *x = mini_startx + g->src_x / 2;
968 *y = mini_starty + g->src_y / 2;
971 void DrawMiniGraphicExt(DrawBuffer *d, int x, int y, int graphic)
976 getMiniGraphicSource(graphic, &src_bitmap, &src_x, &src_y);
977 BlitBitmap(src_bitmap, d, src_x, src_y, MINI_TILEX, MINI_TILEY, x, y);
980 void DrawGraphicShifted(int x,int y, int dx,int dy, int graphic, int frame,
981 int cut_mode, int mask_mode)
986 int width = TILEX, height = TILEY;
992 DrawGraphic(x, y, graphic, frame);
996 if (dx || dy) /* shifted graphic */
998 if (x < BX1) /* object enters playfield from the left */
1005 else if (x > BX2) /* object enters playfield from the right */
1011 else if (x==BX1 && dx < 0) /* object leaves playfield to the left */
1017 else if (x==BX2 && dx > 0) /* object leaves playfield to the right */
1019 else if (dx) /* general horizontal movement */
1020 MarkTileDirty(x + SIGN(dx), y);
1022 if (y < BY1) /* object enters playfield from the top */
1024 if (cut_mode==CUT_BELOW) /* object completely above top border */
1032 else if (y > BY2) /* object enters playfield from the bottom */
1038 else if (y==BY1 && dy < 0) /* object leaves playfield to the top */
1044 else if (dy > 0 && cut_mode == CUT_ABOVE)
1046 if (y == BY2) /* object completely above bottom border */
1052 MarkTileDirty(x, y + 1);
1053 } /* object leaves playfield to the bottom */
1054 else if (dy > 0 && (y == BY2 || cut_mode == CUT_BELOW))
1056 else if (dy) /* general vertical movement */
1057 MarkTileDirty(x, y + SIGN(dy));
1061 getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
1063 src_bitmap = graphic_info[graphic].bitmap;
1064 src_x = graphic_info[graphic].src_x;
1065 src_y = graphic_info[graphic].src_y;
1066 offset_x = graphic_info[graphic].offset_x;
1067 offset_y = graphic_info[graphic].offset_y;
1069 src_x += frame * offset_x;
1070 src_y += frame * offset_y;
1073 drawing_gc = src_bitmap->stored_clip_gc;
1078 dest_x = FX + x * TILEX + dx;
1079 dest_y = FY + y * TILEY + dy;
1082 if (!IN_SCR_FIELD(x,y))
1084 printf("DrawGraphicShifted(): x = %d, y = %d, graphic = %d\n",x,y,graphic);
1085 printf("DrawGraphicShifted(): This should never happen!\n");
1090 if (mask_mode == USE_MASKING)
1092 SetClipOrigin(src_bitmap, drawing_gc, dest_x - src_x, dest_y - src_y);
1093 BlitBitmapMasked(src_bitmap, drawto_field, src_x, src_y, width, height,
1097 BlitBitmap(src_bitmap, drawto_field, src_x, src_y, width, height,
1103 void DrawGraphicShiftedThruMask(int x, int y, int dx, int dy, int graphic,
1104 int frame, int cut_mode)
1106 DrawGraphicShifted(x,y, dx,dy, graphic, frame, cut_mode, USE_MASKING);
1109 void DrawScreenElementExt(int x, int y, int dx, int dy, int element,
1110 int cut_mode, int mask_mode)
1112 int lx = LEVELX(x), ly = LEVELY(y);
1116 if (IN_LEV_FIELD(lx, ly))
1118 SetRandomAnimationValue(lx, ly);
1120 graphic = el_act_dir2img(element, GfxAction[lx][ly], MovDir[lx][ly]);
1121 frame = getGraphicAnimationFrame(graphic, GfxFrame[lx][ly]);
1123 else /* border element */
1125 graphic = el2img(element);
1126 frame = getGraphicAnimationFrame(graphic, -1);
1129 if (element == EL_EXPANDABLE_WALL)
1131 boolean left_stopped = FALSE, right_stopped = FALSE;
1133 if (!IN_LEV_FIELD(lx - 1, ly) || IS_WALL(Feld[lx - 1][ly]))
1134 left_stopped = TRUE;
1135 if (!IN_LEV_FIELD(lx + 1, ly) || IS_WALL(Feld[lx + 1][ly]))
1136 right_stopped = TRUE;
1138 if (left_stopped && right_stopped)
1140 else if (left_stopped)
1142 graphic = IMG_EXPANDABLE_WALL_GROWING_RIGHT;
1143 frame = graphic_info[graphic].anim_frames - 1;
1145 else if (right_stopped)
1147 graphic = IMG_EXPANDABLE_WALL_GROWING_LEFT;
1148 frame = graphic_info[graphic].anim_frames - 1;
1153 DrawGraphicShifted(x, y, dx, dy, graphic, frame, cut_mode, mask_mode);
1154 else if (mask_mode == USE_MASKING)
1155 DrawGraphicThruMask(x, y, graphic, frame);
1157 DrawGraphic(x, y, graphic, frame);
1160 void DrawLevelElementExt(int x, int y, int dx, int dy, int element,
1161 int cut_mode, int mask_mode)
1163 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1164 DrawScreenElementExt(SCREENX(x), SCREENY(y), dx, dy, element,
1165 cut_mode, mask_mode);
1168 void DrawScreenElementShifted(int x, int y, int dx, int dy, int element,
1171 DrawScreenElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
1174 void DrawLevelElementShifted(int x, int y, int dx, int dy, int element,
1177 DrawLevelElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
1180 void DrawLevelElementThruMask(int x, int y, int element)
1182 DrawLevelElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
1185 void DrawLevelFieldThruMask(int x, int y)
1187 DrawLevelElementExt(x, y, 0, 0, Feld[x][y], NO_CUTTING, USE_MASKING);
1190 static void DrawLevelFieldCrumbledSandExt(int x, int y, int graphic, int frame)
1194 int sx = SCREENX(x), sy = SCREENY(y);
1196 int width, height, cx, cy, i;
1197 int snip = TILEX / 8; /* number of border pixels from "crumbled graphic" */
1198 static int xy[4][2] =
1206 if (!IN_LEV_FIELD(x, y))
1209 element = (GfxElement[x][y] != EL_UNDEFINED && Feld[x][y] != EL_EXPLOSION ?
1210 GfxElement[x][y] : Feld[x][y]);
1212 /* crumble field itself */
1213 if (CAN_BE_CRUMBLED(element) && !IS_MOVING(x, y))
1215 if (!IN_SCR_FIELD(sx, sy))
1218 getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
1222 int xx = x + xy[i][0];
1223 int yy = y + xy[i][1];
1225 element = (IN_LEV_FIELD(xx, yy) ? Feld[xx][yy] : BorderElement);
1227 /* check if neighbour field is of same type */
1228 if (CAN_BE_CRUMBLED(element) && !IS_MOVING(xx, yy))
1232 if (Feld[x][y] == EL_CUSTOM_START + 123)
1233 printf("::: crumble [%d] THE CHAOS ENGINE (%d, %d): %d, %d\n",
1234 i, Feld[x][y], element,
1235 CAN_BE_CRUMBLED(element), IS_MOVING(x, y));
1238 if (i == 1 || i == 2)
1242 cx = (i == 2 ? TILEX - snip : 0);
1250 cy = (i == 3 ? TILEY - snip : 0);
1253 BlitBitmap(src_bitmap, drawto_field, src_x + cx, src_y + cy,
1254 width, height, FX + sx * TILEX + cx, FY + sy * TILEY + cy);
1257 MarkTileDirty(sx, sy);
1259 else /* crumble neighbour fields */
1261 getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
1265 int xx = x + xy[i][0];
1266 int yy = y + xy[i][1];
1267 int sxx = sx + xy[i][0];
1268 int syy = sy + xy[i][1];
1270 if (!IN_LEV_FIELD(xx, yy) ||
1271 !IN_SCR_FIELD(sxx, syy) ||
1272 !CAN_BE_CRUMBLED(Feld[xx][yy]) ||
1276 if (i == 1 || i == 2)
1280 cx = (i == 1 ? TILEX - snip : 0);
1288 cy = (i==0 ? TILEY-snip : 0);
1291 BlitBitmap(src_bitmap, drawto_field, src_x + cx, src_y + cy,
1292 width, height, FX + sxx * TILEX + cx, FY + syy * TILEY + cy);
1294 MarkTileDirty(sxx, syy);
1299 void DrawLevelFieldCrumbledSand(int x, int y)
1301 DrawLevelFieldCrumbledSandExt(x, y, IMG_SAND_CRUMBLED, 0);
1304 void DrawLevelFieldCrumbledSandDigging(int x, int y, int direction,
1308 int graphic1 = el_act_dir2img(GfxElement[x][y], ACTION_DIGGING, direction);
1309 int graphic2 = el_act_dir2crm(GfxElement[x][y], ACTION_DIGGING, direction);
1311 int graphic1 = el_act_dir2img(EL_SAND, ACTION_DIGGING, direction);
1312 int graphic2 = el_act_dir2img(EL_SAND_CRUMBLED, ACTION_DIGGING, direction);
1314 int frame1 = getGraphicAnimationFrame(graphic1, step_frame);
1315 int frame2 = getGraphicAnimationFrame(graphic2, step_frame);
1316 int sx = SCREENX(x), sy = SCREENY(y);
1318 DrawGraphic(sx, sy, graphic1, frame1);
1319 DrawLevelFieldCrumbledSandExt(x, y, graphic2, frame2);
1322 void DrawLevelFieldCrumbledSandNeighbours(int x, int y)
1324 int sx = SCREENX(x), sy = SCREENY(y);
1325 static int xy[4][2] =
1336 int xx = x + xy[i][0];
1337 int yy = y + xy[i][1];
1338 int sxx = sx + xy[i][0];
1339 int syy = sy + xy[i][1];
1341 if (!IN_LEV_FIELD(xx, yy) ||
1342 !IN_SCR_FIELD(sxx, syy) ||
1343 !CAN_BE_CRUMBLED(Feld[xx][yy]) ||
1347 DrawLevelField(xx, yy);
1351 static int getBorderElement(int x, int y)
1355 { EL_STEELWALL_TOPLEFT, EL_INVISIBLE_STEELWALL_TOPLEFT },
1356 { EL_STEELWALL_TOPRIGHT, EL_INVISIBLE_STEELWALL_TOPRIGHT },
1357 { EL_STEELWALL_BOTTOMLEFT, EL_INVISIBLE_STEELWALL_BOTTOMLEFT },
1358 { EL_STEELWALL_BOTTOMRIGHT, EL_INVISIBLE_STEELWALL_BOTTOMRIGHT },
1359 { EL_STEELWALL_VERTICAL, EL_INVISIBLE_STEELWALL_VERTICAL },
1360 { EL_STEELWALL_HORIZONTAL, EL_INVISIBLE_STEELWALL_HORIZONTAL },
1361 { EL_STEELWALL, EL_INVISIBLE_STEELWALL }
1363 int steel_type = (BorderElement == EL_STEELWALL ? 0 : 1);
1364 int steel_position = (x == -1 && y == -1 ? 0 :
1365 x == lev_fieldx && y == -1 ? 1 :
1366 x == -1 && y == lev_fieldy ? 2 :
1367 x == lev_fieldx && y == lev_fieldy ? 3 :
1368 x == -1 || x == lev_fieldx ? 4 :
1369 y == -1 || y == lev_fieldy ? 5 : 6);
1371 return border[steel_position][steel_type];
1374 void DrawScreenElement(int x, int y, int element)
1376 DrawScreenElementExt(x, y, 0, 0, element, NO_CUTTING, NO_MASKING);
1377 DrawLevelFieldCrumbledSand(LEVELX(x), LEVELY(y));
1380 void DrawLevelElement(int x, int y, int element)
1382 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1383 DrawScreenElement(SCREENX(x), SCREENY(y), element);
1386 void DrawScreenField(int x, int y)
1388 int lx = LEVELX(x), ly = LEVELY(y);
1389 int element, content;
1391 if (!IN_LEV_FIELD(lx, ly))
1393 if (lx < -1 || lx > lev_fieldx || ly < -1 || ly > lev_fieldy)
1396 element = getBorderElement(lx, ly);
1398 DrawScreenElement(x, y, element);
1402 element = Feld[lx][ly];
1403 content = Store[lx][ly];
1405 if (IS_MOVING(lx, ly))
1407 int horiz_move = (MovDir[lx][ly] == MV_LEFT || MovDir[lx][ly] == MV_RIGHT);
1408 boolean cut_mode = NO_CUTTING;
1410 if (element == EL_QUICKSAND_EMPTYING ||
1411 element == EL_MAGIC_WALL_EMPTYING ||
1412 element == EL_BD_MAGIC_WALL_EMPTYING ||
1413 element == EL_AMOEBA_DROPPING)
1414 cut_mode = CUT_ABOVE;
1415 else if (element == EL_QUICKSAND_FILLING ||
1416 element == EL_MAGIC_WALL_FILLING ||
1417 element == EL_BD_MAGIC_WALL_FILLING)
1418 cut_mode = CUT_BELOW;
1420 if (cut_mode == CUT_ABOVE)
1421 DrawScreenElementShifted(x, y, 0, 0, element, NO_CUTTING);
1423 DrawScreenElement(x, y, EL_EMPTY);
1426 DrawScreenElementShifted(x, y, MovPos[lx][ly], 0, element, NO_CUTTING);
1427 else if (cut_mode == NO_CUTTING)
1428 DrawScreenElementShifted(x, y, 0, MovPos[lx][ly], element, cut_mode);
1430 DrawScreenElementShifted(x, y, 0, MovPos[lx][ly], content, cut_mode);
1432 if (content == EL_ACID)
1433 DrawLevelElementThruMask(lx, ly + 1, EL_ACID);
1435 else if (IS_BLOCKED(lx, ly))
1440 boolean cut_mode = NO_CUTTING;
1441 int element_old, content_old;
1443 Blocked2Moving(lx, ly, &oldx, &oldy);
1446 horiz_move = (MovDir[oldx][oldy] == MV_LEFT ||
1447 MovDir[oldx][oldy] == MV_RIGHT);
1449 element_old = Feld[oldx][oldy];
1450 content_old = Store[oldx][oldy];
1452 if (element_old == EL_QUICKSAND_EMPTYING ||
1453 element_old == EL_MAGIC_WALL_EMPTYING ||
1454 element_old == EL_BD_MAGIC_WALL_EMPTYING ||
1455 element_old == EL_AMOEBA_DROPPING)
1456 cut_mode = CUT_ABOVE;
1458 DrawScreenElement(x, y, EL_EMPTY);
1461 DrawScreenElementShifted(sx, sy, MovPos[oldx][oldy], 0, element_old,
1463 else if (cut_mode == NO_CUTTING)
1464 DrawScreenElementShifted(sx, sy, 0, MovPos[oldx][oldy], element_old,
1467 DrawScreenElementShifted(sx, sy, 0, MovPos[oldx][oldy], content_old,
1470 else if (IS_DRAWABLE(element))
1471 DrawScreenElement(x, y, element);
1473 DrawScreenElement(x, y, EL_EMPTY);
1476 void DrawLevelField(int x, int y)
1478 if (IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1479 DrawScreenField(SCREENX(x), SCREENY(y));
1480 else if (IS_MOVING(x, y))
1484 Moving2Blocked(x, y, &newx, &newy);
1485 if (IN_SCR_FIELD(SCREENX(newx), SCREENY(newy)))
1486 DrawScreenField(SCREENX(newx), SCREENY(newy));
1488 else if (IS_BLOCKED(x, y))
1492 Blocked2Moving(x, y, &oldx, &oldy);
1493 if (IN_SCR_FIELD(SCREENX(oldx), SCREENY(oldy)))
1494 DrawScreenField(SCREENX(oldx), SCREENY(oldy));
1498 void DrawMiniElement(int x, int y, int element)
1502 graphic = el2edimg(element);
1503 DrawMiniGraphic(x, y, graphic);
1506 void DrawMiniElementOrWall(int sx, int sy, int scroll_x, int scroll_y)
1508 int x = sx + scroll_x, y = sy + scroll_y;
1510 if (x < -1 || x > lev_fieldx || y < -1 || y > lev_fieldy)
1511 DrawMiniElement(sx, sy, EL_EMPTY);
1512 else if (x > -1 && x < lev_fieldx && y > -1 && y < lev_fieldy)
1513 DrawMiniElement(sx, sy, Feld[x][y]);
1515 DrawMiniGraphic(sx, sy, el2edimg(getBorderElement(x, y)));
1518 void getMicroGraphicSource(int graphic, Bitmap **bitmap, int *x, int *y)
1520 Bitmap *src_bitmap = graphic_info[graphic].bitmap;
1521 int mini_startx = src_bitmap->width * 3 / 4;
1522 int mini_starty = src_bitmap->height * 2 / 3;
1523 int src_x = mini_startx + graphic_info[graphic].src_x / 8;
1524 int src_y = mini_starty + graphic_info[graphic].src_y / 8;
1526 *bitmap = src_bitmap;
1531 void DrawMicroElement(int xpos, int ypos, int element)
1535 int graphic = el2preimg(element);
1537 getMicroGraphicSource(graphic, &src_bitmap, &src_x, &src_y);
1538 BlitBitmap(src_bitmap, drawto, src_x, src_y, MICRO_TILEX, MICRO_TILEY,
1546 SetDrawBackgroundMask(REDRAW_NONE);
1549 for(x=BX1; x<=BX2; x++)
1550 for(y=BY1; y<=BY2; y++)
1551 DrawScreenField(x, y);
1553 redraw_mask |= REDRAW_FIELD;
1556 void DrawMiniLevel(int size_x, int size_y, int scroll_x, int scroll_y)
1560 for(x=0; x<size_x; x++)
1561 for(y=0; y<size_y; y++)
1562 DrawMiniElementOrWall(x, y, scroll_x, scroll_y);
1564 redraw_mask |= REDRAW_FIELD;
1567 static void DrawMicroLevelExt(int xpos, int ypos, int from_x, int from_y)
1571 DrawBackground(xpos, ypos, MICROLEV_XSIZE, MICROLEV_YSIZE);
1573 if (lev_fieldx < STD_LEV_FIELDX)
1574 xpos += (STD_LEV_FIELDX - lev_fieldx) / 2 * MICRO_TILEX;
1575 if (lev_fieldy < STD_LEV_FIELDY)
1576 ypos += (STD_LEV_FIELDY - lev_fieldy) / 2 * MICRO_TILEY;
1578 xpos += MICRO_TILEX;
1579 ypos += MICRO_TILEY;
1581 for(x=-1; x<=STD_LEV_FIELDX; x++)
1583 for(y=-1; y<=STD_LEV_FIELDY; y++)
1585 int lx = from_x + x, ly = from_y + y;
1587 if (lx >= 0 && lx < lev_fieldx && ly >= 0 && ly < lev_fieldy)
1588 DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
1589 level.field[lx][ly]);
1590 else if (lx >= -1 && lx < lev_fieldx+1 && ly >= -1 && ly < lev_fieldy+1
1591 && BorderElement != EL_EMPTY)
1592 DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
1593 getBorderElement(lx, ly));
1597 redraw_mask |= REDRAW_MICROLEVEL;
1600 #define MICROLABEL_EMPTY 0
1601 #define MICROLABEL_LEVEL_NAME 1
1602 #define MICROLABEL_CREATED_BY 2
1603 #define MICROLABEL_LEVEL_AUTHOR 3
1604 #define MICROLABEL_IMPORTED_FROM 4
1605 #define MICROLABEL_LEVEL_IMPORT_INFO 5
1607 static void DrawMicroLevelLabelExt(int mode)
1609 char label_text[MAX_OUTPUT_LINESIZE + 1];
1610 int max_len_label_text;
1611 int font_nr = FONT_TEXT_2;
1613 if (mode == MICROLABEL_CREATED_BY || mode == MICROLABEL_IMPORTED_FROM)
1614 font_nr = FONT_TEXT_3;
1616 max_len_label_text = SXSIZE / getFontWidth(font_nr);
1618 DrawBackground(SX, MICROLABEL_YPOS, SXSIZE, getFontHeight(font_nr));
1620 strncpy(label_text, (mode == MICROLABEL_LEVEL_NAME ? level.name :
1621 mode == MICROLABEL_CREATED_BY ? "created by" :
1622 mode == MICROLABEL_LEVEL_AUTHOR ? level.author :
1623 mode == MICROLABEL_IMPORTED_FROM ? "imported from" :
1624 mode == MICROLABEL_LEVEL_IMPORT_INFO ?
1625 leveldir_current->imported_from : ""),
1626 max_len_label_text);
1627 label_text[max_len_label_text] = '\0';
1629 if (strlen(label_text) > 0)
1631 int text_width = strlen(label_text) * getFontWidth(font_nr);
1632 int lxpos = SX + (SXSIZE - text_width) / 2;
1633 int lypos = MICROLABEL_YPOS;
1635 DrawText(lxpos, lypos, label_text, font_nr);
1638 redraw_mask |= REDRAW_MICROLEVEL;
1641 void DrawMicroLevel(int xpos, int ypos, boolean restart)
1643 static unsigned long scroll_delay = 0;
1644 static unsigned long label_delay = 0;
1645 static int from_x, from_y, scroll_direction;
1646 static int label_state, label_counter;
1647 int last_game_status = game_status; /* save current game status */
1649 /* force PREVIEW font on preview level */
1650 game_status = GAME_MODE_PSEUDO_PREVIEW;
1654 from_x = from_y = 0;
1655 scroll_direction = MV_RIGHT;
1659 DrawMicroLevelExt(xpos, ypos, from_x, from_y);
1660 DrawMicroLevelLabelExt(label_state);
1662 /* initialize delay counters */
1663 DelayReached(&scroll_delay, 0);
1664 DelayReached(&label_delay, 0);
1666 if (leveldir_current->name)
1668 int len = strlen(leveldir_current->name);
1669 int lxpos = SX + (SXSIZE - len * getFontWidth(FONT_TEXT_1)) / 2;
1670 int lypos = SY + 352;
1672 DrawText(lxpos, lypos, leveldir_current->name, FONT_TEXT_1);
1675 game_status = last_game_status; /* restore current game status */
1680 /* scroll micro level, if needed */
1681 if ((lev_fieldx > STD_LEV_FIELDX || lev_fieldy > STD_LEV_FIELDY) &&
1682 DelayReached(&scroll_delay, MICROLEVEL_SCROLL_DELAY))
1684 switch (scroll_direction)
1690 scroll_direction = MV_UP;
1694 if (from_x < lev_fieldx - STD_LEV_FIELDX)
1697 scroll_direction = MV_DOWN;
1704 scroll_direction = MV_RIGHT;
1708 if (from_y < lev_fieldy - STD_LEV_FIELDY)
1711 scroll_direction = MV_LEFT;
1718 DrawMicroLevelExt(xpos, ypos, from_x, from_y);
1721 /* redraw micro level label, if needed */
1722 if (strcmp(level.name, NAMELESS_LEVEL_NAME) != 0 &&
1723 strcmp(level.author, ANONYMOUS_NAME) != 0 &&
1724 strcmp(level.author, leveldir_current->name) != 0 &&
1725 DelayReached(&label_delay, MICROLEVEL_LABEL_DELAY))
1727 int max_label_counter = 23;
1729 if (leveldir_current->imported_from != NULL)
1730 max_label_counter += 14;
1732 label_counter = (label_counter + 1) % max_label_counter;
1733 label_state = (label_counter >= 0 && label_counter <= 7 ?
1734 MICROLABEL_LEVEL_NAME :
1735 label_counter >= 9 && label_counter <= 12 ?
1736 MICROLABEL_CREATED_BY :
1737 label_counter >= 14 && label_counter <= 21 ?
1738 MICROLABEL_LEVEL_AUTHOR :
1739 label_counter >= 23 && label_counter <= 26 ?
1740 MICROLABEL_IMPORTED_FROM :
1741 label_counter >= 28 && label_counter <= 35 ?
1742 MICROLABEL_LEVEL_IMPORT_INFO : MICROLABEL_EMPTY);
1743 DrawMicroLevelLabelExt(label_state);
1746 game_status = last_game_status; /* restore current game status */
1749 int REQ_in_range(int x, int y)
1751 if (y > DY+249 && y < DY+278)
1753 if (x > DX+1 && x < DX+48)
1755 else if (x > DX+51 && x < DX+98)
1761 #define MAX_REQUEST_LINES 13
1762 #define MAX_REQUEST_LINE_LEN 7
1764 boolean Request(char *text, unsigned int req_state)
1766 int mx, my, ty, result = -1;
1767 unsigned int old_door_state;
1768 int last_game_status = game_status; /* save current game status */
1770 #if defined(PLATFORM_UNIX)
1771 /* pause network game while waiting for request to answer */
1772 if (options.network &&
1773 game_status == GAME_MODE_PLAYING &&
1774 req_state & REQUEST_WAIT_FOR)
1775 SendToServer_PausePlaying();
1778 old_door_state = GetDoorState();
1780 /* simulate releasing mouse button over last gadget, if still pressed */
1782 HandleGadgets(-1, -1, 0);
1786 CloseDoor(DOOR_CLOSE_1);
1788 /* save old door content */
1789 BlitBitmap(bitmap_db_door, bitmap_db_door,
1790 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE,
1791 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1);
1793 SetDrawBackgroundMask(REDRAW_FIELD | REDRAW_DOOR_1);
1795 /* clear door drawing field */
1796 DrawBackground(DX, DY, DXSIZE, DYSIZE);
1798 /* force DOOR font on preview level */
1799 game_status = GAME_MODE_PSEUDO_DOOR;
1801 /* write text for request */
1802 for(ty=0; ty < MAX_REQUEST_LINES; ty++)
1804 char text_line[MAX_REQUEST_LINE_LEN + 1];
1810 for(tl=0,tx=0; tx < MAX_REQUEST_LINE_LEN; tl++,tx++)
1813 if (!tc || tc == ' ')
1824 strncpy(text_line, text, tl);
1827 DrawText(DX + (DXSIZE - tl * getFontWidth(FONT_TEXT_2)) / 2,
1828 DY + 8 + ty * (getFontHeight(FONT_TEXT_2) + 2),
1829 text_line, FONT_TEXT_2);
1831 text += tl + (tc == ' ' ? 1 : 0);
1834 game_status = last_game_status; /* restore current game status */
1836 if (req_state & REQ_ASK)
1838 MapGadget(tool_gadget[TOOL_CTRL_ID_YES]);
1839 MapGadget(tool_gadget[TOOL_CTRL_ID_NO]);
1841 else if (req_state & REQ_CONFIRM)
1843 MapGadget(tool_gadget[TOOL_CTRL_ID_CONFIRM]);
1845 else if (req_state & REQ_PLAYER)
1847 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_1]);
1848 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_2]);
1849 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_3]);
1850 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_4]);
1853 /* copy request gadgets to door backbuffer */
1854 BlitBitmap(drawto, bitmap_db_door,
1855 DX, DY, DXSIZE, DYSIZE,
1856 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
1858 OpenDoor(DOOR_OPEN_1);
1864 if (!(req_state & REQUEST_WAIT_FOR))
1866 SetDrawBackgroundMask(REDRAW_FIELD);
1871 if (game_status != GAME_MODE_MAIN)
1874 button_status = MB_RELEASED;
1876 request_gadget_id = -1;
1878 SetDrawBackgroundMask(REDRAW_FIELD | REDRAW_DOOR_1);
1890 case EVENT_BUTTONPRESS:
1891 case EVENT_BUTTONRELEASE:
1892 case EVENT_MOTIONNOTIFY:
1894 if (event.type == EVENT_MOTIONNOTIFY)
1896 if (!PointerInWindow(window))
1897 continue; /* window and pointer are on different screens */
1902 motion_status = TRUE;
1903 mx = ((MotionEvent *) &event)->x;
1904 my = ((MotionEvent *) &event)->y;
1908 motion_status = FALSE;
1909 mx = ((ButtonEvent *) &event)->x;
1910 my = ((ButtonEvent *) &event)->y;
1911 if (event.type == EVENT_BUTTONPRESS)
1912 button_status = ((ButtonEvent *) &event)->button;
1914 button_status = MB_RELEASED;
1917 /* this sets 'request_gadget_id' */
1918 HandleGadgets(mx, my, button_status);
1920 switch(request_gadget_id)
1922 case TOOL_CTRL_ID_YES:
1925 case TOOL_CTRL_ID_NO:
1928 case TOOL_CTRL_ID_CONFIRM:
1929 result = TRUE | FALSE;
1932 case TOOL_CTRL_ID_PLAYER_1:
1935 case TOOL_CTRL_ID_PLAYER_2:
1938 case TOOL_CTRL_ID_PLAYER_3:
1941 case TOOL_CTRL_ID_PLAYER_4:
1952 case EVENT_KEYPRESS:
1953 switch(GetEventKey((KeyEvent *)&event, TRUE))
1966 if (req_state & REQ_PLAYER)
1970 case EVENT_KEYRELEASE:
1971 ClearPlayerAction();
1975 HandleOtherEvents(&event);
1979 else if (AnyJoystickButton() == JOY_BUTTON_NEW_PRESSED)
1981 int joy = AnyJoystick();
1983 if (joy & JOY_BUTTON_1)
1985 else if (joy & JOY_BUTTON_2)
1991 /* don't eat all CPU time */
1995 if (game_status != GAME_MODE_MAIN)
2000 if (!(req_state & REQ_STAY_OPEN))
2002 CloseDoor(DOOR_CLOSE_1);
2004 if (!(req_state & REQ_STAY_CLOSED) && (old_door_state & DOOR_OPEN_1))
2006 BlitBitmap(bitmap_db_door, bitmap_db_door,
2007 DOOR_GFX_PAGEX2,DOOR_GFX_PAGEY1, DXSIZE,DYSIZE,
2008 DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY1);
2009 OpenDoor(DOOR_OPEN_1);
2015 SetDrawBackgroundMask(REDRAW_FIELD);
2017 #if defined(PLATFORM_UNIX)
2018 /* continue network game after request */
2019 if (options.network &&
2020 game_status == GAME_MODE_PLAYING &&
2021 req_state & REQUEST_WAIT_FOR)
2022 SendToServer_ContinuePlaying();
2028 unsigned int OpenDoor(unsigned int door_state)
2030 unsigned int new_door_state;
2032 if (door_state & DOOR_COPY_BACK)
2034 BlitBitmap(bitmap_db_door, bitmap_db_door,
2035 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE + VYSIZE,
2036 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
2037 door_state &= ~DOOR_COPY_BACK;
2040 new_door_state = MoveDoor(door_state);
2042 return(new_door_state);
2045 unsigned int CloseDoor(unsigned int door_state)
2047 unsigned int new_door_state;
2049 BlitBitmap(backbuffer, bitmap_db_door,
2050 DX, DY, DXSIZE, DYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
2051 BlitBitmap(backbuffer, bitmap_db_door,
2052 VX, VY, VXSIZE, VYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2);
2054 new_door_state = MoveDoor(door_state);
2056 return(new_door_state);
2059 unsigned int GetDoorState()
2061 return MoveDoor(DOOR_GET_STATE);
2064 unsigned int SetDoorState(unsigned int door_state)
2066 return MoveDoor(door_state | DOOR_SET_STATE);
2069 unsigned int MoveDoor(unsigned int door_state)
2071 static int door1 = DOOR_OPEN_1;
2072 static int door2 = DOOR_CLOSE_2;
2073 static unsigned long door_delay = 0;
2074 int x, start, stepsize = door.step_offset;
2075 unsigned long door_delay_value = door.step_delay;
2077 if (door_state == DOOR_GET_STATE)
2078 return(door1 | door2);
2080 if (door_state & DOOR_SET_STATE)
2082 if (door_state & DOOR_ACTION_1)
2083 door1 = door_state & DOOR_ACTION_1;
2084 if (door_state & DOOR_ACTION_2)
2085 door2 = door_state & DOOR_ACTION_2;
2087 return(door1 | door2);
2090 if (door1 == DOOR_OPEN_1 && door_state & DOOR_OPEN_1)
2091 door_state &= ~DOOR_OPEN_1;
2092 else if (door1 == DOOR_CLOSE_1 && door_state & DOOR_CLOSE_1)
2093 door_state &= ~DOOR_CLOSE_1;
2094 if (door2 == DOOR_OPEN_2 && door_state & DOOR_OPEN_2)
2095 door_state &= ~DOOR_OPEN_2;
2096 else if (door2 == DOOR_CLOSE_2 && door_state & DOOR_CLOSE_2)
2097 door_state &= ~DOOR_CLOSE_2;
2099 if (setup.quick_doors)
2102 door_delay_value = 0;
2104 StopSound(SND_DOOR_OPENING);
2105 StopSound(SND_DOOR_CLOSING);
2108 if (global.autoplay_leveldir)
2110 door_state |= DOOR_NO_DELAY;
2111 door_state &= ~DOOR_CLOSE_ALL;
2114 if (door_state & DOOR_ACTION)
2116 if (!(door_state & DOOR_NO_DELAY))
2118 /* opening door sound has priority over simultaneously closing door */
2119 if (door_state & (DOOR_OPEN_1 | DOOR_OPEN_2))
2120 PlaySoundStereo(SND_DOOR_OPENING, SOUND_MIDDLE);
2121 else if (door_state & (DOOR_CLOSE_1 | DOOR_CLOSE_2))
2122 PlaySoundStereo(SND_DOOR_CLOSING, SOUND_MIDDLE);
2125 start = ((door_state & DOOR_NO_DELAY) ? DXSIZE : 0);
2127 for(x=start; x<=DXSIZE; x+=stepsize)
2129 Bitmap *bitmap = graphic_info[IMG_GLOBAL_DOOR].bitmap;
2130 GC gc = bitmap->stored_clip_gc;
2132 if (!(door_state & DOOR_NO_DELAY))
2133 WaitUntilDelayReached(&door_delay, door_delay_value);
2135 if (door_state & DOOR_ACTION_1)
2137 int i = (door_state & DOOR_OPEN_1 ? DXSIZE-x : x);
2138 int j = (DXSIZE - i) / 3;
2140 BlitBitmap(bitmap_db_door, drawto,
2141 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1 + i/2,
2142 DXSIZE,DYSIZE - i/2, DX, DY);
2144 ClearRectangle(drawto, DX, DY + DYSIZE - i/2, DXSIZE,i/2);
2146 SetClipOrigin(bitmap, gc, DX - i, (DY + j) - DOOR_GFX_PAGEY1);
2147 BlitBitmapMasked(bitmap, drawto,
2148 DXSIZE, DOOR_GFX_PAGEY1, i, 77,
2149 DX + DXSIZE - i, DY + j);
2150 BlitBitmapMasked(bitmap, drawto,
2151 DXSIZE, DOOR_GFX_PAGEY1 + 140, i, 63,
2152 DX + DXSIZE - i, DY + 140 + j);
2153 SetClipOrigin(bitmap, gc, DX - DXSIZE + i, DY - (DOOR_GFX_PAGEY1 + j));
2154 BlitBitmapMasked(bitmap, drawto,
2155 DXSIZE - i, DOOR_GFX_PAGEY1 + j, i, 77 - j,
2157 BlitBitmapMasked(bitmap, drawto,
2158 DXSIZE-i, DOOR_GFX_PAGEY1 + 140, i, 63,
2161 BlitBitmapMasked(bitmap, drawto,
2162 DXSIZE - i, DOOR_GFX_PAGEY1 + 77, i, 63,
2164 BlitBitmapMasked(bitmap, drawto,
2165 DXSIZE - i, DOOR_GFX_PAGEY1 + 203, i, 77,
2167 SetClipOrigin(bitmap, gc, DX - i, (DY + j) - DOOR_GFX_PAGEY1);
2168 BlitBitmapMasked(bitmap, drawto,
2169 DXSIZE, DOOR_GFX_PAGEY1 + 77, i, 63,
2170 DX + DXSIZE - i, DY + 77 + j);
2171 BlitBitmapMasked(bitmap, drawto,
2172 DXSIZE, DOOR_GFX_PAGEY1 + 203, i, 77 - j,
2173 DX + DXSIZE - i, DY + 203 + j);
2175 redraw_mask |= REDRAW_DOOR_1;
2178 if (door_state & DOOR_ACTION_2)
2180 int i = (door_state & DOOR_OPEN_2 ? VXSIZE - x : x);
2181 int j = (VXSIZE - i) / 3;
2183 BlitBitmap(bitmap_db_door, drawto,
2184 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2 + i/2,
2185 VXSIZE, VYSIZE - i/2, VX, VY);
2187 ClearRectangle(drawto, VX, VY + VYSIZE-i/2, VXSIZE, i/2);
2189 SetClipOrigin(bitmap, gc, VX - i, (VY + j) - DOOR_GFX_PAGEY2);
2190 BlitBitmapMasked(bitmap, drawto,
2191 VXSIZE, DOOR_GFX_PAGEY2, i, VYSIZE / 2,
2192 VX + VXSIZE-i, VY+j);
2193 SetClipOrigin(bitmap, gc,
2194 VX - VXSIZE + i, VY - (DOOR_GFX_PAGEY2 + j));
2195 BlitBitmapMasked(bitmap, drawto,
2196 VXSIZE - i, DOOR_GFX_PAGEY2 + j, i, VYSIZE / 2 - j,
2199 BlitBitmapMasked(bitmap, drawto,
2200 VXSIZE - i, DOOR_GFX_PAGEY2 + VYSIZE / 2,
2201 i, VYSIZE / 2, VX, VY + VYSIZE / 2 - j);
2202 SetClipOrigin(bitmap, gc, VX - i, (VY + j) - DOOR_GFX_PAGEY2);
2203 BlitBitmapMasked(bitmap, drawto,
2204 VXSIZE, DOOR_GFX_PAGEY2 + VYSIZE / 2,
2206 VX + VXSIZE - i, VY + VYSIZE / 2 + j);
2208 redraw_mask |= REDRAW_DOOR_2;
2213 if (game_status == GAME_MODE_MAIN)
2218 if (setup.quick_doors)
2220 StopSound(SND_DOOR_OPENING);
2221 StopSound(SND_DOOR_CLOSING);
2224 if (door_state & DOOR_ACTION_1)
2225 door1 = door_state & DOOR_ACTION_1;
2226 if (door_state & DOOR_ACTION_2)
2227 door2 = door_state & DOOR_ACTION_2;
2229 return (door1 | door2);
2232 void DrawSpecialEditorDoor()
2234 /* draw bigger toolbox window */
2235 BlitBitmap(graphic_info[IMG_GLOBAL_DOOR].bitmap, drawto,
2236 DOOR_GFX_PAGEX7, 0, EXSIZE + 8, 8,
2238 BlitBitmap(graphic_info[IMG_GLOBAL_BORDER].bitmap, drawto,
2239 EX - 4, VY - 4, EXSIZE + 8, EYSIZE - VYSIZE + 4,
2242 redraw_mask |= REDRAW_ALL;
2245 void UndrawSpecialEditorDoor()
2247 /* draw normal tape recorder window */
2248 BlitBitmap(graphic_info[IMG_GLOBAL_BORDER].bitmap, drawto,
2249 EX - 4, EY - 12, EXSIZE + 8, EYSIZE - VYSIZE + 12,
2252 redraw_mask |= REDRAW_ALL;
2256 /* ---------- new tool button stuff ---------------------------------------- */
2258 /* graphic position values for tool buttons */
2259 #define TOOL_BUTTON_YES_XPOS 2
2260 #define TOOL_BUTTON_YES_YPOS 250
2261 #define TOOL_BUTTON_YES_GFX_YPOS 0
2262 #define TOOL_BUTTON_YES_XSIZE 46
2263 #define TOOL_BUTTON_YES_YSIZE 28
2264 #define TOOL_BUTTON_NO_XPOS 52
2265 #define TOOL_BUTTON_NO_YPOS TOOL_BUTTON_YES_YPOS
2266 #define TOOL_BUTTON_NO_GFX_YPOS TOOL_BUTTON_YES_GFX_YPOS
2267 #define TOOL_BUTTON_NO_XSIZE TOOL_BUTTON_YES_XSIZE
2268 #define TOOL_BUTTON_NO_YSIZE TOOL_BUTTON_YES_YSIZE
2269 #define TOOL_BUTTON_CONFIRM_XPOS TOOL_BUTTON_YES_XPOS
2270 #define TOOL_BUTTON_CONFIRM_YPOS TOOL_BUTTON_YES_YPOS
2271 #define TOOL_BUTTON_CONFIRM_GFX_YPOS 30
2272 #define TOOL_BUTTON_CONFIRM_XSIZE 96
2273 #define TOOL_BUTTON_CONFIRM_YSIZE TOOL_BUTTON_YES_YSIZE
2274 #define TOOL_BUTTON_PLAYER_XSIZE 30
2275 #define TOOL_BUTTON_PLAYER_YSIZE 30
2276 #define TOOL_BUTTON_PLAYER_GFX_XPOS 5
2277 #define TOOL_BUTTON_PLAYER_GFX_YPOS 185
2278 #define TOOL_BUTTON_PLAYER_XPOS (5 + TOOL_BUTTON_PLAYER_XSIZE / 2)
2279 #define TOOL_BUTTON_PLAYER_YPOS (215 - TOOL_BUTTON_PLAYER_YSIZE / 2)
2280 #define TOOL_BUTTON_PLAYER1_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2281 + 0 * TOOL_BUTTON_PLAYER_XSIZE)
2282 #define TOOL_BUTTON_PLAYER2_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2283 + 1 * TOOL_BUTTON_PLAYER_XSIZE)
2284 #define TOOL_BUTTON_PLAYER3_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2285 + 0 * TOOL_BUTTON_PLAYER_XSIZE)
2286 #define TOOL_BUTTON_PLAYER4_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2287 + 1 * TOOL_BUTTON_PLAYER_XSIZE)
2288 #define TOOL_BUTTON_PLAYER1_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2289 + 0 * TOOL_BUTTON_PLAYER_YSIZE)
2290 #define TOOL_BUTTON_PLAYER2_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2291 + 0 * TOOL_BUTTON_PLAYER_YSIZE)
2292 #define TOOL_BUTTON_PLAYER3_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2293 + 1 * TOOL_BUTTON_PLAYER_YSIZE)
2294 #define TOOL_BUTTON_PLAYER4_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2295 + 1 * TOOL_BUTTON_PLAYER_YSIZE)
2304 } toolbutton_info[NUM_TOOL_BUTTONS] =
2307 TOOL_BUTTON_YES_XPOS, TOOL_BUTTON_YES_GFX_YPOS,
2308 TOOL_BUTTON_YES_XPOS, TOOL_BUTTON_YES_YPOS,
2309 TOOL_BUTTON_YES_XSIZE, TOOL_BUTTON_YES_YSIZE,
2314 TOOL_BUTTON_NO_XPOS, TOOL_BUTTON_NO_GFX_YPOS,
2315 TOOL_BUTTON_NO_XPOS, TOOL_BUTTON_NO_YPOS,
2316 TOOL_BUTTON_NO_XSIZE, TOOL_BUTTON_NO_YSIZE,
2321 TOOL_BUTTON_CONFIRM_XPOS, TOOL_BUTTON_CONFIRM_GFX_YPOS,
2322 TOOL_BUTTON_CONFIRM_XPOS, TOOL_BUTTON_CONFIRM_YPOS,
2323 TOOL_BUTTON_CONFIRM_XSIZE, TOOL_BUTTON_CONFIRM_YSIZE,
2324 TOOL_CTRL_ID_CONFIRM,
2328 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2329 TOOL_BUTTON_PLAYER1_XPOS, TOOL_BUTTON_PLAYER1_YPOS,
2330 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2331 TOOL_CTRL_ID_PLAYER_1,
2335 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2336 TOOL_BUTTON_PLAYER2_XPOS, TOOL_BUTTON_PLAYER2_YPOS,
2337 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2338 TOOL_CTRL_ID_PLAYER_2,
2342 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2343 TOOL_BUTTON_PLAYER3_XPOS, TOOL_BUTTON_PLAYER3_YPOS,
2344 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2345 TOOL_CTRL_ID_PLAYER_3,
2349 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2350 TOOL_BUTTON_PLAYER4_XPOS, TOOL_BUTTON_PLAYER4_YPOS,
2351 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2352 TOOL_CTRL_ID_PLAYER_4,
2357 void CreateToolButtons()
2361 for (i=0; i<NUM_TOOL_BUTTONS; i++)
2363 Bitmap *gd_bitmap = graphic_info[IMG_GLOBAL_DOOR].bitmap;
2364 Bitmap *deco_bitmap = None;
2365 int deco_x = 0, deco_y = 0, deco_xpos = 0, deco_ypos = 0;
2366 struct GadgetInfo *gi;
2367 unsigned long event_mask;
2368 int gd_xoffset, gd_yoffset;
2369 int gd_x1, gd_x2, gd_y;
2372 event_mask = GD_EVENT_RELEASED;
2374 gd_xoffset = toolbutton_info[i].xpos;
2375 gd_yoffset = toolbutton_info[i].ypos;
2376 gd_x1 = DOOR_GFX_PAGEX4 + gd_xoffset;
2377 gd_x2 = DOOR_GFX_PAGEX3 + gd_xoffset;
2378 gd_y = DOOR_GFX_PAGEY1 + gd_yoffset;
2380 if (id >= TOOL_CTRL_ID_PLAYER_1 && id <= TOOL_CTRL_ID_PLAYER_4)
2382 int player_nr = id - TOOL_CTRL_ID_PLAYER_1;
2384 getMiniGraphicSource(PLAYER_NR_GFX(IMG_PLAYER_1, player_nr),
2385 &deco_bitmap, &deco_x, &deco_y);
2386 deco_xpos = (toolbutton_info[i].width - MINI_TILEX) / 2;
2387 deco_ypos = (toolbutton_info[i].height - MINI_TILEY) / 2;
2390 gi = CreateGadget(GDI_CUSTOM_ID, id,
2391 GDI_INFO_TEXT, toolbutton_info[i].infotext,
2392 GDI_X, DX + toolbutton_info[i].x,
2393 GDI_Y, DY + toolbutton_info[i].y,
2394 GDI_WIDTH, toolbutton_info[i].width,
2395 GDI_HEIGHT, toolbutton_info[i].height,
2396 GDI_TYPE, GD_TYPE_NORMAL_BUTTON,
2397 GDI_STATE, GD_BUTTON_UNPRESSED,
2398 GDI_DESIGN_UNPRESSED, gd_bitmap, gd_x1, gd_y,
2399 GDI_DESIGN_PRESSED, gd_bitmap, gd_x2, gd_y,
2400 GDI_DECORATION_DESIGN, deco_bitmap, deco_x, deco_y,
2401 GDI_DECORATION_POSITION, deco_xpos, deco_ypos,
2402 GDI_DECORATION_SIZE, MINI_TILEX, MINI_TILEY,
2403 GDI_DECORATION_SHIFTING, 1, 1,
2404 GDI_EVENT_MASK, event_mask,
2405 GDI_CALLBACK_ACTION, HandleToolButtons,
2409 Error(ERR_EXIT, "cannot create gadget");
2411 tool_gadget[id] = gi;
2415 void FreeToolButtons()
2419 for (i=0; i<NUM_TOOL_BUTTONS; i++)
2420 FreeGadget(tool_gadget[i]);
2423 static void UnmapToolButtons()
2427 for (i=0; i<NUM_TOOL_BUTTONS; i++)
2428 UnmapGadget(tool_gadget[i]);
2431 static void HandleToolButtons(struct GadgetInfo *gi)
2433 request_gadget_id = gi->custom_id;
2436 int get_next_element(int element)
2440 case EL_QUICKSAND_FILLING: return EL_QUICKSAND_FULL;
2441 case EL_QUICKSAND_EMPTYING: return EL_QUICKSAND_EMPTY;
2442 case EL_MAGIC_WALL_FILLING: return EL_MAGIC_WALL_FULL;
2443 case EL_MAGIC_WALL_EMPTYING: return EL_MAGIC_WALL_ACTIVE;
2444 case EL_BD_MAGIC_WALL_FILLING: return EL_BD_MAGIC_WALL_FULL;
2445 case EL_BD_MAGIC_WALL_EMPTYING: return EL_BD_MAGIC_WALL_ACTIVE;
2446 case EL_AMOEBA_DROPPING: return EL_AMOEBA_WET;
2448 default: return element;
2452 int el_act_dir2img(int element, int action, int direction)
2454 element = GFX_ELEMENT(element);
2455 direction = MV_DIR_BIT(direction);
2457 return element_info[element].direction_graphic[action][direction];
2460 static int el_act_dir2crm(int element, int action, int direction)
2462 element = GFX_ELEMENT(element);
2463 direction = MV_DIR_BIT(direction);
2465 return element_info[element].direction_crumbled[action][direction];
2468 int el_act2img(int element, int action)
2470 element = GFX_ELEMENT(element);
2472 return element_info[element].graphic[action];
2475 int el_dir2img(int element, int direction)
2477 element = GFX_ELEMENT(element);
2479 return el_act_dir2img(element, ACTION_DEFAULT, direction);
2482 int el2img(int element)
2484 element = GFX_ELEMENT(element);
2486 return element_info[element].graphic[ACTION_DEFAULT];
2489 int el2edimg(int element)
2491 element = GFX_ELEMENT(element);
2493 return element_info[element].special_graphic[GFX_SPECIAL_ARG_EDITOR];
2496 int el2preimg(int element)
2498 element = GFX_ELEMENT(element);
2500 return element_info[element].special_graphic[GFX_SPECIAL_ARG_PREVIEW];