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);
38 static int el_act2crm(int, int);
40 static struct GadgetInfo *tool_gadget[NUM_TOOL_BUTTONS];
41 static int request_gadget_id = -1;
43 void SetDrawtoField(int mode)
45 if (mode == DRAW_BUFFERED && setup.soft_scrolling)
56 drawto_field = fieldbuffer;
58 else /* DRAW_DIRECT, DRAW_BACKBUFFER */
69 drawto_field = (mode == DRAW_DIRECT ? window : backbuffer);
73 void RedrawPlayfield(boolean force_redraw, int x, int y, int width, int height)
75 if (game_status == GAME_MODE_PLAYING && !game.envelope_active)
81 width = gfx.sxsize + 2 * TILEX;
82 height = gfx.sysize + 2 * TILEY;
85 if (force_redraw || setup.direct_draw)
88 int x1 = (x - SX) / TILEX, y1 = (y - SY) / TILEY;
89 int x2 = (x - SX + width) / TILEX, y2 = (y - SY + height) / TILEY;
91 if (setup.direct_draw)
92 SetDrawtoField(DRAW_BACKBUFFER);
94 for(xx=BX1; xx<=BX2; xx++)
95 for(yy=BY1; yy<=BY2; yy++)
96 if (xx >= x1 && xx <= x2 && yy >= y1 && yy <= y2)
97 DrawScreenField(xx, yy);
100 if (setup.direct_draw)
101 SetDrawtoField(DRAW_DIRECT);
104 if (setup.soft_scrolling)
106 int fx = FX, fy = FY;
108 fx += (ScreenMovDir & (MV_LEFT|MV_RIGHT) ? ScreenGfxPos : 0);
109 fy += (ScreenMovDir & (MV_UP|MV_DOWN) ? ScreenGfxPos : 0);
111 BlitBitmap(fieldbuffer, backbuffer, fx,fy, SXSIZE,SYSIZE, SX,SY);
115 BlitBitmap(drawto, window, x, y, width, height, x, y);
121 DrawBuffer *buffer = (drawto_field == window ? backbuffer : drawto_field);
123 if (setup.direct_draw && game_status == GAME_MODE_PLAYING)
124 redraw_mask &= ~REDRAW_MAIN;
126 if (redraw_mask & REDRAW_TILES && redraw_tiles > REDRAWTILES_THRESHOLD)
127 redraw_mask |= REDRAW_FIELD;
129 if (redraw_mask & REDRAW_FIELD)
130 redraw_mask &= ~REDRAW_TILES;
132 if (redraw_mask == REDRAW_NONE)
135 if (global.fps_slowdown && game_status == GAME_MODE_PLAYING)
137 static boolean last_frame_skipped = FALSE;
138 boolean skip_even_when_not_scrolling = TRUE;
139 boolean just_scrolling = (ScreenMovDir != 0);
140 boolean verbose = FALSE;
142 if (global.fps_slowdown_factor > 1 &&
143 (FrameCounter % global.fps_slowdown_factor) &&
144 (just_scrolling || skip_even_when_not_scrolling))
146 redraw_mask &= ~REDRAW_MAIN;
148 last_frame_skipped = TRUE;
151 printf("FRAME SKIPPED\n");
155 if (last_frame_skipped)
156 redraw_mask |= REDRAW_FIELD;
158 last_frame_skipped = FALSE;
161 printf("frame not skipped\n");
165 /* synchronize X11 graphics at this point; if we would synchronize the
166 display immediately after the buffer switching (after the XFlush),
167 this could mean that we have to wait for the graphics to complete,
168 although we could go on doing calculations for the next frame */
172 if (redraw_mask & REDRAW_ALL)
174 BlitBitmap(backbuffer, window, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
178 if (redraw_mask & REDRAW_FIELD)
180 if (game_status != GAME_MODE_PLAYING ||
181 redraw_mask & REDRAW_FROM_BACKBUFFER)
183 BlitBitmap(backbuffer, window,
184 REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE, REAL_SX, REAL_SY);
188 int fx = FX, fy = FY;
190 if (setup.soft_scrolling)
192 fx += (ScreenMovDir & (MV_LEFT | MV_RIGHT) ? ScreenGfxPos : 0);
193 fy += (ScreenMovDir & (MV_UP | MV_DOWN) ? ScreenGfxPos : 0);
196 if (setup.soft_scrolling ||
197 ABS(ScreenMovPos) + ScrollStepSize == TILEX ||
198 ABS(ScreenMovPos) == ScrollStepSize ||
199 redraw_tiles > REDRAWTILES_THRESHOLD)
201 BlitBitmap(buffer, window, fx, fy, SXSIZE, SYSIZE, SX, SY);
205 printf("redrawing all (ScreenGfxPos == %d) because %s\n",
207 (setup.soft_scrolling ?
208 "setup.soft_scrolling" :
209 ABS(ScreenGfxPos) + ScrollStepSize == TILEX ?
210 "ABS(ScreenGfxPos) + ScrollStepSize == TILEX" :
211 ABS(ScreenGfxPos) == ScrollStepSize ?
212 "ABS(ScreenGfxPos) == ScrollStepSize" :
213 "redraw_tiles > REDRAWTILES_THRESHOLD"));
219 redraw_mask &= ~REDRAW_MAIN;
222 if (redraw_mask & REDRAW_DOORS)
224 if (redraw_mask & REDRAW_DOOR_1)
225 BlitBitmap(backbuffer, window, DX, DY, DXSIZE, DYSIZE, DX, DY);
226 if (redraw_mask & REDRAW_DOOR_2)
228 if ((redraw_mask & REDRAW_DOOR_2) == REDRAW_DOOR_2)
229 BlitBitmap(backbuffer, window, VX,VY, VXSIZE,VYSIZE, VX,VY);
232 if (redraw_mask & REDRAW_VIDEO_1)
233 BlitBitmap(backbuffer, window,
234 VX+VIDEO_DISPLAY1_XPOS,VY+VIDEO_DISPLAY1_YPOS,
235 VIDEO_DISPLAY_XSIZE,VIDEO_DISPLAY_YSIZE,
236 VX+VIDEO_DISPLAY1_XPOS,VY+VIDEO_DISPLAY1_YPOS);
237 if (redraw_mask & REDRAW_VIDEO_2)
238 BlitBitmap(backbuffer, window,
239 VX+VIDEO_DISPLAY2_XPOS,VY+VIDEO_DISPLAY2_YPOS,
240 VIDEO_DISPLAY_XSIZE,VIDEO_DISPLAY_YSIZE,
241 VX+VIDEO_DISPLAY2_XPOS,VY+VIDEO_DISPLAY2_YPOS);
242 if (redraw_mask & REDRAW_VIDEO_3)
243 BlitBitmap(backbuffer, window,
244 VX+VIDEO_CONTROL_XPOS,VY+VIDEO_CONTROL_YPOS,
245 VIDEO_CONTROL_XSIZE,VIDEO_CONTROL_YSIZE,
246 VX+VIDEO_CONTROL_XPOS,VY+VIDEO_CONTROL_YPOS);
250 if (redraw_mask & REDRAW_DOOR_3)
251 BlitBitmap(backbuffer, window, EX, EY, EXSIZE, EYSIZE, EX, EY);
253 redraw_mask &= ~REDRAW_DOORS;
256 if (redraw_mask & REDRAW_MICROLEVEL)
258 BlitBitmap(backbuffer, window, SX, SY + 10 * TILEY, SXSIZE, 7 * TILEY,
259 SX, SY + 10 * TILEY);
261 redraw_mask &= ~REDRAW_MICROLEVEL;
264 if (redraw_mask & REDRAW_TILES)
266 for(x=0; x<SCR_FIELDX; x++)
267 for(y=0; y<SCR_FIELDY; y++)
268 if (redraw[redraw_x1 + x][redraw_y1 + y])
269 BlitBitmap(buffer, window,
270 FX + x * TILEX, FX + y * TILEY, TILEX, TILEY,
271 SX + x * TILEX, SY + y * TILEY);
274 if (redraw_mask & REDRAW_FPS) /* display frames per second */
279 sprintf(info1, " (only every %d. frame)", global.fps_slowdown_factor);
280 if (!global.fps_slowdown)
283 sprintf(text, "%.1f fps%s", global.frames_per_second, info1);
284 DrawTextExt(window, SX, SY, text, FONT_TEXT_2, BLIT_OPAQUE);
289 for(x=0; x<MAX_BUF_XSIZE; x++)
290 for(y=0; y<MAX_BUF_YSIZE; y++)
293 redraw_mask = REDRAW_NONE;
299 long fading_delay = 300;
301 if (setup.fading && (redraw_mask & REDRAW_FIELD))
308 ClearRectangle(window, REAL_SX,REAL_SY,FULL_SXSIZE,FULL_SYSIZE);
311 for(i=0;i<2*FULL_SYSIZE;i++)
313 for(y=0;y<FULL_SYSIZE;y++)
315 BlitBitmap(backbuffer, window,
316 REAL_SX,REAL_SY+i, FULL_SXSIZE,1, REAL_SX,REAL_SY+i);
324 for(i=1;i<FULL_SYSIZE;i+=2)
325 BlitBitmap(backbuffer, window,
326 REAL_SX,REAL_SY+i, FULL_SXSIZE,1, REAL_SX,REAL_SY+i);
332 SetClipOrigin(clip_gc[PIX_FADEMASK], 0, 0);
333 BlitBitmapMasked(backbuffer, window,
334 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE,
339 SetClipOrigin(clip_gc[PIX_FADEMASK], -1, -1);
340 BlitBitmapMasked(backbuffer, window,
341 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE,
346 SetClipOrigin(clip_gc[PIX_FADEMASK], 0, -1);
347 BlitBitmapMasked(backbuffer, window,
348 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE,
353 SetClipOrigin(clip_gc[PIX_FADEMASK], -1, 0);
354 BlitBitmapMasked(backbuffer, window,
355 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE,
360 redraw_mask &= ~REDRAW_MAIN;
367 void SetMainBackgroundImage(int graphic)
369 SetMainBackgroundBitmap(graphic == IMG_UNDEFINED ? NULL :
370 graphic_info[graphic].bitmap ?
371 graphic_info[graphic].bitmap :
372 graphic_info[IMG_BACKGROUND].bitmap);
375 void SetDoorBackgroundImage(int graphic)
377 SetDoorBackgroundBitmap(graphic == IMG_UNDEFINED ? NULL :
378 graphic_info[graphic].bitmap ?
379 graphic_info[graphic].bitmap :
380 graphic_info[IMG_BACKGROUND].bitmap);
383 void DrawBackground(int dest_x, int dest_y, int width, int height)
385 ClearRectangleOnBackground(backbuffer, dest_x, dest_y, width, height);
387 redraw_mask |= REDRAW_FIELD;
392 DrawBackground(REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE);
394 if (setup.soft_scrolling && game_status == GAME_MODE_PLAYING)
396 ClearRectangle(fieldbuffer, 0, 0, FXSIZE, FYSIZE);
397 SetDrawtoField(DRAW_BUFFERED);
400 SetDrawtoField(DRAW_BACKBUFFER);
402 if (setup.direct_draw && game_status == GAME_MODE_PLAYING)
404 ClearRectangle(window, REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE);
405 SetDrawtoField(DRAW_DIRECT);
409 void MarkTileDirty(int x, int y)
411 int xx = redraw_x1 + x;
412 int yy = redraw_y1 + y;
417 redraw[xx][yy] = TRUE;
418 redraw_mask |= REDRAW_TILES;
421 void SetBorderElement()
425 BorderElement = EL_EMPTY;
427 for(y=0; y<lev_fieldy && BorderElement == EL_EMPTY; y++)
429 for(x=0; x<lev_fieldx; x++)
431 if (!IS_INDESTRUCTIBLE(Feld[x][y]))
432 BorderElement = EL_STEELWALL;
434 if (y != 0 && y != lev_fieldy - 1 && x != lev_fieldx - 1)
440 void SetRandomAnimationValue(int x, int y)
442 gfx.anim_random_frame = GfxRandom[x][y];
445 inline int getGraphicAnimationFrame(int graphic, int sync_frame)
447 /* animation synchronized with global frame counter, not move position */
448 if (graphic_info[graphic].anim_global_sync || sync_frame < 0)
449 sync_frame = FrameCounter;
451 return getAnimationFrame(graphic_info[graphic].anim_frames,
452 graphic_info[graphic].anim_delay,
453 graphic_info[graphic].anim_mode,
454 graphic_info[graphic].anim_start_frame,
458 inline void DrawGraphicAnimationExt(DrawBuffer *dst_bitmap, int x, int y,
459 int graphic, int sync_frame, int mask_mode)
461 int frame = getGraphicAnimationFrame(graphic, sync_frame);
463 if (mask_mode == USE_MASKING)
464 DrawGraphicThruMaskExt(dst_bitmap, x, y, graphic, frame);
466 DrawGraphicExt(dst_bitmap, x, y, graphic, frame);
469 inline void DrawGraphicAnimation(int x, int y, int graphic)
471 int lx = LEVELX(x), ly = LEVELY(y);
473 if (!IN_SCR_FIELD(x, y))
476 DrawGraphicAnimationExt(drawto_field, FX + x * TILEX, FY + y * TILEY,
477 graphic, GfxFrame[lx][ly], NO_MASKING);
481 void DrawLevelGraphicAnimation(int x, int y, int graphic)
483 DrawGraphicAnimation(SCREENX(x), SCREENY(y), graphic);
486 void DrawLevelElementAnimation(int x, int y, int element)
489 int graphic = el_act_dir2img(element, GfxAction[x][y], MovDir[x][y]);
491 DrawGraphicAnimation(SCREENX(x), SCREENY(y), graphic);
493 DrawGraphicAnimation(SCREENX(x), SCREENY(y), el2img(element));
497 inline void DrawLevelGraphicAnimationIfNeeded(int x, int y, int graphic)
499 int sx = SCREENX(x), sy = SCREENY(y);
501 if (!IN_LEV_FIELD(x, y) || !IN_SCR_FIELD(sx, sy))
504 if (!IS_NEW_FRAME(GfxFrame[x][y], graphic))
507 DrawGraphicAnimation(sx, sy, graphic);
509 if (GFX_CRUMBLED(Feld[x][y]))
510 DrawLevelFieldCrumbledSand(x, y);
513 void DrawLevelElementAnimationIfNeeded(int x, int y, int element)
515 int sx = SCREENX(x), sy = SCREENY(y);
518 if (!IN_LEV_FIELD(x, y) || !IN_SCR_FIELD(sx, sy))
521 graphic = el_act_dir2img(element, GfxAction[x][y], MovDir[x][y]);
523 if (!IS_NEW_FRAME(GfxFrame[x][y], graphic))
526 DrawGraphicAnimation(sx, sy, graphic);
528 if (GFX_CRUMBLED(element))
529 DrawLevelFieldCrumbledSand(x, y);
532 void DrawAllPlayers()
536 for(i=0; i<MAX_PLAYERS; i++)
537 if (stored_player[i].active)
538 DrawPlayer(&stored_player[i]);
541 void DrawPlayerField(int x, int y)
543 if (!IS_PLAYER(x, y))
546 DrawPlayer(PLAYERINFO(x, y));
549 void DrawPlayer(struct PlayerInfo *player)
552 int jx = player->jx, jy = player->jy;
553 int last_jx = player->last_jx, last_jy = player->last_jy;
554 int next_jx = jx + (jx - last_jx), next_jy = jy + (jy - last_jy);
555 int sx = SCREENX(jx), sy = SCREENY(jy);
556 int sxx = 0, syy = 0;
557 int element = Feld[jx][jy], last_element = Feld[last_jx][last_jy];
560 boolean player_is_moving = (last_jx != jx || last_jy != jy ? TRUE : FALSE);
561 int move_dir = player->MovDir;
562 int action = ACTION_DEFAULT;
564 int jx = player->jx, jy = player->jy;
565 int move_dir = player->MovDir;
566 int dx = (move_dir == MV_LEFT ? -1 : move_dir == MV_RIGHT ? +1 : 0);
567 int dy = (move_dir == MV_UP ? -1 : move_dir == MV_DOWN ? +1 : 0);
568 int last_jx = (player->is_moving ? jx - dx : jx);
569 int last_jy = (player->is_moving ? jy - dy : jy);
570 int next_jx = jx + dx;
571 int next_jy = jy + dy;
572 int sx = SCREENX(jx), sy = SCREENY(jy);
573 int sxx = 0, syy = 0;
574 int element = Feld[jx][jy], last_element = Feld[last_jx][last_jy];
577 boolean player_is_moving = (player->MovPos ? TRUE : FALSE);
578 int action = ACTION_DEFAULT;
581 if (!player->active || !IN_SCR_FIELD(SCREENX(last_jx), SCREENY(last_jy)))
585 if (!IN_LEV_FIELD(jx,jy))
587 printf("DrawPlayerField(): x = %d, y = %d\n",jx,jy);
588 printf("DrawPlayerField(): sx = %d, sy = %d\n",sx,sy);
589 printf("DrawPlayerField(): This should never happen!\n");
594 if (element == EL_EXPLOSION)
597 action = (player->Pushing ? ACTION_PUSHING :
598 player->is_digging ? ACTION_DIGGING :
599 player->is_collecting ? ACTION_COLLECTING :
600 player->is_moving ? ACTION_MOVING :
601 player->snapped ? ACTION_SNAPPING : ACTION_DEFAULT);
604 printf("::: '%s'\n", element_action_info[action].suffix);
607 InitPlayerGfxAnimation(player, action, move_dir);
609 /* ----------------------------------------------------------------------- */
610 /* draw things in the field the player is leaving, if needed */
611 /* ----------------------------------------------------------------------- */
614 if (player->is_moving)
616 if (player_is_moving)
619 if (Back[last_jx][last_jy] && IS_DRAWABLE(last_element))
621 DrawLevelElement(last_jx, last_jy, Back[last_jx][last_jy]);
623 if (last_element == EL_DYNAMITE_ACTIVE ||
624 last_element == EL_SP_DISK_RED_ACTIVE)
625 DrawDynamite(last_jx, last_jy);
627 DrawLevelFieldThruMask(last_jx, last_jy);
629 else if (last_element == EL_DYNAMITE_ACTIVE ||
630 last_element == EL_SP_DISK_RED_ACTIVE)
631 DrawDynamite(last_jx, last_jy);
633 DrawLevelField(last_jx, last_jy);
635 if (player->Pushing && IN_SCR_FIELD(SCREENX(next_jx), SCREENY(next_jy)))
639 DrawLevelElement(next_jx, next_jy, EL_EMPTY);
643 if (Feld[next_jx][next_jy] == EL_SOKOBAN_FIELD_FULL)
644 DrawLevelElement(next_jx, next_jy, EL_SOKOBAN_FIELD_EMPTY);
646 DrawLevelElement(next_jx, next_jy, EL_EMPTY);
649 DrawLevelField(next_jx, next_jy);
655 if (!IN_SCR_FIELD(sx, sy))
658 if (setup.direct_draw)
659 SetDrawtoField(DRAW_BUFFERED);
661 /* ----------------------------------------------------------------------- */
662 /* draw things behind the player, if needed */
663 /* ----------------------------------------------------------------------- */
666 DrawLevelElement(jx, jy, Back[jx][jy]);
667 else if (IS_ACTIVE_BOMB(element))
668 DrawLevelElement(jx, jy, EL_EMPTY);
671 if (player_is_moving && GfxElement[jx][jy] != EL_UNDEFINED)
674 if (GFX_CRUMBLED(GfxElement[jx][jy]))
675 DrawLevelFieldCrumbledSandDigging(jx, jy, move_dir, player->StepFrame);
677 if (GfxElement[jx][jy] == EL_SAND)
678 DrawLevelFieldCrumbledSandDigging(jx, jy, move_dir, player->StepFrame);
682 int old_element = GfxElement[jx][jy];
683 int old_graphic = el_act_dir2img(old_element, action, move_dir);
684 int frame = getGraphicAnimationFrame(old_graphic, player->StepFrame);
686 DrawGraphic(sx, sy, old_graphic, frame);
691 GfxElement[jx][jy] = EL_UNDEFINED;
693 DrawLevelField(jx, jy);
697 /* ----------------------------------------------------------------------- */
698 /* draw player himself */
699 /* ----------------------------------------------------------------------- */
701 if (player->use_murphy_graphic)
703 static int last_horizontal_dir = MV_LEFT;
706 if (move_dir == MV_LEFT || move_dir == MV_RIGHT)
707 last_horizontal_dir = move_dir;
709 direction = (player->snapped ? move_dir : last_horizontal_dir);
711 graphic = el_act_dir2img(EL_SP_MURPHY, player->GfxAction, direction);
714 graphic = el_act_dir2img(player->element_nr, player->GfxAction, move_dir);
716 frame = getGraphicAnimationFrame(graphic, player->Frame);
720 if (move_dir == MV_LEFT || move_dir == MV_RIGHT)
721 sxx = player->GfxPos;
723 syy = player->GfxPos;
726 if (!setup.soft_scrolling && ScreenMovPos)
729 DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, frame, NO_CUTTING);
731 if (SHIELD_ON(player))
733 int graphic = (player->shield_deadly_time_left ? IMG_SHIELD_DEADLY_ACTIVE :
734 IMG_SHIELD_NORMAL_ACTIVE);
735 int frame = getGraphicAnimationFrame(graphic, -1);
737 DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, frame, NO_CUTTING);
740 /* ----------------------------------------------------------------------- */
741 /* draw things the player is pushing, if needed */
742 /* ----------------------------------------------------------------------- */
745 printf("::: %d, %d [%d, %d] [%d]\n",
746 player->Pushing, player_is_moving, player->GfxAction,
747 player->is_moving, player_is_moving);
751 if (player->Pushing && player->is_moving)
753 if (player->Pushing && player_is_moving)
756 int px = SCREENX(next_jx), py = SCREENY(next_jy);
758 if (Back[next_jx][next_jy])
759 DrawLevelElement(next_jx, next_jy, Back[next_jx][next_jy]);
762 if ((sxx || syy) && element == EL_SOKOBAN_OBJECT)
763 DrawGraphicShiftedThruMask(px, py, sxx, syy, IMG_SOKOBAN_OBJECT, 0,
767 (element == EL_SOKOBAN_FIELD_EMPTY ||
768 Feld[next_jx][next_jy] == EL_SOKOBAN_FIELD_FULL))
769 DrawGraphicShiftedThruMask(px, py, sxx, syy, IMG_SOKOBAN_OBJECT, 0,
775 int element = MovingOrBlocked2Element(next_jx, next_jy);
778 int element = Feld[jx][jy];
780 int element = Feld[next_jx][next_jy];
785 int graphic = el2img(element);
789 if ((sxx || syy) && IS_PUSHABLE(element))
792 graphic = el_act_dir2img(element, ACTION_PUSHING, move_dir);
793 frame = getGraphicAnimationFrame(graphic, player->Frame);
797 printf("::: pushing %d: %d ...\n", sxx, frame);
800 DrawGraphicShifted(px, py, sxx, syy, graphic, frame,
801 NO_CUTTING, NO_MASKING);
806 /* ----------------------------------------------------------------------- */
807 /* draw things in front of player (active dynamite or dynabombs) */
808 /* ----------------------------------------------------------------------- */
810 if (IS_ACTIVE_BOMB(element))
812 graphic = el2img(element);
813 frame = getGraphicAnimationFrame(graphic, GfxFrame[jx][jy]);
815 if (game.emulation == EMU_SUPAPLEX)
816 DrawGraphic(sx, sy, IMG_SP_DISK_RED, frame);
818 DrawGraphicThruMask(sx, sy, graphic, frame);
821 if (player_is_moving && last_element == EL_EXPLOSION)
824 int graphic = el_act2img(GfxElement[last_jx][last_jy], ACTION_EXPLODING);
826 int stored = Store[last_jx][last_jy];
827 int graphic = (game.emulation != EMU_SUPAPLEX ? IMG_EXPLOSION :
828 stored == EL_SP_INFOTRON ? IMG_SP_EXPLOSION_INFOTRON :
831 int delay = (game.emulation == EMU_SUPAPLEX ? 3 : 2);
832 int phase = ExplodePhase[last_jx][last_jy] - 1;
833 int frame = getGraphicAnimationFrame(graphic, phase - delay);
836 DrawGraphicThruMask(SCREENX(last_jx), SCREENY(last_jy), graphic, frame);
839 /* ----------------------------------------------------------------------- */
840 /* draw elements the player is just walking/passing through/under */
841 /* ----------------------------------------------------------------------- */
843 /* handle the field the player is leaving ... */
844 if (player_is_moving && IS_ACCESSIBLE_INSIDE(last_element))
845 DrawLevelField(last_jx, last_jy);
846 else if (player_is_moving && IS_ACCESSIBLE_UNDER(last_element))
847 DrawLevelFieldThruMask(last_jx, last_jy);
849 /* ... and the field the player is entering */
850 if (IS_ACCESSIBLE_INSIDE(element))
851 DrawLevelField(jx, jy);
852 else if (IS_ACCESSIBLE_UNDER(element))
853 DrawLevelFieldThruMask(jx, jy);
855 if (setup.direct_draw)
857 int dest_x = SX + SCREENX(MIN(jx, last_jx)) * TILEX;
858 int dest_y = SY + SCREENY(MIN(jy, last_jy)) * TILEY;
859 int x_size = TILEX * (1 + ABS(jx - last_jx));
860 int y_size = TILEY * (1 + ABS(jy - last_jy));
862 BlitBitmap(drawto_field, window,
863 dest_x, dest_y, x_size, y_size, dest_x, dest_y);
864 SetDrawtoField(DRAW_DIRECT);
867 MarkTileDirty(sx,sy);
870 void getGraphicSource(int graphic, int frame, Bitmap **bitmap, int *x, int *y)
872 struct GraphicInfo *g = &graphic_info[graphic];
876 if (g->offset_y == 0) /* frames are ordered horizontally */
878 int max_width = g->anim_frames_per_line * g->width;
880 *x = (g->src_x + frame * g->offset_x) % max_width;
881 *y = g->src_y + (g->src_x + frame * g->offset_x) / max_width * g->height;
883 else if (g->offset_x == 0) /* frames are ordered vertically */
885 int max_height = g->anim_frames_per_line * g->height;
887 *x = g->src_x + (g->src_y + frame * g->offset_y) / max_height * g->width;
888 *y = (g->src_y + frame * g->offset_y) % max_height;
890 else /* frames are ordered diagonally */
892 *x = g->src_x + frame * g->offset_x;
893 *y = g->src_y + frame * g->offset_y;
897 void DrawGraphic(int x, int y, int graphic, int frame)
900 if (!IN_SCR_FIELD(x, y))
902 printf("DrawGraphic(): x = %d, y = %d, graphic = %d\n", x, y, graphic);
903 printf("DrawGraphic(): This should never happen!\n");
908 DrawGraphicExt(drawto_field, FX + x * TILEX, FY + y * TILEY, graphic, frame);
912 void DrawGraphicExt(DrawBuffer *dst_bitmap, int x, int y, int graphic,
918 getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
919 BlitBitmap(src_bitmap, dst_bitmap, src_x, src_y, TILEX, TILEY, x, y);
922 void DrawGraphicThruMask(int x, int y, int graphic, int frame)
925 if (!IN_SCR_FIELD(x, y))
927 printf("DrawGraphicThruMask(): x = %d,y = %d, graphic = %d\n",x,y,graphic);
928 printf("DrawGraphicThruMask(): This should never happen!\n");
933 DrawGraphicThruMaskExt(drawto_field, FX + x * TILEX, FY + y *TILEY, graphic,
938 void DrawGraphicThruMaskExt(DrawBuffer *d, int dest_x, int dest_y, int graphic,
946 getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
947 drawing_gc = src_bitmap->stored_clip_gc;
949 GC drawing_gc = src_bitmap->stored_clip_gc;
950 Bitmap *src_bitmap = graphic_info[graphic].bitmap;
951 int src_x = graphic_info[graphic].src_x;
952 int src_y = graphic_info[graphic].src_y;
953 int offset_x = graphic_info[graphic].offset_x;
954 int offset_y = graphic_info[graphic].offset_y;
956 src_x += frame * offset_x;
957 src_y += frame * offset_y;
961 SetClipOrigin(src_bitmap, drawing_gc, dest_x - src_x, dest_y - src_y);
962 BlitBitmapMasked(src_bitmap, d, src_x, src_y, TILEX, TILEY, dest_x, dest_y);
965 void DrawMiniGraphic(int x, int y, int graphic)
967 DrawMiniGraphicExt(drawto, SX + x * MINI_TILEX,SY + y * MINI_TILEY, graphic);
968 MarkTileDirty(x / 2, y / 2);
971 void getMiniGraphicSource(int graphic, Bitmap **bitmap, int *x, int *y)
973 struct GraphicInfo *g = &graphic_info[graphic];
975 int mini_starty = g->bitmap->height * 2 / 3;
978 *x = mini_startx + g->src_x / 2;
979 *y = mini_starty + g->src_y / 2;
982 void DrawMiniGraphicExt(DrawBuffer *d, int x, int y, int graphic)
987 getMiniGraphicSource(graphic, &src_bitmap, &src_x, &src_y);
988 BlitBitmap(src_bitmap, d, src_x, src_y, MINI_TILEX, MINI_TILEY, x, y);
991 void DrawGraphicShifted(int x,int y, int dx,int dy, int graphic, int frame,
992 int cut_mode, int mask_mode)
997 int width = TILEX, height = TILEY;
1003 DrawGraphic(x, y, graphic, frame);
1007 if (dx || dy) /* shifted graphic */
1009 if (x < BX1) /* object enters playfield from the left */
1016 else if (x > BX2) /* object enters playfield from the right */
1022 else if (x==BX1 && dx < 0) /* object leaves playfield to the left */
1028 else if (x==BX2 && dx > 0) /* object leaves playfield to the right */
1030 else if (dx) /* general horizontal movement */
1031 MarkTileDirty(x + SIGN(dx), y);
1033 if (y < BY1) /* object enters playfield from the top */
1035 if (cut_mode==CUT_BELOW) /* object completely above top border */
1043 else if (y > BY2) /* object enters playfield from the bottom */
1049 else if (y==BY1 && dy < 0) /* object leaves playfield to the top */
1055 else if (dy > 0 && cut_mode == CUT_ABOVE)
1057 if (y == BY2) /* object completely above bottom border */
1063 MarkTileDirty(x, y + 1);
1064 } /* object leaves playfield to the bottom */
1065 else if (dy > 0 && (y == BY2 || cut_mode == CUT_BELOW))
1067 else if (dy) /* general vertical movement */
1068 MarkTileDirty(x, y + SIGN(dy));
1072 getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
1074 src_bitmap = graphic_info[graphic].bitmap;
1075 src_x = graphic_info[graphic].src_x;
1076 src_y = graphic_info[graphic].src_y;
1077 offset_x = graphic_info[graphic].offset_x;
1078 offset_y = graphic_info[graphic].offset_y;
1080 src_x += frame * offset_x;
1081 src_y += frame * offset_y;
1084 drawing_gc = src_bitmap->stored_clip_gc;
1089 dest_x = FX + x * TILEX + dx;
1090 dest_y = FY + y * TILEY + dy;
1093 if (!IN_SCR_FIELD(x,y))
1095 printf("DrawGraphicShifted(): x = %d, y = %d, graphic = %d\n",x,y,graphic);
1096 printf("DrawGraphicShifted(): This should never happen!\n");
1101 if (mask_mode == USE_MASKING)
1103 SetClipOrigin(src_bitmap, drawing_gc, dest_x - src_x, dest_y - src_y);
1104 BlitBitmapMasked(src_bitmap, drawto_field, src_x, src_y, width, height,
1108 BlitBitmap(src_bitmap, drawto_field, src_x, src_y, width, height,
1114 void DrawGraphicShiftedThruMask(int x, int y, int dx, int dy, int graphic,
1115 int frame, int cut_mode)
1117 DrawGraphicShifted(x,y, dx,dy, graphic, frame, cut_mode, USE_MASKING);
1120 void DrawScreenElementExt(int x, int y, int dx, int dy, int element,
1121 int cut_mode, int mask_mode)
1123 int lx = LEVELX(x), ly = LEVELY(y);
1127 if (IN_LEV_FIELD(lx, ly))
1129 SetRandomAnimationValue(lx, ly);
1131 graphic = el_act_dir2img(element, GfxAction[lx][ly], MovDir[lx][ly]);
1132 frame = getGraphicAnimationFrame(graphic, GfxFrame[lx][ly]);
1134 else /* border element */
1136 graphic = el2img(element);
1137 frame = getGraphicAnimationFrame(graphic, -1);
1140 if (element == EL_EXPANDABLE_WALL)
1142 boolean left_stopped = FALSE, right_stopped = FALSE;
1144 if (!IN_LEV_FIELD(lx - 1, ly) || IS_WALL(Feld[lx - 1][ly]))
1145 left_stopped = TRUE;
1146 if (!IN_LEV_FIELD(lx + 1, ly) || IS_WALL(Feld[lx + 1][ly]))
1147 right_stopped = TRUE;
1149 if (left_stopped && right_stopped)
1151 else if (left_stopped)
1153 graphic = IMG_EXPANDABLE_WALL_GROWING_RIGHT;
1154 frame = graphic_info[graphic].anim_frames - 1;
1156 else if (right_stopped)
1158 graphic = IMG_EXPANDABLE_WALL_GROWING_LEFT;
1159 frame = graphic_info[graphic].anim_frames - 1;
1164 DrawGraphicShifted(x, y, dx, dy, graphic, frame, cut_mode, mask_mode);
1165 else if (mask_mode == USE_MASKING)
1166 DrawGraphicThruMask(x, y, graphic, frame);
1168 DrawGraphic(x, y, graphic, frame);
1171 void DrawLevelElementExt(int x, int y, int dx, int dy, int element,
1172 int cut_mode, int mask_mode)
1174 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1175 DrawScreenElementExt(SCREENX(x), SCREENY(y), dx, dy, element,
1176 cut_mode, mask_mode);
1179 void DrawScreenElementShifted(int x, int y, int dx, int dy, int element,
1182 DrawScreenElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
1185 void DrawLevelElementShifted(int x, int y, int dx, int dy, int element,
1188 DrawLevelElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
1191 void DrawLevelElementThruMask(int x, int y, int element)
1193 DrawLevelElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
1196 void DrawLevelFieldThruMask(int x, int y)
1198 DrawLevelElementExt(x, y, 0, 0, Feld[x][y], NO_CUTTING, USE_MASKING);
1201 static void DrawLevelFieldCrumbledSandExt(int x, int y, int graphic, int frame)
1205 int sx = SCREENX(x), sy = SCREENY(y);
1207 int width, height, cx, cy, i;
1209 int crumbled_border_size = graphic_info[graphic].border_size;
1211 int snip = TILEX / 8; /* number of border pixels from "crumbled graphic" */
1213 static int xy[4][2] =
1222 if (x == 0 && y == 7)
1223 printf("::: %d, %d [%d]\n", GfxElement[x][y], Feld[x][y],
1224 crumbled_border_size);
1227 if (!IN_LEV_FIELD(x, y))
1230 element = (GfxElement[x][y] != EL_UNDEFINED && Feld[x][y] != EL_EXPLOSION ?
1231 GfxElement[x][y] : Feld[x][y]);
1233 /* crumble field itself */
1234 if (GFX_CRUMBLED(element) && !IS_MOVING(x, y))
1236 if (!IN_SCR_FIELD(sx, sy))
1239 getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
1243 int xx = x + xy[i][0];
1244 int yy = y + xy[i][1];
1246 element = (IN_LEV_FIELD(xx, yy) ? Feld[xx][yy] : BorderElement);
1248 /* check if neighbour field is of same type */
1249 if (GFX_CRUMBLED(element) && !IS_MOVING(xx, yy))
1253 if (Feld[x][y] == EL_CUSTOM_START + 123)
1254 printf("::: crumble [%d] THE CHAOS ENGINE (%d, %d): %d, %d\n",
1255 i, Feld[x][y], element,
1256 GFX_CRUMBLED(element), IS_MOVING(x, y));
1259 if (i == 1 || i == 2)
1261 width = crumbled_border_size;
1263 cx = (i == 2 ? TILEX - crumbled_border_size : 0);
1269 height = crumbled_border_size;
1271 cy = (i == 3 ? TILEY - crumbled_border_size : 0);
1274 BlitBitmap(src_bitmap, drawto_field, src_x + cx, src_y + cy,
1275 width, height, FX + sx * TILEX + cx, FY + sy * TILEY + cy);
1278 MarkTileDirty(sx, sy);
1280 else /* crumble neighbour fields */
1283 getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
1288 int xx = x + xy[i][0];
1289 int yy = y + xy[i][1];
1290 int sxx = sx + xy[i][0];
1291 int syy = sy + xy[i][1];
1293 if (!IN_LEV_FIELD(xx, yy) ||
1294 !IN_SCR_FIELD(sxx, syy) ||
1295 !GFX_CRUMBLED(Feld[xx][yy]) ||
1300 graphic = el_act2crm(Feld[xx][yy], ACTION_DEFAULT);
1301 crumbled_border_size = graphic_info[graphic].border_size;
1303 getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
1306 if (i == 1 || i == 2)
1308 width = crumbled_border_size;
1310 cx = (i == 1 ? TILEX - crumbled_border_size : 0);
1316 height = crumbled_border_size;
1318 cy = (i == 0 ? TILEY - crumbled_border_size : 0);
1321 BlitBitmap(src_bitmap, drawto_field, src_x + cx, src_y + cy,
1322 width, height, FX + sxx * TILEX + cx, FY + syy * TILEY + cy);
1324 MarkTileDirty(sxx, syy);
1329 void DrawLevelFieldCrumbledSand(int x, int y)
1334 if (!IN_LEV_FIELD(x, y))
1337 graphic = el_act2crm(Feld[x][y], ACTION_DEFAULT);
1339 DrawLevelFieldCrumbledSandExt(x, y, graphic, 0);
1341 DrawLevelFieldCrumbledSandExt(x, y, IMG_SAND_CRUMBLED, 0);
1345 void DrawLevelFieldCrumbledSandDigging(int x, int y, int direction,
1349 int graphic1 = el_act_dir2img(GfxElement[x][y], ACTION_DIGGING, direction);
1350 int graphic2 = el_act_dir2crm(GfxElement[x][y], ACTION_DIGGING, direction);
1352 int graphic1 = el_act_dir2img(EL_SAND, ACTION_DIGGING, direction);
1353 int graphic2 = el_act_dir2img(EL_SAND_CRUMBLED, ACTION_DIGGING, direction);
1355 int frame1 = getGraphicAnimationFrame(graphic1, step_frame);
1356 int frame2 = getGraphicAnimationFrame(graphic2, step_frame);
1357 int sx = SCREENX(x), sy = SCREENY(y);
1359 DrawGraphic(sx, sy, graphic1, frame1);
1360 DrawLevelFieldCrumbledSandExt(x, y, graphic2, frame2);
1363 void DrawLevelFieldCrumbledSandNeighbours(int x, int y)
1365 int sx = SCREENX(x), sy = SCREENY(y);
1366 static int xy[4][2] =
1377 int xx = x + xy[i][0];
1378 int yy = y + xy[i][1];
1379 int sxx = sx + xy[i][0];
1380 int syy = sy + xy[i][1];
1382 if (!IN_LEV_FIELD(xx, yy) ||
1383 !IN_SCR_FIELD(sxx, syy) ||
1384 !GFX_CRUMBLED(Feld[xx][yy]) ||
1388 DrawLevelField(xx, yy);
1392 static int getBorderElement(int x, int y)
1396 { EL_STEELWALL_TOPLEFT, EL_INVISIBLE_STEELWALL_TOPLEFT },
1397 { EL_STEELWALL_TOPRIGHT, EL_INVISIBLE_STEELWALL_TOPRIGHT },
1398 { EL_STEELWALL_BOTTOMLEFT, EL_INVISIBLE_STEELWALL_BOTTOMLEFT },
1399 { EL_STEELWALL_BOTTOMRIGHT, EL_INVISIBLE_STEELWALL_BOTTOMRIGHT },
1400 { EL_STEELWALL_VERTICAL, EL_INVISIBLE_STEELWALL_VERTICAL },
1401 { EL_STEELWALL_HORIZONTAL, EL_INVISIBLE_STEELWALL_HORIZONTAL },
1402 { EL_STEELWALL, EL_INVISIBLE_STEELWALL }
1404 int steel_type = (BorderElement == EL_STEELWALL ? 0 : 1);
1405 int steel_position = (x == -1 && y == -1 ? 0 :
1406 x == lev_fieldx && y == -1 ? 1 :
1407 x == -1 && y == lev_fieldy ? 2 :
1408 x == lev_fieldx && y == lev_fieldy ? 3 :
1409 x == -1 || x == lev_fieldx ? 4 :
1410 y == -1 || y == lev_fieldy ? 5 : 6);
1412 return border[steel_position][steel_type];
1415 void DrawScreenElement(int x, int y, int element)
1417 DrawScreenElementExt(x, y, 0, 0, element, NO_CUTTING, NO_MASKING);
1418 DrawLevelFieldCrumbledSand(LEVELX(x), LEVELY(y));
1421 void DrawLevelElement(int x, int y, int element)
1423 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1424 DrawScreenElement(SCREENX(x), SCREENY(y), element);
1427 void DrawScreenField(int x, int y)
1429 int lx = LEVELX(x), ly = LEVELY(y);
1430 int element, content;
1432 if (!IN_LEV_FIELD(lx, ly))
1434 if (lx < -1 || lx > lev_fieldx || ly < -1 || ly > lev_fieldy)
1437 element = getBorderElement(lx, ly);
1439 DrawScreenElement(x, y, element);
1443 element = Feld[lx][ly];
1444 content = Store[lx][ly];
1446 if (IS_MOVING(lx, ly))
1448 int horiz_move = (MovDir[lx][ly] == MV_LEFT || MovDir[lx][ly] == MV_RIGHT);
1449 boolean cut_mode = NO_CUTTING;
1451 if (element == EL_QUICKSAND_EMPTYING ||
1452 element == EL_MAGIC_WALL_EMPTYING ||
1453 element == EL_BD_MAGIC_WALL_EMPTYING ||
1454 element == EL_AMOEBA_DROPPING)
1455 cut_mode = CUT_ABOVE;
1456 else if (element == EL_QUICKSAND_FILLING ||
1457 element == EL_MAGIC_WALL_FILLING ||
1458 element == EL_BD_MAGIC_WALL_FILLING)
1459 cut_mode = CUT_BELOW;
1461 if (cut_mode == CUT_ABOVE)
1462 DrawScreenElementShifted(x, y, 0, 0, element, NO_CUTTING);
1464 DrawScreenElement(x, y, EL_EMPTY);
1467 DrawScreenElementShifted(x, y, MovPos[lx][ly], 0, element, NO_CUTTING);
1468 else if (cut_mode == NO_CUTTING)
1469 DrawScreenElementShifted(x, y, 0, MovPos[lx][ly], element, cut_mode);
1471 DrawScreenElementShifted(x, y, 0, MovPos[lx][ly], content, cut_mode);
1473 if (content == EL_ACID)
1474 DrawLevelElementThruMask(lx, ly + 1, EL_ACID);
1476 else if (IS_BLOCKED(lx, ly))
1481 boolean cut_mode = NO_CUTTING;
1482 int element_old, content_old;
1484 Blocked2Moving(lx, ly, &oldx, &oldy);
1487 horiz_move = (MovDir[oldx][oldy] == MV_LEFT ||
1488 MovDir[oldx][oldy] == MV_RIGHT);
1490 element_old = Feld[oldx][oldy];
1491 content_old = Store[oldx][oldy];
1493 if (element_old == EL_QUICKSAND_EMPTYING ||
1494 element_old == EL_MAGIC_WALL_EMPTYING ||
1495 element_old == EL_BD_MAGIC_WALL_EMPTYING ||
1496 element_old == EL_AMOEBA_DROPPING)
1497 cut_mode = CUT_ABOVE;
1499 DrawScreenElement(x, y, EL_EMPTY);
1502 DrawScreenElementShifted(sx, sy, MovPos[oldx][oldy], 0, element_old,
1504 else if (cut_mode == NO_CUTTING)
1505 DrawScreenElementShifted(sx, sy, 0, MovPos[oldx][oldy], element_old,
1508 DrawScreenElementShifted(sx, sy, 0, MovPos[oldx][oldy], content_old,
1511 else if (IS_DRAWABLE(element))
1512 DrawScreenElement(x, y, element);
1514 DrawScreenElement(x, y, EL_EMPTY);
1517 void DrawLevelField(int x, int y)
1519 if (IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1520 DrawScreenField(SCREENX(x), SCREENY(y));
1521 else if (IS_MOVING(x, y))
1525 Moving2Blocked(x, y, &newx, &newy);
1526 if (IN_SCR_FIELD(SCREENX(newx), SCREENY(newy)))
1527 DrawScreenField(SCREENX(newx), SCREENY(newy));
1529 else if (IS_BLOCKED(x, y))
1533 Blocked2Moving(x, y, &oldx, &oldy);
1534 if (IN_SCR_FIELD(SCREENX(oldx), SCREENY(oldy)))
1535 DrawScreenField(SCREENX(oldx), SCREENY(oldy));
1539 void DrawMiniElement(int x, int y, int element)
1543 graphic = el2edimg(element);
1544 DrawMiniGraphic(x, y, graphic);
1547 void DrawMiniElementOrWall(int sx, int sy, int scroll_x, int scroll_y)
1549 int x = sx + scroll_x, y = sy + scroll_y;
1551 if (x < -1 || x > lev_fieldx || y < -1 || y > lev_fieldy)
1552 DrawMiniElement(sx, sy, EL_EMPTY);
1553 else if (x > -1 && x < lev_fieldx && y > -1 && y < lev_fieldy)
1554 DrawMiniElement(sx, sy, Feld[x][y]);
1556 DrawMiniGraphic(sx, sy, el2edimg(getBorderElement(x, y)));
1559 void DrawEnvelopeBackground(int envelope_nr, int startx, int starty,
1560 int x, int y, int xsize, int ysize, int font_nr)
1562 int font_width = getFontWidth(font_nr);
1563 int font_height = getFontHeight(font_nr);
1564 int graphic = IMG_GAME_ENVELOPE_1_BACKGROUND + envelope_nr;
1567 int dst_x = SX + startx + x * font_width;
1568 int dst_y = SY + starty + y * font_height;
1569 int width = graphic_info[graphic].width;
1570 int height = graphic_info[graphic].height;
1571 int inner_width = MAX(width - 2 * font_width, font_width);
1572 int inner_height = MAX(height - 2 * font_height, font_height);
1573 int inner_sx = (width >= 3 * font_width ? font_width : 0);
1574 int inner_sy = (height >= 3 * font_height ? font_height : 0);
1575 boolean draw_masked = graphic_info[graphic].draw_masked;
1577 getGraphicSource(graphic, 0, &src_bitmap, &src_x, &src_y);
1579 if (src_bitmap == NULL || width < font_width || height < font_height)
1581 ClearRectangle(drawto, dst_x, dst_y, font_width, font_height);
1585 src_x += (x == 0 ? 0 : x == xsize - 1 ? width - font_width :
1586 inner_sx + (x - 1) * font_width % inner_width);
1587 src_y += (y == 0 ? 0 : y == ysize - 1 ? height - font_height :
1588 inner_sy + (y - 1) * font_height % inner_height);
1592 SetClipOrigin(src_bitmap, src_bitmap->stored_clip_gc,
1593 dst_x - src_x, dst_y - src_y);
1594 BlitBitmapMasked(src_bitmap, drawto, src_x, src_y, font_width, font_height,
1598 BlitBitmap(src_bitmap, drawto, src_x, src_y, font_width, font_height,
1604 void AnimateEnvelope(int envelope_nr)
1608 void ShowEnvelope(int envelope_nr)
1610 int element = EL_ENVELOPE_1 + envelope_nr;
1611 int graphic = IMG_GAME_ENVELOPE_1_BACKGROUND + envelope_nr;
1612 int sound_opening = element_info[element].sound[ACTION_OPENING];
1613 int sound_closing = element_info[element].sound[ACTION_CLOSING];
1614 boolean draw_masked = graphic_info[graphic].draw_masked;
1615 int anim_mode = graphic_info[graphic].anim_mode;
1616 int mask_mode = (draw_masked ? BLIT_MASKED : BLIT_ON_BACKGROUND);
1617 int font_nr = FONT_TEXT_1 + envelope_nr;
1618 int font_width = getFontWidth(font_nr);
1619 int font_height = getFontHeight(font_nr);
1620 boolean ffwd_delay = (tape.playing && tape.fast_forward);
1621 unsigned long anim_delay = 0;
1622 int anim_delay_value = (ffwd_delay ? FfwdFrameDelay : GameFrameDelay);
1623 int wait_delay_value = (ffwd_delay ? 500 : 1000);
1624 int start_pos_vertically = 0;
1627 game.envelope_active = TRUE;
1629 if (anim_mode != ANIM_NONE)
1630 PlaySoundStereo(sound_opening, SOUND_MIDDLE);
1632 if (anim_mode == ANIM_DEFAULT)
1634 /* open envelope window horizontally */
1635 for (i = 0; i <= level.envelope_xsize[envelope_nr]; i++)
1639 int startx = (SXSIZE - xsize * font_width) / 2;
1640 int starty = (SYSIZE - ysize * font_height) / 2;
1642 SetDrawtoField(DRAW_BUFFERED);
1644 BlitBitmap(fieldbuffer, backbuffer, FX, FY, SXSIZE, SYSIZE, SX, SY);
1646 SetDrawtoField(DRAW_BACKBUFFER);
1648 for (y=0; y < ysize; y++) for (x=0; x < xsize; x++)
1649 DrawEnvelopeBackground(envelope_nr, startx, starty, x, y, xsize, ysize,
1652 redraw_mask |= REDRAW_FIELD | REDRAW_FROM_BACKBUFFER;
1655 WaitUntilDelayReached(&anim_delay, anim_delay_value / 2);
1659 if (anim_mode == ANIM_NONE)
1660 start_pos_vertically = level.envelope_ysize[envelope_nr];
1662 /* open envelope window vertically */
1663 for (i = start_pos_vertically; i <= level.envelope_ysize[envelope_nr]; i++)
1665 int xsize = level.envelope_xsize[envelope_nr] + 2;
1667 int startx = (SXSIZE - xsize * font_width) / 2;
1668 int starty = (SYSIZE - ysize * font_height) / 2;
1670 SetDrawtoField(DRAW_BUFFERED);
1672 BlitBitmap(fieldbuffer, backbuffer, FX, FY, SXSIZE, SYSIZE, SX, SY);
1674 SetDrawtoField(DRAW_BACKBUFFER);
1676 for (y=0; y < ysize; y++) for (x=0; x < xsize; x++)
1677 DrawEnvelopeBackground(envelope_nr, startx, starty, x, y, xsize, ysize,
1680 DrawTextToTextArea(SX + startx + font_width, SY + starty + font_height,
1681 level.envelope_text[envelope_nr], font_nr,
1682 level.envelope_xsize[envelope_nr], i, mask_mode);
1684 redraw_mask |= REDRAW_FIELD | REDRAW_FROM_BACKBUFFER;
1687 WaitUntilDelayReached(&anim_delay, anim_delay_value);
1691 Delay(wait_delay_value);
1693 WaitForEventToContinue();
1695 if (anim_mode != ANIM_NONE)
1696 PlaySoundStereo(sound_closing, SOUND_MIDDLE);
1698 if (anim_mode != ANIM_NONE)
1700 /* close envelope window vertically */
1701 for (i = level.envelope_ysize[envelope_nr]; i >= 0; i--)
1703 int xsize = level.envelope_xsize[envelope_nr] + 2;
1705 int startx = (SXSIZE - xsize * font_width) / 2;
1706 int starty = (SYSIZE - ysize * font_height) / 2;
1708 SetDrawtoField(DRAW_BUFFERED);
1710 BlitBitmap(fieldbuffer, backbuffer, FX, FY, SXSIZE, SYSIZE, SX, SY);
1712 SetDrawtoField(DRAW_BACKBUFFER);
1714 for (y=0; y < ysize; y++) for (x=0; x < xsize; x++)
1715 DrawEnvelopeBackground(envelope_nr, startx, starty, x, y, xsize, ysize,
1718 DrawTextToTextArea(SX + startx + font_width, SY + starty + font_height,
1719 level.envelope_text[envelope_nr], font_nr,
1720 level.envelope_xsize[envelope_nr], i, mask_mode);
1722 redraw_mask |= REDRAW_FIELD | REDRAW_FROM_BACKBUFFER;
1725 WaitUntilDelayReached(&anim_delay, anim_delay_value);
1729 if (anim_mode == ANIM_DEFAULT)
1731 /* close envelope window horizontally */
1732 for (i = level.envelope_xsize[envelope_nr]; i >= 0; i--)
1736 int startx = (SXSIZE - xsize * font_width) / 2;
1737 int starty = (SYSIZE - ysize * font_height) / 2;
1739 SetDrawtoField(DRAW_BUFFERED);
1741 BlitBitmap(fieldbuffer, backbuffer, FX, FY, SXSIZE, SYSIZE, SX, SY);
1743 SetDrawtoField(DRAW_BACKBUFFER);
1745 for (y=0; y < ysize; y++) for (x=0; x < xsize; x++)
1746 DrawEnvelopeBackground(envelope_nr, startx, starty, x, y, xsize, ysize,
1749 redraw_mask |= REDRAW_FIELD | REDRAW_FROM_BACKBUFFER;
1752 WaitUntilDelayReached(&anim_delay, anim_delay_value / 2);
1756 game.envelope_active = FALSE;
1758 SetDrawtoField(DRAW_BUFFERED);
1760 redraw_mask |= REDRAW_FIELD;
1766 void ShowEnvelope(int envelope_nr)
1768 int element = EL_ENVELOPE_1 + envelope_nr;
1769 int graphic = IMG_GAME_ENVELOPE_1_BACKGROUND + envelope_nr;
1770 int sound_opening = element_info[element].sound[ACTION_OPENING];
1771 int sound_closing = element_info[element].sound[ACTION_CLOSING];
1772 boolean draw_masked = graphic_info[graphic].draw_masked;
1773 int anim_mode = graphic_info[graphic].anim_mode;
1774 int mask_mode = (draw_masked ? BLIT_MASKED : BLIT_ON_BACKGROUND);
1775 int font_nr = FONT_TEXT_1;
1776 int font_width = getFontWidth(font_nr);
1777 int font_height = getFontHeight(font_nr);
1778 boolean ffwd_delay = (tape.playing && tape.fast_forward);
1779 unsigned long anim_delay = 0;
1780 int anim_delay_value = (ffwd_delay ? FfwdFrameDelay : GameFrameDelay);
1781 int wait_delay_value = (ffwd_delay ? 500 : 1000);
1782 int start_pos_vertically = 0;
1785 game.envelope_active = TRUE;
1787 if (anim_mode != ANIM_NONE)
1788 PlaySoundStereo(sound_opening, SOUND_MIDDLE);
1790 if (anim_mode == ANIM_DEFAULT)
1792 /* open envelope window horizontally */
1793 for (i = 0; i <= level.envelope_xsize[envelope_nr]; i++)
1797 int startx = (SXSIZE - xsize * font_width) / 2;
1798 int starty = (SYSIZE - ysize * font_height) / 2;
1800 SetDrawtoField(DRAW_BUFFERED);
1802 BlitBitmap(fieldbuffer, backbuffer, FX, FY, SXSIZE, SYSIZE, SX, SY);
1804 SetDrawtoField(DRAW_BACKBUFFER);
1806 for (y=0; y < ysize; y++) for (x=0; x < xsize; x++)
1807 DrawEnvelopeBackground(envelope_nr, startx, starty, x, y, xsize, ysize,
1810 redraw_mask |= REDRAW_FIELD | REDRAW_FROM_BACKBUFFER;
1813 WaitUntilDelayReached(&anim_delay, anim_delay_value / 2);
1817 if (anim_mode == ANIM_NONE)
1818 start_pos_vertically = level.envelope_ysize[envelope_nr];
1820 /* open envelope window vertically */
1821 for (i = start_pos_vertically; i <= level.envelope_ysize[envelope_nr]; i++)
1823 int xsize = level.envelope_xsize[envelope_nr] + 2;
1825 int startx = (SXSIZE - xsize * font_width) / 2;
1826 int starty = (SYSIZE - ysize * font_height) / 2;
1828 SetDrawtoField(DRAW_BUFFERED);
1830 BlitBitmap(fieldbuffer, backbuffer, FX, FY, SXSIZE, SYSIZE, SX, SY);
1832 SetDrawtoField(DRAW_BACKBUFFER);
1834 for (y=0; y < ysize; y++) for (x=0; x < xsize; x++)
1835 DrawEnvelopeBackground(envelope_nr, startx, starty, x, y, xsize, ysize,
1838 DrawTextToTextArea(SX + startx + font_width, SY + starty + font_height,
1839 level.envelope_text[envelope_nr], FONT_TEXT_1,
1840 level.envelope_xsize[envelope_nr], i, mask_mode);
1842 redraw_mask |= REDRAW_FIELD | REDRAW_FROM_BACKBUFFER;
1845 WaitUntilDelayReached(&anim_delay, anim_delay_value);
1849 Delay(wait_delay_value);
1851 WaitForEventToContinue();
1853 if (anim_mode != ANIM_NONE)
1854 PlaySoundStereo(sound_closing, SOUND_MIDDLE);
1856 if (anim_mode != ANIM_NONE)
1858 /* close envelope window vertically */
1859 for (i = level.envelope_ysize[envelope_nr]; i >= 0; i--)
1861 int xsize = level.envelope_xsize[envelope_nr] + 2;
1863 int startx = (SXSIZE - xsize * font_width) / 2;
1864 int starty = (SYSIZE - ysize * font_height) / 2;
1866 SetDrawtoField(DRAW_BUFFERED);
1868 BlitBitmap(fieldbuffer, backbuffer, FX, FY, SXSIZE, SYSIZE, SX, SY);
1870 SetDrawtoField(DRAW_BACKBUFFER);
1872 for (y=0; y < ysize; y++) for (x=0; x < xsize; x++)
1873 DrawEnvelopeBackground(envelope_nr, startx, starty, x, y, xsize, ysize,
1876 DrawTextToTextArea(SX + startx + font_width, SY + starty + font_height,
1877 level.envelope_text[envelope_nr], FONT_TEXT_1,
1878 level.envelope_xsize[envelope_nr], i, mask_mode);
1880 redraw_mask |= REDRAW_FIELD | REDRAW_FROM_BACKBUFFER;
1883 WaitUntilDelayReached(&anim_delay, anim_delay_value);
1887 if (anim_mode == ANIM_DEFAULT)
1889 /* close envelope window horizontally */
1890 for (i = level.envelope_xsize[envelope_nr]; i >= 0; i--)
1894 int startx = (SXSIZE - xsize * font_width) / 2;
1895 int starty = (SYSIZE - ysize * font_height) / 2;
1897 SetDrawtoField(DRAW_BUFFERED);
1899 BlitBitmap(fieldbuffer, backbuffer, FX, FY, SXSIZE, SYSIZE, SX, SY);
1901 SetDrawtoField(DRAW_BACKBUFFER);
1903 for (y=0; y < ysize; y++) for (x=0; x < xsize; x++)
1904 DrawEnvelopeBackground(envelope_nr, startx, starty, x, y, xsize, ysize,
1907 redraw_mask |= REDRAW_FIELD | REDRAW_FROM_BACKBUFFER;
1910 WaitUntilDelayReached(&anim_delay, anim_delay_value / 2);
1914 game.envelope_active = FALSE;
1916 SetDrawtoField(DRAW_BUFFERED);
1918 redraw_mask |= REDRAW_FIELD;
1924 void getMicroGraphicSource(int graphic, Bitmap **bitmap, int *x, int *y)
1926 Bitmap *src_bitmap = graphic_info[graphic].bitmap;
1927 int mini_startx = src_bitmap->width * 3 / 4;
1928 int mini_starty = src_bitmap->height * 2 / 3;
1929 int src_x = mini_startx + graphic_info[graphic].src_x / 8;
1930 int src_y = mini_starty + graphic_info[graphic].src_y / 8;
1932 *bitmap = src_bitmap;
1937 void DrawMicroElement(int xpos, int ypos, int element)
1941 int graphic = el2preimg(element);
1943 getMicroGraphicSource(graphic, &src_bitmap, &src_x, &src_y);
1944 BlitBitmap(src_bitmap, drawto, src_x, src_y, MICRO_TILEX, MICRO_TILEY,
1952 SetDrawBackgroundMask(REDRAW_NONE);
1955 for(x=BX1; x<=BX2; x++)
1956 for(y=BY1; y<=BY2; y++)
1957 DrawScreenField(x, y);
1959 redraw_mask |= REDRAW_FIELD;
1962 void DrawMiniLevel(int size_x, int size_y, int scroll_x, int scroll_y)
1966 for(x=0; x<size_x; x++)
1967 for(y=0; y<size_y; y++)
1968 DrawMiniElementOrWall(x, y, scroll_x, scroll_y);
1970 redraw_mask |= REDRAW_FIELD;
1973 static void DrawMicroLevelExt(int xpos, int ypos, int from_x, int from_y)
1977 DrawBackground(xpos, ypos, MICROLEV_XSIZE, MICROLEV_YSIZE);
1979 if (lev_fieldx < STD_LEV_FIELDX)
1980 xpos += (STD_LEV_FIELDX - lev_fieldx) / 2 * MICRO_TILEX;
1981 if (lev_fieldy < STD_LEV_FIELDY)
1982 ypos += (STD_LEV_FIELDY - lev_fieldy) / 2 * MICRO_TILEY;
1984 xpos += MICRO_TILEX;
1985 ypos += MICRO_TILEY;
1987 for(x=-1; x<=STD_LEV_FIELDX; x++)
1989 for(y=-1; y<=STD_LEV_FIELDY; y++)
1991 int lx = from_x + x, ly = from_y + y;
1993 if (lx >= 0 && lx < lev_fieldx && ly >= 0 && ly < lev_fieldy)
1994 DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
1995 level.field[lx][ly]);
1996 else if (lx >= -1 && lx < lev_fieldx+1 && ly >= -1 && ly < lev_fieldy+1
1997 && BorderElement != EL_EMPTY)
1998 DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
1999 getBorderElement(lx, ly));
2003 redraw_mask |= REDRAW_MICROLEVEL;
2006 #define MICROLABEL_EMPTY 0
2007 #define MICROLABEL_LEVEL_NAME 1
2008 #define MICROLABEL_CREATED_BY 2
2009 #define MICROLABEL_LEVEL_AUTHOR 3
2010 #define MICROLABEL_IMPORTED_FROM 4
2011 #define MICROLABEL_LEVEL_IMPORT_INFO 5
2013 static void DrawMicroLevelLabelExt(int mode)
2015 char label_text[MAX_OUTPUT_LINESIZE + 1];
2016 int max_len_label_text;
2017 int font_nr = FONT_TEXT_2;
2019 if (mode == MICROLABEL_CREATED_BY || mode == MICROLABEL_IMPORTED_FROM)
2020 font_nr = FONT_TEXT_3;
2022 max_len_label_text = SXSIZE / getFontWidth(font_nr);
2024 DrawBackground(SX, MICROLABEL_YPOS, SXSIZE, getFontHeight(font_nr));
2026 strncpy(label_text, (mode == MICROLABEL_LEVEL_NAME ? level.name :
2027 mode == MICROLABEL_CREATED_BY ? "created by" :
2028 mode == MICROLABEL_LEVEL_AUTHOR ? level.author :
2029 mode == MICROLABEL_IMPORTED_FROM ? "imported from" :
2030 mode == MICROLABEL_LEVEL_IMPORT_INFO ?
2031 leveldir_current->imported_from : ""),
2032 max_len_label_text);
2033 label_text[max_len_label_text] = '\0';
2035 if (strlen(label_text) > 0)
2037 int lxpos = SX + (SXSIZE - getTextWidth(label_text, font_nr)) / 2;
2038 int lypos = MICROLABEL_YPOS;
2040 DrawText(lxpos, lypos, label_text, font_nr);
2043 redraw_mask |= REDRAW_MICROLEVEL;
2046 void DrawMicroLevel(int xpos, int ypos, boolean restart)
2048 static unsigned long scroll_delay = 0;
2049 static unsigned long label_delay = 0;
2050 static int from_x, from_y, scroll_direction;
2051 static int label_state, label_counter;
2052 int last_game_status = game_status; /* save current game status */
2054 /* force PREVIEW font on preview level */
2055 game_status = GAME_MODE_PSEUDO_PREVIEW;
2059 from_x = from_y = 0;
2060 scroll_direction = MV_RIGHT;
2064 DrawMicroLevelExt(xpos, ypos, from_x, from_y);
2065 DrawMicroLevelLabelExt(label_state);
2067 /* initialize delay counters */
2068 DelayReached(&scroll_delay, 0);
2069 DelayReached(&label_delay, 0);
2071 if (leveldir_current->name)
2073 int text_width = getTextWidth(leveldir_current->name, FONT_TEXT_1);
2074 int lxpos = SX + (SXSIZE - text_width) / 2;
2075 int lypos = SY + 352;
2077 DrawText(lxpos, lypos, leveldir_current->name, FONT_TEXT_1);
2080 game_status = last_game_status; /* restore current game status */
2085 /* scroll micro level, if needed */
2086 if ((lev_fieldx > STD_LEV_FIELDX || lev_fieldy > STD_LEV_FIELDY) &&
2087 DelayReached(&scroll_delay, MICROLEVEL_SCROLL_DELAY))
2089 switch (scroll_direction)
2095 scroll_direction = MV_UP;
2099 if (from_x < lev_fieldx - STD_LEV_FIELDX)
2102 scroll_direction = MV_DOWN;
2109 scroll_direction = MV_RIGHT;
2113 if (from_y < lev_fieldy - STD_LEV_FIELDY)
2116 scroll_direction = MV_LEFT;
2123 DrawMicroLevelExt(xpos, ypos, from_x, from_y);
2126 /* redraw micro level label, if needed */
2127 if (strcmp(level.name, NAMELESS_LEVEL_NAME) != 0 &&
2128 strcmp(level.author, ANONYMOUS_NAME) != 0 &&
2129 strcmp(level.author, leveldir_current->name) != 0 &&
2130 DelayReached(&label_delay, MICROLEVEL_LABEL_DELAY))
2132 int max_label_counter = 23;
2134 if (leveldir_current->imported_from != NULL)
2135 max_label_counter += 14;
2137 label_counter = (label_counter + 1) % max_label_counter;
2138 label_state = (label_counter >= 0 && label_counter <= 7 ?
2139 MICROLABEL_LEVEL_NAME :
2140 label_counter >= 9 && label_counter <= 12 ?
2141 MICROLABEL_CREATED_BY :
2142 label_counter >= 14 && label_counter <= 21 ?
2143 MICROLABEL_LEVEL_AUTHOR :
2144 label_counter >= 23 && label_counter <= 26 ?
2145 MICROLABEL_IMPORTED_FROM :
2146 label_counter >= 28 && label_counter <= 35 ?
2147 MICROLABEL_LEVEL_IMPORT_INFO : MICROLABEL_EMPTY);
2148 DrawMicroLevelLabelExt(label_state);
2151 game_status = last_game_status; /* restore current game status */
2154 void WaitForEventToContinue()
2156 boolean still_wait = TRUE;
2158 /* simulate releasing mouse button over last gadget, if still pressed */
2160 HandleGadgets(-1, -1, 0);
2162 button_status = MB_RELEASED;
2174 case EVENT_BUTTONPRESS:
2175 case EVENT_KEYPRESS:
2179 case EVENT_KEYRELEASE:
2180 ClearPlayerAction();
2184 HandleOtherEvents(&event);
2188 else if (AnyJoystickButton() == JOY_BUTTON_NEW_PRESSED)
2195 /* don't eat all CPU time */
2200 #define MAX_REQUEST_LINES 13
2201 #define MAX_REQUEST_LINE_LEN 7
2203 boolean Request(char *text, unsigned int req_state)
2205 int mx, my, ty, result = -1;
2206 unsigned int old_door_state;
2207 int last_game_status = game_status; /* save current game status */
2210 SetMouseCursor(CURSOR_DEFAULT);
2213 #if defined(PLATFORM_UNIX)
2214 /* pause network game while waiting for request to answer */
2215 if (options.network &&
2216 game_status == GAME_MODE_PLAYING &&
2217 req_state & REQUEST_WAIT_FOR)
2218 SendToServer_PausePlaying();
2221 old_door_state = GetDoorState();
2223 /* simulate releasing mouse button over last gadget, if still pressed */
2225 HandleGadgets(-1, -1, 0);
2229 CloseDoor(DOOR_CLOSE_1);
2231 /* save old door content */
2232 BlitBitmap(bitmap_db_door, bitmap_db_door,
2233 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE,
2234 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1);
2236 SetDrawBackgroundMask(REDRAW_FIELD | REDRAW_DOOR_1);
2238 /* clear door drawing field */
2239 DrawBackground(DX, DY, DXSIZE, DYSIZE);
2241 /* force DOOR font on preview level */
2242 game_status = GAME_MODE_PSEUDO_DOOR;
2244 /* write text for request */
2245 for(ty=0; ty < MAX_REQUEST_LINES; ty++)
2247 char text_line[MAX_REQUEST_LINE_LEN + 1];
2253 for(tl=0,tx=0; tx < MAX_REQUEST_LINE_LEN; tl++,tx++)
2256 if (!tc || tc == ' ')
2267 strncpy(text_line, text, tl);
2270 DrawText(DX + (DXSIZE - tl * getFontWidth(FONT_TEXT_2)) / 2,
2271 DY + 8 + ty * (getFontHeight(FONT_TEXT_2) + 2),
2272 text_line, FONT_TEXT_2);
2274 text += tl + (tc == ' ' ? 1 : 0);
2277 game_status = last_game_status; /* restore current game status */
2279 if (req_state & REQ_ASK)
2281 MapGadget(tool_gadget[TOOL_CTRL_ID_YES]);
2282 MapGadget(tool_gadget[TOOL_CTRL_ID_NO]);
2284 else if (req_state & REQ_CONFIRM)
2286 MapGadget(tool_gadget[TOOL_CTRL_ID_CONFIRM]);
2288 else if (req_state & REQ_PLAYER)
2290 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_1]);
2291 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_2]);
2292 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_3]);
2293 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_4]);
2296 /* copy request gadgets to door backbuffer */
2297 BlitBitmap(drawto, bitmap_db_door,
2298 DX, DY, DXSIZE, DYSIZE,
2299 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
2301 OpenDoor(DOOR_OPEN_1);
2307 if (!(req_state & REQUEST_WAIT_FOR))
2309 SetDrawBackgroundMask(REDRAW_FIELD);
2314 if (game_status != GAME_MODE_MAIN)
2317 button_status = MB_RELEASED;
2319 request_gadget_id = -1;
2321 SetDrawBackgroundMask(REDRAW_FIELD | REDRAW_DOOR_1);
2324 SetMouseCursor(CURSOR_DEFAULT);
2337 case EVENT_BUTTONPRESS:
2338 case EVENT_BUTTONRELEASE:
2339 case EVENT_MOTIONNOTIFY:
2341 if (event.type == EVENT_MOTIONNOTIFY)
2343 if (!PointerInWindow(window))
2344 continue; /* window and pointer are on different screens */
2349 motion_status = TRUE;
2350 mx = ((MotionEvent *) &event)->x;
2351 my = ((MotionEvent *) &event)->y;
2355 motion_status = FALSE;
2356 mx = ((ButtonEvent *) &event)->x;
2357 my = ((ButtonEvent *) &event)->y;
2358 if (event.type == EVENT_BUTTONPRESS)
2359 button_status = ((ButtonEvent *) &event)->button;
2361 button_status = MB_RELEASED;
2364 /* this sets 'request_gadget_id' */
2365 HandleGadgets(mx, my, button_status);
2367 switch(request_gadget_id)
2369 case TOOL_CTRL_ID_YES:
2372 case TOOL_CTRL_ID_NO:
2375 case TOOL_CTRL_ID_CONFIRM:
2376 result = TRUE | FALSE;
2379 case TOOL_CTRL_ID_PLAYER_1:
2382 case TOOL_CTRL_ID_PLAYER_2:
2385 case TOOL_CTRL_ID_PLAYER_3:
2388 case TOOL_CTRL_ID_PLAYER_4:
2399 case EVENT_KEYPRESS:
2400 switch(GetEventKey((KeyEvent *)&event, TRUE))
2413 if (req_state & REQ_PLAYER)
2417 case EVENT_KEYRELEASE:
2418 ClearPlayerAction();
2422 HandleOtherEvents(&event);
2426 else if (AnyJoystickButton() == JOY_BUTTON_NEW_PRESSED)
2428 int joy = AnyJoystick();
2430 if (joy & JOY_BUTTON_1)
2432 else if (joy & JOY_BUTTON_2)
2438 /* don't eat all CPU time */
2442 if (game_status != GAME_MODE_MAIN)
2447 if (!(req_state & REQ_STAY_OPEN))
2449 CloseDoor(DOOR_CLOSE_1);
2451 if (!(req_state & REQ_STAY_CLOSED) && (old_door_state & DOOR_OPEN_1))
2453 BlitBitmap(bitmap_db_door, bitmap_db_door,
2454 DOOR_GFX_PAGEX2,DOOR_GFX_PAGEY1, DXSIZE,DYSIZE,
2455 DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY1);
2456 OpenDoor(DOOR_OPEN_1);
2462 SetDrawBackgroundMask(REDRAW_FIELD);
2464 #if defined(PLATFORM_UNIX)
2465 /* continue network game after request */
2466 if (options.network &&
2467 game_status == GAME_MODE_PLAYING &&
2468 req_state & REQUEST_WAIT_FOR)
2469 SendToServer_ContinuePlaying();
2475 unsigned int OpenDoor(unsigned int door_state)
2477 unsigned int new_door_state;
2479 if (door_state & DOOR_COPY_BACK)
2481 BlitBitmap(bitmap_db_door, bitmap_db_door,
2482 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE + VYSIZE,
2483 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
2484 door_state &= ~DOOR_COPY_BACK;
2487 new_door_state = MoveDoor(door_state);
2489 return(new_door_state);
2492 unsigned int CloseDoor(unsigned int door_state)
2494 unsigned int new_door_state;
2496 BlitBitmap(backbuffer, bitmap_db_door,
2497 DX, DY, DXSIZE, DYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
2498 BlitBitmap(backbuffer, bitmap_db_door,
2499 VX, VY, VXSIZE, VYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2);
2501 new_door_state = MoveDoor(door_state);
2503 return(new_door_state);
2506 unsigned int GetDoorState()
2508 return MoveDoor(DOOR_GET_STATE);
2511 unsigned int SetDoorState(unsigned int door_state)
2513 return MoveDoor(door_state | DOOR_SET_STATE);
2516 unsigned int MoveDoor(unsigned int door_state)
2518 static int door1 = DOOR_OPEN_1;
2519 static int door2 = DOOR_CLOSE_2;
2520 unsigned long door_delay = 0;
2521 unsigned long door_delay_value;
2524 if (door_state == DOOR_GET_STATE)
2525 return(door1 | door2);
2527 if (door_state & DOOR_SET_STATE)
2529 if (door_state & DOOR_ACTION_1)
2530 door1 = door_state & DOOR_ACTION_1;
2531 if (door_state & DOOR_ACTION_2)
2532 door2 = door_state & DOOR_ACTION_2;
2534 return(door1 | door2);
2537 if (door1 == DOOR_OPEN_1 && door_state & DOOR_OPEN_1)
2538 door_state &= ~DOOR_OPEN_1;
2539 else if (door1 == DOOR_CLOSE_1 && door_state & DOOR_CLOSE_1)
2540 door_state &= ~DOOR_CLOSE_1;
2541 if (door2 == DOOR_OPEN_2 && door_state & DOOR_OPEN_2)
2542 door_state &= ~DOOR_OPEN_2;
2543 else if (door2 == DOOR_CLOSE_2 && door_state & DOOR_CLOSE_2)
2544 door_state &= ~DOOR_CLOSE_2;
2546 door_delay_value = (door_state & DOOR_ACTION_1 ? door_1.step_delay :
2549 if (setup.quick_doors)
2551 stepsize = 20; /* must be choosen to always draw last frame */
2552 door_delay_value = 0;
2554 StopSound(SND_DOOR_OPENING);
2555 StopSound(SND_DOOR_CLOSING);
2558 if (global.autoplay_leveldir)
2560 door_state |= DOOR_NO_DELAY;
2561 door_state &= ~DOOR_CLOSE_ALL;
2564 if (door_state & DOOR_ACTION)
2566 boolean door_1_done = !(door_state & DOOR_ACTION_1);
2567 boolean door_2_done = !(door_state & DOOR_ACTION_2);
2568 int start = ((door_state & DOOR_NO_DELAY) ? DXSIZE : 0);
2569 int end = (door_state & DOOR_ACTION_1 &&
2570 door_1.anim_mode == ANIM_VERTICAL ? DYSIZE : DXSIZE);
2573 if (!(door_state & DOOR_NO_DELAY))
2575 /* opening door sound has priority over simultaneously closing door */
2576 if (door_state & (DOOR_OPEN_1 | DOOR_OPEN_2))
2577 PlaySoundStereo(SND_DOOR_OPENING, SOUND_MIDDLE);
2578 else if (door_state & (DOOR_CLOSE_1 | DOOR_CLOSE_2))
2579 PlaySoundStereo(SND_DOOR_CLOSING, SOUND_MIDDLE);
2582 for(x = start; x <= end && !(door_1_done && door_2_done); x += stepsize)
2584 Bitmap *bitmap = graphic_info[IMG_GLOBAL_DOOR].bitmap;
2585 GC gc = bitmap->stored_clip_gc;
2587 if (door_state & DOOR_ACTION_1)
2589 int a = MIN(x * door_1.step_offset, end);
2590 int i = (door_state & DOOR_OPEN_1 ? end - a : a);
2594 BlitBitmap(bitmap_db_door, drawto,
2595 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1 + i / 2,
2596 DXSIZE,DYSIZE - i / 2, DX, DY);
2598 ClearRectangle(drawto, DX, DY + DYSIZE - i / 2, DXSIZE, i / 2);
2601 if (door_1.anim_mode == ANIM_HORIZONTAL && x <= DXSIZE)
2603 int src1_x = DXSIZE, src1_y = DOOR_GFX_PAGEY1;
2604 int dst1_x = DX + DXSIZE - i, dst1_y = DY;
2605 int src2_x = DXSIZE - i, src2_y = DOOR_GFX_PAGEY1;
2606 int dst2_x = DX, dst2_y = DY;
2607 int width = i, height = DYSIZE;
2609 SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y);
2610 BlitBitmapMasked(bitmap, drawto, src1_x, src1_y, width, height,
2613 SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y);
2614 BlitBitmapMasked(bitmap, drawto, src2_x, src2_y, width, height,
2617 else if (door_1.anim_mode == ANIM_VERTICAL && x <= DYSIZE)
2619 int src1_x = DXSIZE, src1_y = DOOR_GFX_PAGEY1;
2620 int dst1_x = DX, dst1_y = DY + DYSIZE - i;
2621 int src2_x = 0, src2_y = DOOR_GFX_PAGEY1 + DYSIZE - i;
2622 int dst2_x = DX, dst2_y = DY;
2623 int width = DXSIZE, height = i;
2625 SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y);
2626 BlitBitmapMasked(bitmap, drawto, src1_x, src1_y, width, height,
2629 SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y);
2630 BlitBitmapMasked(bitmap, drawto, src2_x, src2_y, width, height,
2633 else if (x <= DXSIZE) /* ANIM_DEFAULT */
2635 int j = (door_1.anim_mode == ANIM_DEFAULT ? (DXSIZE - i) / 3 : 0);
2637 SetClipOrigin(bitmap, gc, DX - i, (DY + j) - DOOR_GFX_PAGEY1);
2638 BlitBitmapMasked(bitmap, drawto,
2639 DXSIZE, DOOR_GFX_PAGEY1, i, 77,
2640 DX + DXSIZE - i, DY + j);
2641 BlitBitmapMasked(bitmap, drawto,
2642 DXSIZE, DOOR_GFX_PAGEY1 + 140, i, 63,
2643 DX + DXSIZE - i, DY + 140 + j);
2644 SetClipOrigin(bitmap, gc, DX - DXSIZE + i,
2645 DY - (DOOR_GFX_PAGEY1 + j));
2646 BlitBitmapMasked(bitmap, drawto,
2647 DXSIZE - i, DOOR_GFX_PAGEY1 + j, i, 77 - j,
2649 BlitBitmapMasked(bitmap, drawto,
2650 DXSIZE-i, DOOR_GFX_PAGEY1 + 140, i, 63,
2653 BlitBitmapMasked(bitmap, drawto,
2654 DXSIZE - i, DOOR_GFX_PAGEY1 + 77, i, 63,
2656 BlitBitmapMasked(bitmap, drawto,
2657 DXSIZE - i, DOOR_GFX_PAGEY1 + 203, i, 77,
2659 SetClipOrigin(bitmap, gc, DX - i, (DY + j) - DOOR_GFX_PAGEY1);
2660 BlitBitmapMasked(bitmap, drawto,
2661 DXSIZE, DOOR_GFX_PAGEY1 + 77, i, 63,
2662 DX + DXSIZE - i, DY + 77 + j);
2663 BlitBitmapMasked(bitmap, drawto,
2664 DXSIZE, DOOR_GFX_PAGEY1 + 203, i, 77 - j,
2665 DX + DXSIZE - i, DY + 203 + j);
2668 redraw_mask |= REDRAW_DOOR_1;
2669 door_1_done = (a == end);
2672 if (door_state & DOOR_ACTION_2)
2674 int a = MIN(x * door_2.step_offset, VXSIZE);
2675 int i = (door_state & DOOR_OPEN_2 ? VXSIZE - a : a);
2679 BlitBitmap(bitmap_db_door, drawto,
2680 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2 + i / 2,
2681 VXSIZE, VYSIZE - i / 2, VX, VY);
2683 ClearRectangle(drawto, VX, VY + VYSIZE - i / 2, VXSIZE, i / 2);
2686 if (door_2.anim_mode == ANIM_HORIZONTAL && x <= VXSIZE)
2688 int src1_x = VXSIZE, src1_y = DOOR_GFX_PAGEY2;
2689 int dst1_x = VX + VXSIZE - i, dst1_y = VY;
2690 int src2_x = VXSIZE - i, src2_y = DOOR_GFX_PAGEY2;
2691 int dst2_x = VX, dst2_y = VY;
2692 int width = i, height = VYSIZE;
2694 SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y);
2695 BlitBitmapMasked(bitmap, drawto, src1_x, src1_y, width, height,
2698 SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y);
2699 BlitBitmapMasked(bitmap, drawto, src2_x, src2_y, width, height,
2702 else if (door_2.anim_mode == ANIM_VERTICAL && x <= VYSIZE)
2704 int src1_x = VXSIZE, src1_y = DOOR_GFX_PAGEY2;
2705 int dst1_x = VX, dst1_y = VY + VYSIZE - i;
2706 int src2_x = 0, src2_y = DOOR_GFX_PAGEY2 + VYSIZE - i;
2707 int dst2_x = VX, dst2_y = VY;
2708 int width = VXSIZE, height = i;
2710 SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y);
2711 BlitBitmapMasked(bitmap, drawto, src1_x, src1_y, width, height,
2714 SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y);
2715 BlitBitmapMasked(bitmap, drawto, src2_x, src2_y, width, height,
2718 else if (x <= VXSIZE) /* ANIM_DEFAULT */
2720 int j = (door_2.anim_mode == ANIM_DEFAULT ? (VXSIZE - i) / 3 : 0);
2722 SetClipOrigin(bitmap, gc, VX - i, (VY + j) - DOOR_GFX_PAGEY2);
2723 BlitBitmapMasked(bitmap, drawto,
2724 VXSIZE, DOOR_GFX_PAGEY2, i, VYSIZE / 2,
2725 VX + VXSIZE - i, VY + j);
2726 SetClipOrigin(bitmap, gc,
2727 VX - VXSIZE + i, VY - (DOOR_GFX_PAGEY2 + j));
2728 BlitBitmapMasked(bitmap, drawto,
2729 VXSIZE - i, DOOR_GFX_PAGEY2 + j, i, VYSIZE / 2 - j,
2732 BlitBitmapMasked(bitmap, drawto,
2733 VXSIZE - i, DOOR_GFX_PAGEY2 + VYSIZE / 2,
2734 i, VYSIZE / 2, VX, VY + VYSIZE / 2 - j);
2735 SetClipOrigin(bitmap, gc, VX - i, (VY + j) - DOOR_GFX_PAGEY2);
2736 BlitBitmapMasked(bitmap, drawto,
2737 VXSIZE, DOOR_GFX_PAGEY2 + VYSIZE / 2,
2739 VX + VXSIZE - i, VY + VYSIZE / 2 + j);
2742 redraw_mask |= REDRAW_DOOR_2;
2743 door_2_done = (a == VXSIZE);
2748 if (game_status == GAME_MODE_MAIN)
2751 if (!(door_state & DOOR_NO_DELAY))
2752 WaitUntilDelayReached(&door_delay, door_delay_value);
2756 if (setup.quick_doors)
2758 StopSound(SND_DOOR_OPENING);
2759 StopSound(SND_DOOR_CLOSING);
2762 if (door_state & DOOR_ACTION_1)
2763 door1 = door_state & DOOR_ACTION_1;
2764 if (door_state & DOOR_ACTION_2)
2765 door2 = door_state & DOOR_ACTION_2;
2767 return (door1 | door2);
2770 void DrawSpecialEditorDoor()
2772 /* draw bigger toolbox window */
2773 BlitBitmap(graphic_info[IMG_GLOBAL_DOOR].bitmap, drawto,
2774 DOOR_GFX_PAGEX7, 0, EXSIZE + 8, 8,
2776 BlitBitmap(graphic_info[IMG_GLOBAL_BORDER].bitmap, drawto,
2777 EX - 4, VY - 4, EXSIZE + 8, EYSIZE - VYSIZE + 4,
2780 redraw_mask |= REDRAW_ALL;
2783 void UndrawSpecialEditorDoor()
2785 /* draw normal tape recorder window */
2786 BlitBitmap(graphic_info[IMG_GLOBAL_BORDER].bitmap, drawto,
2787 EX - 4, EY - 12, EXSIZE + 8, EYSIZE - VYSIZE + 12,
2790 redraw_mask |= REDRAW_ALL;
2794 /* ---------- new tool button stuff ---------------------------------------- */
2796 /* graphic position values for tool buttons */
2797 #define TOOL_BUTTON_YES_XPOS 2
2798 #define TOOL_BUTTON_YES_YPOS 250
2799 #define TOOL_BUTTON_YES_GFX_YPOS 0
2800 #define TOOL_BUTTON_YES_XSIZE 46
2801 #define TOOL_BUTTON_YES_YSIZE 28
2802 #define TOOL_BUTTON_NO_XPOS 52
2803 #define TOOL_BUTTON_NO_YPOS TOOL_BUTTON_YES_YPOS
2804 #define TOOL_BUTTON_NO_GFX_YPOS TOOL_BUTTON_YES_GFX_YPOS
2805 #define TOOL_BUTTON_NO_XSIZE TOOL_BUTTON_YES_XSIZE
2806 #define TOOL_BUTTON_NO_YSIZE TOOL_BUTTON_YES_YSIZE
2807 #define TOOL_BUTTON_CONFIRM_XPOS TOOL_BUTTON_YES_XPOS
2808 #define TOOL_BUTTON_CONFIRM_YPOS TOOL_BUTTON_YES_YPOS
2809 #define TOOL_BUTTON_CONFIRM_GFX_YPOS 30
2810 #define TOOL_BUTTON_CONFIRM_XSIZE 96
2811 #define TOOL_BUTTON_CONFIRM_YSIZE TOOL_BUTTON_YES_YSIZE
2812 #define TOOL_BUTTON_PLAYER_XSIZE 30
2813 #define TOOL_BUTTON_PLAYER_YSIZE 30
2814 #define TOOL_BUTTON_PLAYER_GFX_XPOS 5
2815 #define TOOL_BUTTON_PLAYER_GFX_YPOS 185
2816 #define TOOL_BUTTON_PLAYER_XPOS (5 + TOOL_BUTTON_PLAYER_XSIZE / 2)
2817 #define TOOL_BUTTON_PLAYER_YPOS (215 - TOOL_BUTTON_PLAYER_YSIZE / 2)
2818 #define TOOL_BUTTON_PLAYER1_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2819 + 0 * TOOL_BUTTON_PLAYER_XSIZE)
2820 #define TOOL_BUTTON_PLAYER2_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2821 + 1 * TOOL_BUTTON_PLAYER_XSIZE)
2822 #define TOOL_BUTTON_PLAYER3_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2823 + 0 * TOOL_BUTTON_PLAYER_XSIZE)
2824 #define TOOL_BUTTON_PLAYER4_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2825 + 1 * TOOL_BUTTON_PLAYER_XSIZE)
2826 #define TOOL_BUTTON_PLAYER1_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2827 + 0 * TOOL_BUTTON_PLAYER_YSIZE)
2828 #define TOOL_BUTTON_PLAYER2_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2829 + 0 * TOOL_BUTTON_PLAYER_YSIZE)
2830 #define TOOL_BUTTON_PLAYER3_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2831 + 1 * TOOL_BUTTON_PLAYER_YSIZE)
2832 #define TOOL_BUTTON_PLAYER4_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2833 + 1 * TOOL_BUTTON_PLAYER_YSIZE)
2842 } toolbutton_info[NUM_TOOL_BUTTONS] =
2845 TOOL_BUTTON_YES_XPOS, TOOL_BUTTON_YES_GFX_YPOS,
2846 TOOL_BUTTON_YES_XPOS, TOOL_BUTTON_YES_YPOS,
2847 TOOL_BUTTON_YES_XSIZE, TOOL_BUTTON_YES_YSIZE,
2852 TOOL_BUTTON_NO_XPOS, TOOL_BUTTON_NO_GFX_YPOS,
2853 TOOL_BUTTON_NO_XPOS, TOOL_BUTTON_NO_YPOS,
2854 TOOL_BUTTON_NO_XSIZE, TOOL_BUTTON_NO_YSIZE,
2859 TOOL_BUTTON_CONFIRM_XPOS, TOOL_BUTTON_CONFIRM_GFX_YPOS,
2860 TOOL_BUTTON_CONFIRM_XPOS, TOOL_BUTTON_CONFIRM_YPOS,
2861 TOOL_BUTTON_CONFIRM_XSIZE, TOOL_BUTTON_CONFIRM_YSIZE,
2862 TOOL_CTRL_ID_CONFIRM,
2866 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2867 TOOL_BUTTON_PLAYER1_XPOS, TOOL_BUTTON_PLAYER1_YPOS,
2868 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2869 TOOL_CTRL_ID_PLAYER_1,
2873 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2874 TOOL_BUTTON_PLAYER2_XPOS, TOOL_BUTTON_PLAYER2_YPOS,
2875 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2876 TOOL_CTRL_ID_PLAYER_2,
2880 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2881 TOOL_BUTTON_PLAYER3_XPOS, TOOL_BUTTON_PLAYER3_YPOS,
2882 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2883 TOOL_CTRL_ID_PLAYER_3,
2887 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2888 TOOL_BUTTON_PLAYER4_XPOS, TOOL_BUTTON_PLAYER4_YPOS,
2889 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2890 TOOL_CTRL_ID_PLAYER_4,
2895 void CreateToolButtons()
2899 for (i=0; i<NUM_TOOL_BUTTONS; i++)
2901 Bitmap *gd_bitmap = graphic_info[IMG_GLOBAL_DOOR].bitmap;
2902 Bitmap *deco_bitmap = None;
2903 int deco_x = 0, deco_y = 0, deco_xpos = 0, deco_ypos = 0;
2904 struct GadgetInfo *gi;
2905 unsigned long event_mask;
2906 int gd_xoffset, gd_yoffset;
2907 int gd_x1, gd_x2, gd_y;
2910 event_mask = GD_EVENT_RELEASED;
2912 gd_xoffset = toolbutton_info[i].xpos;
2913 gd_yoffset = toolbutton_info[i].ypos;
2914 gd_x1 = DOOR_GFX_PAGEX4 + gd_xoffset;
2915 gd_x2 = DOOR_GFX_PAGEX3 + gd_xoffset;
2916 gd_y = DOOR_GFX_PAGEY1 + gd_yoffset;
2918 if (id >= TOOL_CTRL_ID_PLAYER_1 && id <= TOOL_CTRL_ID_PLAYER_4)
2920 int player_nr = id - TOOL_CTRL_ID_PLAYER_1;
2922 getMiniGraphicSource(PLAYER_NR_GFX(IMG_PLAYER_1, player_nr),
2923 &deco_bitmap, &deco_x, &deco_y);
2924 deco_xpos = (toolbutton_info[i].width - MINI_TILEX) / 2;
2925 deco_ypos = (toolbutton_info[i].height - MINI_TILEY) / 2;
2928 gi = CreateGadget(GDI_CUSTOM_ID, id,
2929 GDI_INFO_TEXT, toolbutton_info[i].infotext,
2930 GDI_X, DX + toolbutton_info[i].x,
2931 GDI_Y, DY + toolbutton_info[i].y,
2932 GDI_WIDTH, toolbutton_info[i].width,
2933 GDI_HEIGHT, toolbutton_info[i].height,
2934 GDI_TYPE, GD_TYPE_NORMAL_BUTTON,
2935 GDI_STATE, GD_BUTTON_UNPRESSED,
2936 GDI_DESIGN_UNPRESSED, gd_bitmap, gd_x1, gd_y,
2937 GDI_DESIGN_PRESSED, gd_bitmap, gd_x2, gd_y,
2938 GDI_DECORATION_DESIGN, deco_bitmap, deco_x, deco_y,
2939 GDI_DECORATION_POSITION, deco_xpos, deco_ypos,
2940 GDI_DECORATION_SIZE, MINI_TILEX, MINI_TILEY,
2941 GDI_DECORATION_SHIFTING, 1, 1,
2942 GDI_EVENT_MASK, event_mask,
2943 GDI_CALLBACK_ACTION, HandleToolButtons,
2947 Error(ERR_EXIT, "cannot create gadget");
2949 tool_gadget[id] = gi;
2953 void FreeToolButtons()
2957 for (i=0; i<NUM_TOOL_BUTTONS; i++)
2958 FreeGadget(tool_gadget[i]);
2961 static void UnmapToolButtons()
2965 for (i=0; i<NUM_TOOL_BUTTONS; i++)
2966 UnmapGadget(tool_gadget[i]);
2969 static void HandleToolButtons(struct GadgetInfo *gi)
2971 request_gadget_id = gi->custom_id;
2974 int get_next_element(int element)
2978 case EL_QUICKSAND_FILLING: return EL_QUICKSAND_FULL;
2979 case EL_QUICKSAND_EMPTYING: return EL_QUICKSAND_EMPTY;
2980 case EL_MAGIC_WALL_FILLING: return EL_MAGIC_WALL_FULL;
2981 case EL_MAGIC_WALL_EMPTYING: return EL_MAGIC_WALL_ACTIVE;
2982 case EL_BD_MAGIC_WALL_FILLING: return EL_BD_MAGIC_WALL_FULL;
2983 case EL_BD_MAGIC_WALL_EMPTYING: return EL_BD_MAGIC_WALL_ACTIVE;
2984 case EL_AMOEBA_DROPPING: return EL_AMOEBA_WET;
2986 default: return element;
2990 int el_act_dir2img(int element, int action, int direction)
2992 element = GFX_ELEMENT(element);
2993 direction = MV_DIR_BIT(direction);
2995 return element_info[element].direction_graphic[action][direction];
2998 static int el_act_dir2crm(int element, int action, int direction)
3000 element = GFX_ELEMENT(element);
3001 direction = MV_DIR_BIT(direction);
3003 return element_info[element].direction_crumbled[action][direction];
3006 int el_act2img(int element, int action)
3008 element = GFX_ELEMENT(element);
3010 return element_info[element].graphic[action];
3013 int el_act2crm(int element, int action)
3015 element = GFX_ELEMENT(element);
3017 return element_info[element].crumbled[action];
3020 int el_dir2img(int element, int direction)
3022 element = GFX_ELEMENT(element);
3024 return el_act_dir2img(element, ACTION_DEFAULT, direction);
3027 int el2img(int element)
3029 element = GFX_ELEMENT(element);
3031 return element_info[element].graphic[ACTION_DEFAULT];
3034 int el2edimg(int element)
3036 element = GFX_ELEMENT(element);
3038 return element_info[element].special_graphic[GFX_SPECIAL_ARG_EDITOR];
3041 int el2preimg(int element)
3043 element = GFX_ELEMENT(element);
3045 return element_info[element].special_graphic[GFX_SPECIAL_ARG_PREVIEW];