1 /***********************************************************
2 * Rocks'n'Diamonds -- McDuffin Strikes Back! *
3 *----------------------------------------------------------*
4 * (c) 1995-2002 Artsoft Entertainment *
6 * Detmolder Strasse 189 *
9 * e-mail: info@artsoft.org *
10 *----------------------------------------------------------*
12 ***********************************************************/
14 #include "libgame/libgame.h"
23 /* tool button identifiers */
24 #define TOOL_CTRL_ID_YES 0
25 #define TOOL_CTRL_ID_NO 1
26 #define TOOL_CTRL_ID_CONFIRM 2
27 #define TOOL_CTRL_ID_PLAYER_1 3
28 #define TOOL_CTRL_ID_PLAYER_2 4
29 #define TOOL_CTRL_ID_PLAYER_3 5
30 #define TOOL_CTRL_ID_PLAYER_4 6
32 #define NUM_TOOL_BUTTONS 7
34 /* forward declaration for internal use */
35 static void UnmapToolButtons();
36 static void HandleToolButtons(struct GadgetInfo *);
38 static struct GadgetInfo *tool_gadget[NUM_TOOL_BUTTONS];
39 static int request_gadget_id = -1;
41 void SetDrawtoField(int mode)
43 if (mode == DRAW_BUFFERED && setup.soft_scrolling)
54 drawto_field = fieldbuffer;
56 else /* DRAW_DIRECT, DRAW_BACKBUFFER */
67 drawto_field = (mode == DRAW_DIRECT ? window : backbuffer);
71 void RedrawPlayfield(boolean force_redraw, int x, int y, int width, int height)
73 if (game_status == PLAYING)
79 width = gfx.sxsize + 2 * TILEX;
80 height = gfx.sysize + 2 * TILEY;
83 if (force_redraw || setup.direct_draw)
86 int x1 = (x - SX) / TILEX, y1 = (y - SY) / TILEY;
87 int x2 = (x - SX + width) / TILEX, y2 = (y - SY + height) / TILEY;
89 if (setup.direct_draw)
90 SetDrawtoField(DRAW_BACKBUFFER);
92 for(xx=BX1; xx<=BX2; xx++)
93 for(yy=BY1; yy<=BY2; yy++)
94 if (xx >= x1 && xx <= x2 && yy >= y1 && yy <= y2)
95 DrawScreenField(xx, yy);
98 if (setup.direct_draw)
99 SetDrawtoField(DRAW_DIRECT);
102 if (setup.soft_scrolling)
104 int fx = FX, fy = FY;
106 fx += (ScreenMovDir & (MV_LEFT|MV_RIGHT) ? ScreenGfxPos : 0);
107 fy += (ScreenMovDir & (MV_UP|MV_DOWN) ? ScreenGfxPos : 0);
109 BlitBitmap(fieldbuffer, backbuffer, fx,fy, SXSIZE,SYSIZE, SX,SY);
113 BlitBitmap(drawto, window, x, y, width, height, x, y);
119 DrawBuffer *buffer = (drawto_field == window ? backbuffer : drawto_field);
121 if (setup.direct_draw && game_status == PLAYING)
122 redraw_mask &= ~REDRAW_MAIN;
124 if (redraw_mask & REDRAW_TILES && redraw_tiles > REDRAWTILES_THRESHOLD)
125 redraw_mask |= REDRAW_FIELD;
127 if (redraw_mask & REDRAW_FIELD)
128 redraw_mask &= ~REDRAW_TILES;
130 if (redraw_mask == REDRAW_NONE)
133 if (global.fps_slowdown && game_status == PLAYING)
135 static boolean last_frame_skipped = FALSE;
136 boolean skip_even_when_not_scrolling = TRUE;
137 boolean just_scrolling = (ScreenMovDir != 0);
138 boolean verbose = FALSE;
140 if (global.fps_slowdown_factor > 1 &&
141 (FrameCounter % global.fps_slowdown_factor) &&
142 (just_scrolling || skip_even_when_not_scrolling))
144 redraw_mask &= ~REDRAW_MAIN;
146 last_frame_skipped = TRUE;
149 printf("FRAME SKIPPED\n");
153 if (last_frame_skipped)
154 redraw_mask |= REDRAW_FIELD;
156 last_frame_skipped = FALSE;
159 printf("frame not skipped\n");
163 /* synchronize X11 graphics at this point; if we would synchronize the
164 display immediately after the buffer switching (after the XFlush),
165 this could mean that we have to wait for the graphics to complete,
166 although we could go on doing calculations for the next frame */
170 if (redraw_mask & REDRAW_ALL)
172 BlitBitmap(backbuffer, window, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
176 if (redraw_mask & REDRAW_FIELD)
178 if (game_status != PLAYING || redraw_mask & REDRAW_FROM_BACKBUFFER)
180 BlitBitmap(backbuffer, window,
181 REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE, REAL_SX, REAL_SY);
185 int fx = FX, fy = FY;
187 if (setup.soft_scrolling)
189 fx += (ScreenMovDir & (MV_LEFT | MV_RIGHT) ? ScreenGfxPos : 0);
190 fy += (ScreenMovDir & (MV_UP | MV_DOWN) ? ScreenGfxPos : 0);
193 if (setup.soft_scrolling ||
194 ABS(ScreenMovPos) + ScrollStepSize == TILEX ||
195 ABS(ScreenMovPos) == ScrollStepSize ||
196 redraw_tiles > REDRAWTILES_THRESHOLD)
198 BlitBitmap(buffer, window, fx, fy, SXSIZE, SYSIZE, SX, SY);
202 printf("redrawing all (ScreenGfxPos == %d) because %s\n",
204 (setup.soft_scrolling ?
205 "setup.soft_scrolling" :
206 ABS(ScreenGfxPos) + ScrollStepSize == TILEX ?
207 "ABS(ScreenGfxPos) + ScrollStepSize == TILEX" :
208 ABS(ScreenGfxPos) == ScrollStepSize ?
209 "ABS(ScreenGfxPos) == ScrollStepSize" :
210 "redraw_tiles > REDRAWTILES_THRESHOLD"));
216 redraw_mask &= ~REDRAW_MAIN;
219 if (redraw_mask & REDRAW_DOORS)
221 if (redraw_mask & REDRAW_DOOR_1)
222 BlitBitmap(backbuffer, window, DX, DY, DXSIZE, DYSIZE, DX, DY);
223 if (redraw_mask & REDRAW_DOOR_2)
225 if ((redraw_mask & REDRAW_DOOR_2) == REDRAW_DOOR_2)
226 BlitBitmap(backbuffer, window, VX,VY, VXSIZE,VYSIZE, VX,VY);
229 if (redraw_mask & REDRAW_VIDEO_1)
230 BlitBitmap(backbuffer, window,
231 VX+VIDEO_DISPLAY1_XPOS,VY+VIDEO_DISPLAY1_YPOS,
232 VIDEO_DISPLAY_XSIZE,VIDEO_DISPLAY_YSIZE,
233 VX+VIDEO_DISPLAY1_XPOS,VY+VIDEO_DISPLAY1_YPOS);
234 if (redraw_mask & REDRAW_VIDEO_2)
235 BlitBitmap(backbuffer, window,
236 VX+VIDEO_DISPLAY2_XPOS,VY+VIDEO_DISPLAY2_YPOS,
237 VIDEO_DISPLAY_XSIZE,VIDEO_DISPLAY_YSIZE,
238 VX+VIDEO_DISPLAY2_XPOS,VY+VIDEO_DISPLAY2_YPOS);
239 if (redraw_mask & REDRAW_VIDEO_3)
240 BlitBitmap(backbuffer, window,
241 VX+VIDEO_CONTROL_XPOS,VY+VIDEO_CONTROL_YPOS,
242 VIDEO_CONTROL_XSIZE,VIDEO_CONTROL_YSIZE,
243 VX+VIDEO_CONTROL_XPOS,VY+VIDEO_CONTROL_YPOS);
246 if (redraw_mask & REDRAW_DOOR_3)
247 BlitBitmap(backbuffer, window, EX, EY, EXSIZE, EYSIZE, EX, EY);
248 redraw_mask &= ~REDRAW_DOORS;
251 if (redraw_mask & REDRAW_MICROLEVEL)
253 BlitBitmap(backbuffer, window,
254 MICROLEV_XPOS, MICROLEV_YPOS, MICROLEV_XSIZE, MICROLEV_YSIZE,
255 MICROLEV_XPOS, MICROLEV_YPOS);
256 BlitBitmap(backbuffer, window,
257 SX, MICROLABEL_YPOS, SXSIZE, getFontHeight(FONT_SPECIAL_GAME),
258 SX, MICROLABEL_YPOS);
259 redraw_mask &= ~REDRAW_MICROLEVEL;
262 if (redraw_mask & REDRAW_TILES)
264 for(x=0; x<SCR_FIELDX; x++)
265 for(y=0; y<SCR_FIELDY; y++)
266 if (redraw[redraw_x1 + x][redraw_y1 + y])
267 BlitBitmap(buffer, window,
268 FX + x * TILEX, FX + y * TILEY, TILEX, TILEY,
269 SX + x * TILEX, SY + y * TILEY);
272 if (redraw_mask & REDRAW_FPS) /* display frames per second */
277 sprintf(info1, " (only every %d. frame)", global.fps_slowdown_factor);
278 if (!global.fps_slowdown)
281 sprintf(text, "%.1f fps%s", global.frames_per_second, info1);
282 DrawTextExt(window, SX, SY, text, FONT_DEFAULT_SMALL, FONT_OPAQUE);
287 for(x=0; x<MAX_BUF_XSIZE; x++)
288 for(y=0; y<MAX_BUF_YSIZE; y++)
291 redraw_mask = REDRAW_NONE;
297 long fading_delay = 300;
299 if (setup.fading && (redraw_mask & REDRAW_FIELD))
306 ClearRectangle(window, REAL_SX,REAL_SY,FULL_SXSIZE,FULL_SYSIZE);
309 for(i=0;i<2*FULL_SYSIZE;i++)
311 for(y=0;y<FULL_SYSIZE;y++)
313 BlitBitmap(backbuffer, window,
314 REAL_SX,REAL_SY+i, FULL_SXSIZE,1, REAL_SX,REAL_SY+i);
322 for(i=1;i<FULL_SYSIZE;i+=2)
323 BlitBitmap(backbuffer, window,
324 REAL_SX,REAL_SY+i, FULL_SXSIZE,1, REAL_SX,REAL_SY+i);
330 SetClipOrigin(clip_gc[PIX_FADEMASK], 0, 0);
331 BlitBitmapMasked(backbuffer, window,
332 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE,
337 SetClipOrigin(clip_gc[PIX_FADEMASK], -1, -1);
338 BlitBitmapMasked(backbuffer, window,
339 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE,
344 SetClipOrigin(clip_gc[PIX_FADEMASK], 0, -1);
345 BlitBitmapMasked(backbuffer, window,
346 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE,
351 SetClipOrigin(clip_gc[PIX_FADEMASK], -1, 0);
352 BlitBitmapMasked(backbuffer, window,
353 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE,
358 redraw_mask &= ~REDRAW_MAIN;
365 void SetMainBackgroundImage(int graphic)
367 SetMainBackgroundBitmap(graphic == IMG_UNDEFINED ? NULL :
368 graphic_info[graphic].bitmap ?
369 graphic_info[graphic].bitmap :
370 graphic_info[IMG_BACKGROUND].bitmap);
373 void SetDoorBackgroundImage(int graphic)
375 SetDoorBackgroundBitmap(graphic == IMG_UNDEFINED ? NULL :
376 graphic_info[graphic].bitmap ?
377 graphic_info[graphic].bitmap :
378 graphic_info[IMG_BACKGROUND].bitmap);
381 void DrawBackground(int dest_x, int dest_y, int width, int height)
383 ClearRectangleOnBackground(backbuffer, dest_x, dest_y, width, height);
385 redraw_mask |= REDRAW_FIELD;
390 DrawBackground(REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE);
392 if (setup.soft_scrolling && game_status == PLAYING)
394 ClearRectangle(fieldbuffer, 0, 0, FXSIZE, FYSIZE);
395 SetDrawtoField(DRAW_BUFFERED);
398 SetDrawtoField(DRAW_BACKBUFFER);
400 if (setup.direct_draw && game_status == PLAYING)
402 ClearRectangle(window, REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE);
403 SetDrawtoField(DRAW_DIRECT);
407 void MarkTileDirty(int x, int y)
409 int xx = redraw_x1 + x;
410 int yy = redraw_y1 + y;
415 redraw[xx][yy] = TRUE;
416 redraw_mask |= REDRAW_TILES;
419 void SetBorderElement()
423 BorderElement = EL_EMPTY;
425 for(y=0; y<lev_fieldy && BorderElement == EL_EMPTY; y++)
427 for(x=0; x<lev_fieldx; x++)
429 if (!IS_INDESTRUCTIBLE(Feld[x][y]))
430 BorderElement = EL_STEELWALL;
432 if (y != 0 && y != lev_fieldy - 1 && x != lev_fieldx - 1)
438 void SetRandomAnimationValue(int x, int y)
440 gfx.anim_random_frame = GfxRandom[x][y];
443 inline int getGraphicAnimationFrame(int graphic, int sync_frame)
445 /* animation synchronized with global frame counter, not move position */
446 if (graphic_info[graphic].anim_global_sync || sync_frame < 0)
447 sync_frame = FrameCounter;
449 return getAnimationFrame(graphic_info[graphic].anim_frames,
450 graphic_info[graphic].anim_delay,
451 graphic_info[graphic].anim_mode,
452 graphic_info[graphic].anim_start_frame,
456 inline void DrawGraphicAnimationExt(DrawBuffer *dst_bitmap, int x, int y,
457 int graphic, int sync_frame, int mask_mode)
459 int frame = getGraphicAnimationFrame(graphic, sync_frame);
461 if (mask_mode == USE_MASKING)
462 DrawGraphicThruMaskExt(dst_bitmap, x, y, graphic, frame);
464 DrawGraphicExt(dst_bitmap, x, y, graphic, frame);
467 inline void DrawGraphicAnimation(int x, int y, int graphic)
469 int lx = LEVELX(x), ly = LEVELY(y);
471 if (!IN_SCR_FIELD(x, y))
474 DrawGraphicAnimationExt(drawto_field, FX + x * TILEX, FY + y * TILEY,
475 graphic, GfxFrame[lx][ly], NO_MASKING);
479 void DrawLevelGraphicAnimation(int x, int y, int graphic)
481 DrawGraphicAnimation(SCREENX(x), SCREENY(y), graphic);
484 void DrawLevelElementAnimation(int x, int y, int element)
486 DrawGraphicAnimation(SCREENX(x), SCREENY(y), el2img(element));
489 inline void DrawLevelGraphicAnimationIfNeeded(int x, int y, int graphic)
491 int sx = SCREENX(x), sy = SCREENY(y);
493 if (!IN_LEV_FIELD(x, y) || !IN_SCR_FIELD(sx, sy))
496 if (!IS_NEW_FRAME(GfxFrame[x][y], graphic))
499 DrawGraphicAnimation(sx, sy, graphic);
502 void DrawLevelElementAnimationIfNeeded(int x, int y, int element)
504 int sx = SCREENX(x), sy = SCREENY(y);
507 if (!IN_LEV_FIELD(x, y) || !IN_SCR_FIELD(sx, sy))
510 graphic = el_act_dir2img(element, GfxAction[x][y], MovDir[x][y]);
512 if (!IS_NEW_FRAME(GfxFrame[x][y], graphic))
515 DrawGraphicAnimation(sx, sy, graphic);
518 void DrawAllPlayers()
522 for(i=0; i<MAX_PLAYERS; i++)
523 if (stored_player[i].active)
524 DrawPlayer(&stored_player[i]);
527 void DrawPlayerField(int x, int y)
529 if (!IS_PLAYER(x, y))
532 DrawPlayer(PLAYERINFO(x, y));
535 void DrawPlayer(struct PlayerInfo *player)
537 int jx = player->jx, jy = player->jy;
538 int last_jx = player->last_jx, last_jy = player->last_jy;
539 int next_jx = jx + (jx - last_jx), next_jy = jy + (jy - last_jy);
540 int sx = SCREENX(jx), sy = SCREENY(jy);
541 int sxx = 0, syy = 0;
542 int element = Feld[jx][jy], last_element = Feld[last_jx][last_jy];
545 boolean player_is_moving = (last_jx != jx || last_jy != jy ? TRUE : FALSE);
547 if (!player->active || !IN_SCR_FIELD(SCREENX(last_jx), SCREENY(last_jy)))
551 if (!IN_LEV_FIELD(jx,jy))
553 printf("DrawPlayerField(): x = %d, y = %d\n",jx,jy);
554 printf("DrawPlayerField(): sx = %d, sy = %d\n",sx,sy);
555 printf("DrawPlayerField(): This should never happen!\n");
560 if (element == EL_EXPLOSION)
563 /* ----------------------------------------------------------------------- */
564 /* draw things in the field the player is leaving, if needed */
565 /* ----------------------------------------------------------------------- */
567 if (player_is_moving)
569 if (Store[last_jx][last_jy] && IS_DRAWABLE(last_element))
571 DrawLevelElement(last_jx, last_jy, Store[last_jx][last_jy]);
573 if (last_element == EL_DYNAMITE_ACTIVE ||
574 last_element == EL_SP_DISK_RED_ACTIVE)
575 DrawDynamite(last_jx, last_jy);
577 DrawLevelFieldThruMask(last_jx, last_jy);
579 else if (last_element == EL_DYNAMITE_ACTIVE ||
580 last_element == EL_SP_DISK_RED_ACTIVE)
581 DrawDynamite(last_jx, last_jy);
583 DrawLevelField(last_jx, last_jy);
585 if (player->Pushing && IN_SCR_FIELD(SCREENX(next_jx), SCREENY(next_jy)))
589 if (Feld[next_jx][next_jy] == EL_SOKOBAN_FIELD_FULL)
590 DrawLevelElement(next_jx, next_jy, EL_SOKOBAN_FIELD_EMPTY);
592 DrawLevelElement(next_jx, next_jy, EL_EMPTY);
595 DrawLevelField(next_jx, next_jy);
599 if (!IN_SCR_FIELD(sx, sy))
602 if (setup.direct_draw)
603 SetDrawtoField(DRAW_BUFFERED);
605 /* ----------------------------------------------------------------------- */
606 /* draw things behind the player, if needed */
607 /* ----------------------------------------------------------------------- */
610 DrawLevelElement(jx, jy, Store[jx][jy]);
611 else if (!IS_ACTIVE_BOMB(element))
612 DrawLevelField(jx, jy);
614 DrawLevelElement(jx, jy, EL_EMPTY);
616 /* ----------------------------------------------------------------------- */
617 /* draw player himself */
618 /* ----------------------------------------------------------------------- */
620 player->GfxAction = (player->Pushing ? ACTION_PUSHING :
621 player->is_digging ? ACTION_DIGGING :
622 player->is_moving ? ACTION_MOVING :
623 player->snapped ? ACTION_SNAPPING : ACTION_DEFAULT);
625 if (player->use_murphy_graphic)
627 static int last_horizontal_dir = MV_LEFT;
630 if (player->MovDir == MV_LEFT || player->MovDir == MV_RIGHT)
631 last_horizontal_dir = player->MovDir;
633 direction = (player->snapped ? player->MovDir : last_horizontal_dir);
635 graphic = el_act_dir2img(EL_SP_MURPHY, player->GfxAction, direction);
638 graphic = el_act_dir2img(player->element_nr, player->GfxAction,
641 frame = getGraphicAnimationFrame(graphic, player->Frame);
645 if (player->MovDir == MV_LEFT || player->MovDir == MV_RIGHT)
646 sxx = player->GfxPos;
648 syy = player->GfxPos;
651 if (!setup.soft_scrolling && ScreenMovPos)
654 DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, frame, NO_CUTTING);
656 if (SHIELD_ON(player))
658 int graphic = (player->shield_deadly_time_left ? IMG_SHIELD_DEADLY_ACTIVE :
659 IMG_SHIELD_NORMAL_ACTIVE);
660 int frame = getGraphicAnimationFrame(graphic, -1);
662 DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, frame, NO_CUTTING);
665 /* ----------------------------------------------------------------------- */
666 /* draw things the player is pushing, if needed */
667 /* ----------------------------------------------------------------------- */
669 if (player->Pushing && player_is_moving)
671 int px = SCREENX(next_jx), py = SCREENY(next_jy);
674 (element == EL_SOKOBAN_FIELD_EMPTY ||
675 Feld[next_jx][next_jy] == EL_SOKOBAN_FIELD_FULL))
676 DrawGraphicShiftedThruMask(px, py, sxx, syy, IMG_SOKOBAN_OBJECT, 0,
680 int element = Feld[next_jx][next_jy];
681 int graphic = el2img(element);
684 if ((sxx || syy) && IS_PUSHABLE(element))
686 graphic = el_act_dir2img(element, ACTION_MOVING, player->MovDir);
687 frame = getGraphicAnimationFrame(graphic, player->Frame);
690 DrawGraphicShifted(px, py, sxx, syy, graphic, frame,
691 NO_CUTTING, NO_MASKING);
695 /* ----------------------------------------------------------------------- */
696 /* draw things in front of player (active dynamite or dynabombs) */
697 /* ----------------------------------------------------------------------- */
699 if (IS_ACTIVE_BOMB(element))
701 graphic = el2img(element);
702 frame = getGraphicAnimationFrame(graphic, GfxFrame[jx][jy]);
704 if (game.emulation == EMU_SUPAPLEX)
705 DrawGraphic(sx, sy, IMG_SP_DISK_RED, frame);
707 DrawGraphicThruMask(sx, sy, graphic, frame);
710 if (player_is_moving && last_element == EL_EXPLOSION)
712 int stored = Store[last_jx][last_jy];
713 int graphic = (game.emulation != EMU_SUPAPLEX ? IMG_EXPLOSION :
714 stored == EL_SP_INFOTRON ? IMG_SP_EXPLOSION_INFOTRON :
716 int delay = (game.emulation == EMU_SUPAPLEX ? 3 : 2);
717 int phase = ExplodePhase[last_jx][last_jy] - 1;
718 int frame = getGraphicAnimationFrame(graphic, phase - delay);
721 DrawGraphicThruMask(SCREENX(last_jx), SCREENY(last_jy), graphic, frame);
724 /* ----------------------------------------------------------------------- */
725 /* draw elements that stay over the player */
726 /* ----------------------------------------------------------------------- */
728 /* handle the field the player is leaving ... */
729 if (player_is_moving && IS_OVER_PLAYER(last_element))
730 DrawLevelField(last_jx, last_jy);
732 /* ... and the field the player is entering */
733 if (IS_OVER_PLAYER(element))
734 DrawLevelField(jx, jy);
736 if (setup.direct_draw)
738 int dest_x = SX + SCREENX(MIN(jx, last_jx)) * TILEX;
739 int dest_y = SY + SCREENY(MIN(jy, last_jy)) * TILEY;
740 int x_size = TILEX * (1 + ABS(jx - last_jx));
741 int y_size = TILEY * (1 + ABS(jy - last_jy));
743 BlitBitmap(drawto_field, window,
744 dest_x, dest_y, x_size, y_size, dest_x, dest_y);
745 SetDrawtoField(DRAW_DIRECT);
748 MarkTileDirty(sx,sy);
751 void getGraphicSource(int graphic, int frame, Bitmap **bitmap, int *x, int *y)
753 Bitmap *src_bitmap = graphic_info[graphic].bitmap;
754 int offset_x = graphic_info[graphic].offset_x;
755 int offset_y = graphic_info[graphic].offset_y;
756 int src_x = graphic_info[graphic].src_x + frame * offset_x;
757 int src_y = graphic_info[graphic].src_y + frame * offset_y;
759 *bitmap = src_bitmap;
764 void DrawGraphic(int x, int y, int graphic, int frame)
767 if (!IN_SCR_FIELD(x, y))
769 printf("DrawGraphic(): x = %d, y = %d, graphic = %d\n", x, y, graphic);
770 printf("DrawGraphic(): This should never happen!\n");
775 DrawGraphicExt(drawto_field, FX + x * TILEX, FY + y * TILEY, graphic, frame);
780 void DrawOldGraphicExt(DrawBuffer *dst_bitmap, int x, int y, int graphic)
785 getOldGraphicSource(graphic, &src_bitmap, &src_x, &src_y);
786 BlitBitmap(src_bitmap, dst_bitmap, src_x, src_y, TILEX, TILEY, x, y);
790 void DrawGraphicExt(DrawBuffer *dst_bitmap, int x, int y, int graphic,
797 getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
799 Bitmap *src_bitmap = graphic_info[graphic].bitmap;
800 int src_x = graphic_info[graphic].src_x;
801 int src_y = graphic_info[graphic].src_y;
802 int offset_x = graphic_info[graphic].offset_x;
803 int offset_y = graphic_info[graphic].offset_y;
805 src_x += frame * offset_x;
806 src_y += frame * offset_y;
809 BlitBitmap(src_bitmap, dst_bitmap, src_x, src_y, TILEX, TILEY, x, y);
812 void DrawGraphicThruMask(int x, int y, int graphic, int frame)
815 if (!IN_SCR_FIELD(x, y))
817 printf("DrawGraphicThruMask(): x = %d,y = %d, graphic = %d\n",x,y,graphic);
818 printf("DrawGraphicThruMask(): This should never happen!\n");
823 DrawGraphicThruMaskExt(drawto_field, FX + x * TILEX, FY + y *TILEY, graphic,
828 void DrawGraphicThruMaskExt(DrawBuffer *d, int dest_x, int dest_y, int graphic,
836 getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
837 drawing_gc = src_bitmap->stored_clip_gc;
839 GC drawing_gc = src_bitmap->stored_clip_gc;
840 Bitmap *src_bitmap = graphic_info[graphic].bitmap;
841 int src_x = graphic_info[graphic].src_x;
842 int src_y = graphic_info[graphic].src_y;
843 int offset_x = graphic_info[graphic].offset_x;
844 int offset_y = graphic_info[graphic].offset_y;
846 src_x += frame * offset_x;
847 src_y += frame * offset_y;
851 SetClipOrigin(src_bitmap, drawing_gc, dest_x - src_x, dest_y - src_y);
852 BlitBitmapMasked(src_bitmap, d, src_x, src_y, TILEX, TILEY, dest_x, dest_y);
855 void DrawMiniGraphic(int x, int y, int graphic)
857 DrawMiniGraphicExt(drawto, SX + x * MINI_TILEX,SY + y * MINI_TILEY, graphic);
858 MarkTileDirty(x / 2, y / 2);
861 void getMiniGraphicSource(int graphic, Bitmap **bitmap, int *x, int *y)
863 Bitmap *src_bitmap = graphic_info[graphic].bitmap;
865 int mini_starty = src_bitmap->height * 2 / 3;
866 int src_x = mini_startx + graphic_info[graphic].src_x / 2;
867 int src_y = mini_starty + graphic_info[graphic].src_y / 2;
870 /* !!! not needed anymore, because of automatically created mini graphics */
871 if (src_x + MINI_TILEX > src_bitmap->width ||
872 src_y + MINI_TILEY > src_bitmap->height)
874 /* graphic of desired size seems not to be contained in this image;
875 dirty workaround: get it from the middle of the normal sized image */
877 printf("::: using dirty workaround for %d (%d, %d)\n",
878 graphic, src_bitmap->width, src_bitmap->height);
880 getGraphicSource(graphic, 0, &src_bitmap, &src_x, &src_y);
881 src_x += (TILEX / 2 - MINI_TILEX / 2);
882 src_y += (TILEY / 2 - MINI_TILEY / 2);
886 *bitmap = src_bitmap;
891 void DrawMiniGraphicExt(DrawBuffer *d, int x, int y, int graphic)
896 getMiniGraphicSource(graphic, &src_bitmap, &src_x, &src_y);
897 BlitBitmap(src_bitmap, d, src_x, src_y, MINI_TILEX, MINI_TILEY, x, y);
900 void DrawGraphicShifted(int x,int y, int dx,int dy, int graphic, int frame,
901 int cut_mode, int mask_mode)
910 int width = TILEX, height = TILEY;
916 DrawGraphic(x, y, graphic, frame);
920 if (dx || dy) /* shifted graphic */
922 if (x < BX1) /* object enters playfield from the left */
929 else if (x > BX2) /* object enters playfield from the right */
935 else if (x==BX1 && dx < 0) /* object leaves playfield to the left */
941 else if (x==BX2 && dx > 0) /* object leaves playfield to the right */
943 else if (dx) /* general horizontal movement */
944 MarkTileDirty(x + SIGN(dx), y);
946 if (y < BY1) /* object enters playfield from the top */
948 if (cut_mode==CUT_BELOW) /* object completely above top border */
956 else if (y > BY2) /* object enters playfield from the bottom */
962 else if (y==BY1 && dy < 0) /* object leaves playfield to the top */
968 else if (dy > 0 && cut_mode == CUT_ABOVE)
970 if (y == BY2) /* object completely above bottom border */
976 MarkTileDirty(x, y + 1);
977 } /* object leaves playfield to the bottom */
978 else if (dy > 0 && (y == BY2 || cut_mode == CUT_BELOW))
980 else if (dy) /* general vertical movement */
981 MarkTileDirty(x, y + SIGN(dy));
984 src_bitmap = graphic_info[graphic].bitmap;
985 src_x = graphic_info[graphic].src_x;
986 src_y = graphic_info[graphic].src_y;
987 offset_x = graphic_info[graphic].offset_x;
988 offset_y = graphic_info[graphic].offset_y;
990 drawing_gc = src_bitmap->stored_clip_gc;
992 src_x += frame * offset_x;
993 src_y += frame * offset_y;
998 dest_x = FX + x * TILEX + dx;
999 dest_y = FY + y * TILEY + dy;
1002 if (!IN_SCR_FIELD(x,y))
1004 printf("DrawGraphicShifted(): x = %d, y = %d, graphic = %d\n",x,y,graphic);
1005 printf("DrawGraphicShifted(): This should never happen!\n");
1010 if (mask_mode == USE_MASKING)
1012 SetClipOrigin(src_bitmap, drawing_gc, dest_x - src_x, dest_y - src_y);
1013 BlitBitmapMasked(src_bitmap, drawto_field, src_x, src_y, width, height,
1017 BlitBitmap(src_bitmap, drawto_field, src_x, src_y, width, height,
1023 void DrawGraphicShiftedThruMask(int x, int y, int dx, int dy, int graphic,
1024 int frame, int cut_mode)
1026 DrawGraphicShifted(x,y, dx,dy, graphic, frame, cut_mode, USE_MASKING);
1029 void DrawScreenElementExt(int x, int y, int dx, int dy, int element,
1030 int cut_mode, int mask_mode)
1032 int lx = LEVELX(x), ly = LEVELY(y);
1036 if (IN_LEV_FIELD(lx, ly))
1038 SetRandomAnimationValue(lx, ly);
1040 graphic = el_act_dir2img(element, GfxAction[lx][ly], MovDir[lx][ly]);
1041 frame = getGraphicAnimationFrame(graphic, GfxFrame[lx][ly]);
1043 else /* border element */
1045 graphic = el2img(element);
1046 frame = getGraphicAnimationFrame(graphic, -1);
1049 if (element == EL_WALL_GROWING)
1051 boolean left_stopped = FALSE, right_stopped = FALSE;
1053 if (!IN_LEV_FIELD(lx - 1, ly) || IS_MAUER(Feld[lx - 1][ly]))
1054 left_stopped = TRUE;
1055 if (!IN_LEV_FIELD(lx + 1, ly) || IS_MAUER(Feld[lx + 1][ly]))
1056 right_stopped = TRUE;
1058 if (left_stopped && right_stopped)
1060 else if (left_stopped)
1062 graphic = IMG_WALL_GROWING_ACTIVE_RIGHT;
1063 frame = graphic_info[graphic].anim_frames - 1;
1065 else if (right_stopped)
1067 graphic = IMG_WALL_GROWING_ACTIVE_LEFT;
1068 frame = graphic_info[graphic].anim_frames - 1;
1072 else if (IS_AMOEBOID(element) || element == EL_AMOEBA_DRIPPING)
1074 graphic = (element == EL_BD_AMOEBA ? IMG_BD_AMOEBA_PART1 :
1075 element == EL_AMOEBA_WET ? IMG_AMOEBA_WET_PART1 :
1076 element == EL_AMOEBA_DRY ? IMG_AMOEBA_DRY_PART1 :
1077 element == EL_AMOEBA_FULL ? IMG_AMOEBA_FULL_PART1 :
1078 IMG_AMOEBA_DEAD_PART1);
1080 graphic += (x + 2 * y + 4) % 4;
1085 if (IS_AMOEBOID(element) || element == EL_AMOEBA_DRIPPING)
1087 if (Feld[lx][ly] == EL_AMOEBA_DRIPPING)
1088 printf("---> %d -> %d / %d [%d]\n",
1089 element, graphic, frame, GfxRandom[lx][ly]);
1094 DrawGraphicShifted(x, y, dx, dy, graphic, frame, cut_mode, mask_mode);
1095 else if (mask_mode == USE_MASKING)
1096 DrawGraphicThruMask(x, y, graphic, frame);
1098 DrawGraphic(x, y, graphic, frame);
1101 void DrawLevelElementExt(int x, int y, int dx, int dy, int element,
1102 int cut_mode, int mask_mode)
1104 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1105 DrawScreenElementExt(SCREENX(x), SCREENY(y), dx, dy, element,
1106 cut_mode, mask_mode);
1109 void DrawScreenElementShifted(int x, int y, int dx, int dy, int element,
1112 DrawScreenElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
1115 void DrawLevelElementShifted(int x, int y, int dx, int dy, int element,
1118 DrawLevelElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
1122 void DrawOldScreenElementThruMask(int x, int y, int element)
1124 DrawOldScreenElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
1127 void DrawScreenElementThruMask(int x, int y, int element)
1129 DrawScreenElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
1133 void DrawLevelElementThruMask(int x, int y, int element)
1135 DrawLevelElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
1138 void DrawLevelFieldThruMask(int x, int y)
1140 DrawLevelElementExt(x, y, 0, 0, Feld[x][y], NO_CUTTING, USE_MASKING);
1143 void DrawCrumbledSand(int x, int y)
1147 int i, width, height, cx,cy;
1148 int lx = LEVELX(x), ly = LEVELY(y);
1149 int element, graphic;
1151 static int xy[4][2] =
1159 if (!IN_LEV_FIELD(lx, ly))
1162 element = Feld[lx][ly];
1164 if (element == EL_SAND ||
1165 element == EL_LANDMINE ||
1166 element == EL_TRAP ||
1167 element == EL_TRAP_ACTIVE)
1169 if (!IN_SCR_FIELD(x, y))
1172 graphic = IMG_SAND_CRUMBLED;
1174 src_bitmap = graphic_info[graphic].bitmap;
1175 src_x = graphic_info[graphic].src_x;
1176 src_y = graphic_info[graphic].src_y;
1182 lxx = lx + xy[i][0];
1183 lyy = ly + xy[i][1];
1184 if (!IN_LEV_FIELD(lxx, lyy))
1185 element = EL_STEELWALL;
1187 element = Feld[lxx][lyy];
1189 if (element == EL_SAND ||
1190 element == EL_LANDMINE ||
1191 element == EL_TRAP ||
1192 element == EL_TRAP_ACTIVE)
1195 if (i == 1 || i == 2)
1199 cx = (i == 2 ? TILEX - snip : 0);
1207 cy = (i == 3 ? TILEY - snip : 0);
1210 BlitBitmap(src_bitmap, drawto_field, src_x + cx, src_y + cy,
1211 width, height, FX + x * TILEX + cx, FY + y * TILEY + cy);
1214 MarkTileDirty(x, y);
1218 graphic = IMG_SAND_CRUMBLED;
1220 src_bitmap = graphic_info[graphic].bitmap;
1221 src_x = graphic_info[graphic].src_x;
1222 src_y = graphic_info[graphic].src_y;
1226 int xx, yy, lxx, lyy;
1230 lxx = lx + xy[i][0];
1231 lyy = ly + xy[i][1];
1233 if (!IN_LEV_FIELD(lxx, lyy) ||
1234 (Feld[lxx][lyy] != EL_SAND &&
1235 Feld[lxx][lyy] != EL_LANDMINE &&
1236 Feld[lxx][lyy] != EL_TRAP &&
1237 Feld[lxx][lyy] != EL_TRAP_ACTIVE) ||
1238 !IN_SCR_FIELD(xx, yy))
1241 if (i == 1 || i == 2)
1245 cx = (i == 1 ? TILEX - snip : 0);
1253 cy = (i==0 ? TILEY-snip : 0);
1256 BlitBitmap(src_bitmap, drawto_field, src_x + cx, src_y + cy,
1257 width, height, FX + xx * TILEX + cx, FY + yy * TILEY + cy);
1259 MarkTileDirty(xx, yy);
1264 static int getBorderElement(int x, int y)
1268 { EL_STEELWALL_TOPLEFT, EL_INVISIBLE_STEELWALL_TOPLEFT },
1269 { EL_STEELWALL_TOPRIGHT, EL_INVISIBLE_STEELWALL_TOPRIGHT },
1270 { EL_STEELWALL_BOTTOMLEFT, EL_INVISIBLE_STEELWALL_BOTTOMLEFT },
1271 { EL_STEELWALL_BOTTOMRIGHT, EL_INVISIBLE_STEELWALL_BOTTOMRIGHT },
1272 { EL_STEELWALL_VERTICAL, EL_INVISIBLE_STEELWALL_VERTICAL },
1273 { EL_STEELWALL_HORIZONTAL, EL_INVISIBLE_STEELWALL_HORIZONTAL },
1274 { EL_STEELWALL, EL_INVISIBLE_STEELWALL }
1276 int steel_type = (BorderElement == EL_STEELWALL ? 0 : 1);
1277 int steel_position = (x == -1 && y == -1 ? 0 :
1278 x == lev_fieldx && y == -1 ? 1 :
1279 x == -1 && y == lev_fieldy ? 2 :
1280 x == lev_fieldx && y == lev_fieldy ? 3 :
1281 x == -1 || x == lev_fieldx ? 4 :
1282 y == -1 || y == lev_fieldy ? 5 : 6);
1284 return border[steel_position][steel_type];
1287 void DrawScreenElement(int x, int y, int element)
1289 DrawScreenElementExt(x, y, 0, 0, element, NO_CUTTING, NO_MASKING);
1290 DrawCrumbledSand(x, y);
1293 void DrawLevelElement(int x, int y, int element)
1295 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1296 DrawScreenElement(SCREENX(x), SCREENY(y), element);
1299 void DrawScreenField(int x, int y)
1301 int lx = LEVELX(x), ly = LEVELY(y);
1302 int element, content;
1304 if (!IN_LEV_FIELD(lx, ly))
1306 if (lx < -1 || lx > lev_fieldx || ly < -1 || ly > lev_fieldy)
1309 element = getBorderElement(lx, ly);
1311 DrawScreenElement(x, y, element);
1315 element = Feld[lx][ly];
1316 content = Store[lx][ly];
1318 if (IS_MOVING(lx, ly))
1320 int horiz_move = (MovDir[lx][ly] == MV_LEFT || MovDir[lx][ly] == MV_RIGHT);
1321 boolean cut_mode = NO_CUTTING;
1323 if (element == EL_QUICKSAND_EMPTYING ||
1324 element == EL_MAGIC_WALL_EMPTYING ||
1325 element == EL_BD_MAGIC_WALL_EMPTYING ||
1326 element == EL_AMOEBA_DRIPPING)
1327 cut_mode = CUT_ABOVE;
1328 else if (element == EL_QUICKSAND_FILLING ||
1329 element == EL_MAGIC_WALL_FILLING ||
1330 element == EL_BD_MAGIC_WALL_FILLING)
1331 cut_mode = CUT_BELOW;
1333 if (cut_mode == CUT_ABOVE)
1334 DrawScreenElementShifted(x, y, 0, 0, element, NO_CUTTING);
1336 DrawScreenElement(x, y, EL_EMPTY);
1339 DrawScreenElementShifted(x, y, MovPos[lx][ly], 0, element, NO_CUTTING);
1340 else if (cut_mode == NO_CUTTING)
1341 DrawScreenElementShifted(x, y, 0, MovPos[lx][ly], element, cut_mode);
1343 DrawScreenElementShifted(x, y, 0, MovPos[lx][ly], content, cut_mode);
1345 if (content == EL_ACID)
1346 DrawLevelElementThruMask(lx, ly + 1, EL_ACID);
1348 else if (IS_BLOCKED(lx, ly))
1353 boolean cut_mode = NO_CUTTING;
1354 int element_old, content_old;
1356 Blocked2Moving(lx, ly, &oldx, &oldy);
1359 horiz_move = (MovDir[oldx][oldy] == MV_LEFT ||
1360 MovDir[oldx][oldy] == MV_RIGHT);
1362 element_old = Feld[oldx][oldy];
1363 content_old = Store[oldx][oldy];
1365 if (element_old == EL_QUICKSAND_EMPTYING ||
1366 element_old == EL_MAGIC_WALL_EMPTYING ||
1367 element_old == EL_BD_MAGIC_WALL_EMPTYING ||
1368 element_old == EL_AMOEBA_DRIPPING)
1369 cut_mode = CUT_ABOVE;
1371 DrawScreenElement(x, y, EL_EMPTY);
1374 DrawScreenElementShifted(sx, sy, MovPos[oldx][oldy], 0, element_old,
1376 else if (cut_mode == NO_CUTTING)
1377 DrawScreenElementShifted(sx, sy, 0, MovPos[oldx][oldy], element_old,
1380 DrawScreenElementShifted(sx, sy, 0, MovPos[oldx][oldy], content_old,
1383 else if (IS_DRAWABLE(element))
1384 DrawScreenElement(x, y, element);
1386 DrawScreenElement(x, y, EL_EMPTY);
1389 void DrawLevelField(int x, int y)
1391 if (IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1392 DrawScreenField(SCREENX(x), SCREENY(y));
1393 else if (IS_MOVING(x, y))
1397 Moving2Blocked(x, y, &newx, &newy);
1398 if (IN_SCR_FIELD(SCREENX(newx), SCREENY(newy)))
1399 DrawScreenField(SCREENX(newx), SCREENY(newy));
1401 else if (IS_BLOCKED(x, y))
1405 Blocked2Moving(x, y, &oldx, &oldy);
1406 if (IN_SCR_FIELD(SCREENX(oldx), SCREENY(oldy)))
1407 DrawScreenField(SCREENX(oldx), SCREENY(oldy));
1411 void DrawMiniElement(int x, int y, int element)
1415 graphic = el2edimg(element);
1416 DrawMiniGraphic(x, y, graphic);
1419 void DrawMiniElementOrWall(int sx, int sy, int scroll_x, int scroll_y)
1421 int x = sx + scroll_x, y = sy + scroll_y;
1423 if (x < -1 || x > lev_fieldx || y < -1 || y > lev_fieldy)
1424 DrawMiniElement(sx, sy, EL_EMPTY);
1425 else if (x > -1 && x < lev_fieldx && y > -1 && y < lev_fieldy)
1426 DrawMiniElement(sx, sy, Feld[x][y]);
1428 DrawMiniGraphic(sx, sy, el2edimg(getBorderElement(x, y)));
1431 void getMicroGraphicSource(int graphic, Bitmap **bitmap, int *x, int *y)
1433 Bitmap *src_bitmap = graphic_info[graphic].bitmap;
1434 int mini_startx = src_bitmap->width * 3 / 4;
1435 int mini_starty = src_bitmap->height * 2 / 3;
1436 int src_x = mini_startx + graphic_info[graphic].src_x / 8;
1437 int src_y = mini_starty + graphic_info[graphic].src_y / 8;
1439 if (src_x + MICRO_TILEX > src_bitmap->width ||
1440 src_y + MICRO_TILEY > src_bitmap->height)
1442 /* graphic of desired size seems not to be contained in this image;
1443 dirty workaround: get it from the middle of the normal sized image */
1445 getGraphicSource(graphic, 0, &src_bitmap, &src_x, &src_y);
1446 src_x += (TILEX / 2 - MICRO_TILEX / 2);
1447 src_y += (TILEY / 2 - MICRO_TILEY / 2);
1450 *bitmap = src_bitmap;
1455 void DrawMicroElement(int xpos, int ypos, int element)
1459 int graphic = el2preimg(element);
1461 getMicroGraphicSource(graphic, &src_bitmap, &src_x, &src_y);
1462 BlitBitmap(src_bitmap, drawto, src_x, src_y, MICRO_TILEX, MICRO_TILEY,
1470 SetDrawBackgroundMask(REDRAW_NONE);
1473 for(x=BX1; x<=BX2; x++)
1474 for(y=BY1; y<=BY2; y++)
1475 DrawScreenField(x, y);
1477 redraw_mask |= REDRAW_FIELD;
1480 void DrawMiniLevel(int size_x, int size_y, int scroll_x, int scroll_y)
1484 for(x=0; x<size_x; x++)
1485 for(y=0; y<size_y; y++)
1486 DrawMiniElementOrWall(x, y, scroll_x, scroll_y);
1488 redraw_mask |= REDRAW_FIELD;
1491 static void DrawMicroLevelExt(int xpos, int ypos, int from_x, int from_y)
1495 DrawBackground(xpos, ypos, MICROLEV_XSIZE, MICROLEV_YSIZE);
1497 if (lev_fieldx < STD_LEV_FIELDX)
1498 xpos += (STD_LEV_FIELDX - lev_fieldx) / 2 * MICRO_TILEX;
1499 if (lev_fieldy < STD_LEV_FIELDY)
1500 ypos += (STD_LEV_FIELDY - lev_fieldy) / 2 * MICRO_TILEY;
1502 xpos += MICRO_TILEX;
1503 ypos += MICRO_TILEY;
1505 for(x=-1; x<=STD_LEV_FIELDX; x++)
1507 for(y=-1; y<=STD_LEV_FIELDY; y++)
1509 int lx = from_x + x, ly = from_y + y;
1511 if (lx >= 0 && lx < lev_fieldx && ly >= 0 && ly < lev_fieldy)
1512 DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
1514 else if (lx >= -1 && lx < lev_fieldx+1 && ly >= -1 && ly < lev_fieldy+1
1515 && BorderElement != EL_EMPTY)
1516 DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
1517 getBorderElement(lx, ly));
1521 redraw_mask |= REDRAW_MICROLEVEL;
1524 #define MICROLABEL_EMPTY 0
1525 #define MICROLABEL_LEVEL_NAME 1
1526 #define MICROLABEL_CREATED_BY 2
1527 #define MICROLABEL_LEVEL_AUTHOR 3
1528 #define MICROLABEL_IMPORTED_FROM 4
1529 #define MICROLABEL_LEVEL_IMPORT_INFO 5
1531 static void DrawMicroLevelLabelExt(int mode)
1533 char label_text[MAX_OUTPUT_LINESIZE + 1];
1534 int max_len_label_text = SXSIZE / getFontWidth(FONT_SPECIAL_GAME);
1536 DrawBackground(SX, MICROLABEL_YPOS, SXSIZE,getFontHeight(FONT_SPECIAL_GAME));
1538 strncpy(label_text, (mode == MICROLABEL_LEVEL_NAME ? level.name :
1539 mode == MICROLABEL_CREATED_BY ? "created by" :
1540 mode == MICROLABEL_LEVEL_AUTHOR ? level.author :
1541 mode == MICROLABEL_IMPORTED_FROM ? "imported from" :
1542 mode == MICROLABEL_LEVEL_IMPORT_INFO ?
1543 leveldir_current->imported_from : ""),
1544 max_len_label_text);
1545 label_text[max_len_label_text] = '\0';
1547 if (strlen(label_text) > 0)
1549 int text_width = strlen(label_text) * getFontWidth(FONT_SPECIAL_GAME);
1550 int lxpos = SX + (SXSIZE - text_width) / 2;
1551 int lypos = MICROLABEL_YPOS;
1553 DrawText(lxpos, lypos, label_text, FONT_SPECIAL_GAME);
1556 redraw_mask |= REDRAW_MICROLEVEL;
1559 void DrawMicroLevel(int xpos, int ypos, boolean restart)
1561 static unsigned long scroll_delay = 0;
1562 static unsigned long label_delay = 0;
1563 static int from_x, from_y, scroll_direction;
1564 static int label_state, label_counter;
1568 from_x = from_y = 0;
1569 scroll_direction = MV_RIGHT;
1573 DrawMicroLevelExt(xpos, ypos, from_x, from_y);
1574 DrawMicroLevelLabelExt(label_state);
1576 /* initialize delay counters */
1577 DelayReached(&scroll_delay, 0);
1578 DelayReached(&label_delay, 0);
1583 /* scroll micro level, if needed */
1584 if ((lev_fieldx > STD_LEV_FIELDX || lev_fieldy > STD_LEV_FIELDY) &&
1585 DelayReached(&scroll_delay, MICROLEVEL_SCROLL_DELAY))
1587 switch (scroll_direction)
1593 scroll_direction = MV_UP;
1597 if (from_x < lev_fieldx - STD_LEV_FIELDX)
1600 scroll_direction = MV_DOWN;
1607 scroll_direction = MV_RIGHT;
1611 if (from_y < lev_fieldy - STD_LEV_FIELDY)
1614 scroll_direction = MV_LEFT;
1621 DrawMicroLevelExt(xpos, ypos, from_x, from_y);
1624 /* redraw micro level label, if needed */
1625 if (strcmp(level.name, NAMELESS_LEVEL_NAME) != 0 &&
1626 strcmp(level.author, ANONYMOUS_NAME) != 0 &&
1627 strcmp(level.author, leveldir_current->name) != 0 &&
1628 DelayReached(&label_delay, MICROLEVEL_LABEL_DELAY))
1630 int max_label_counter = 23;
1632 if (leveldir_current->imported_from != NULL)
1633 max_label_counter += 14;
1635 label_counter = (label_counter + 1) % max_label_counter;
1636 label_state = (label_counter >= 0 && label_counter <= 7 ?
1637 MICROLABEL_LEVEL_NAME :
1638 label_counter >= 9 && label_counter <= 12 ?
1639 MICROLABEL_CREATED_BY :
1640 label_counter >= 14 && label_counter <= 21 ?
1641 MICROLABEL_LEVEL_AUTHOR :
1642 label_counter >= 23 && label_counter <= 26 ?
1643 MICROLABEL_IMPORTED_FROM :
1644 label_counter >= 28 && label_counter <= 35 ?
1645 MICROLABEL_LEVEL_IMPORT_INFO : MICROLABEL_EMPTY);
1646 DrawMicroLevelLabelExt(label_state);
1650 int REQ_in_range(int x, int y)
1652 if (y > DY+249 && y < DY+278)
1654 if (x > DX+1 && x < DX+48)
1656 else if (x > DX+51 && x < DX+98)
1662 #define MAX_REQUEST_LINES 13
1663 #define MAX_REQUEST_LINE_LEN 7
1665 boolean Request(char *text, unsigned int req_state)
1667 int mx, my, ty, result = -1;
1668 unsigned int old_door_state;
1670 #if defined(PLATFORM_UNIX)
1671 /* pause network game while waiting for request to answer */
1672 if (options.network &&
1673 game_status == PLAYING &&
1674 req_state & REQUEST_WAIT_FOR)
1675 SendToServer_PausePlaying();
1678 old_door_state = GetDoorState();
1682 CloseDoor(DOOR_CLOSE_1);
1684 /* save old door content */
1685 BlitBitmap(bitmap_db_door, bitmap_db_door,
1686 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE,
1687 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1);
1689 SetDrawBackgroundMask(REDRAW_FIELD | REDRAW_DOOR_1);
1691 /* clear door drawing field */
1692 DrawBackground(DX, DY, DXSIZE, DYSIZE);
1694 /* write text for request */
1695 for(ty=0; ty < MAX_REQUEST_LINES; ty++)
1697 char text_line[MAX_REQUEST_LINE_LEN + 1];
1703 for(tl=0,tx=0; tx < MAX_REQUEST_LINE_LEN; tl++,tx++)
1706 if (!tc || tc == ' ')
1717 strncpy(text_line, text, tl);
1720 DrawText(DX + 50 - (tl * 14)/2, DY + 8 + ty * 16,
1721 text_line, FONT_DEFAULT_SMALL);
1723 text += tl + (tc == ' ' ? 1 : 0);
1726 if (req_state & REQ_ASK)
1728 MapGadget(tool_gadget[TOOL_CTRL_ID_YES]);
1729 MapGadget(tool_gadget[TOOL_CTRL_ID_NO]);
1731 else if (req_state & REQ_CONFIRM)
1733 MapGadget(tool_gadget[TOOL_CTRL_ID_CONFIRM]);
1735 else if (req_state & REQ_PLAYER)
1737 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_1]);
1738 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_2]);
1739 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_3]);
1740 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_4]);
1743 /* copy request gadgets to door backbuffer */
1744 BlitBitmap(drawto, bitmap_db_door,
1745 DX, DY, DXSIZE, DYSIZE,
1746 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
1748 OpenDoor(DOOR_OPEN_1);
1754 if (!(req_state & REQUEST_WAIT_FOR))
1756 SetDrawBackgroundMask(REDRAW_FIELD);
1761 if (game_status != MAINMENU)
1764 button_status = MB_RELEASED;
1766 request_gadget_id = -1;
1768 SetDrawBackgroundMask(REDRAW_FIELD | REDRAW_DOOR_1);
1780 case EVENT_BUTTONPRESS:
1781 case EVENT_BUTTONRELEASE:
1782 case EVENT_MOTIONNOTIFY:
1784 if (event.type == EVENT_MOTIONNOTIFY)
1786 if (!PointerInWindow(window))
1787 continue; /* window and pointer are on different screens */
1792 motion_status = TRUE;
1793 mx = ((MotionEvent *) &event)->x;
1794 my = ((MotionEvent *) &event)->y;
1798 motion_status = FALSE;
1799 mx = ((ButtonEvent *) &event)->x;
1800 my = ((ButtonEvent *) &event)->y;
1801 if (event.type == EVENT_BUTTONPRESS)
1802 button_status = ((ButtonEvent *) &event)->button;
1804 button_status = MB_RELEASED;
1807 /* this sets 'request_gadget_id' */
1808 HandleGadgets(mx, my, button_status);
1810 switch(request_gadget_id)
1812 case TOOL_CTRL_ID_YES:
1815 case TOOL_CTRL_ID_NO:
1818 case TOOL_CTRL_ID_CONFIRM:
1819 result = TRUE | FALSE;
1822 case TOOL_CTRL_ID_PLAYER_1:
1825 case TOOL_CTRL_ID_PLAYER_2:
1828 case TOOL_CTRL_ID_PLAYER_3:
1831 case TOOL_CTRL_ID_PLAYER_4:
1842 case EVENT_KEYPRESS:
1843 switch(GetEventKey((KeyEvent *)&event, TRUE))
1856 if (req_state & REQ_PLAYER)
1860 case EVENT_KEYRELEASE:
1861 ClearPlayerAction();
1865 HandleOtherEvents(&event);
1869 else if (AnyJoystickButton() == JOY_BUTTON_NEW_PRESSED)
1871 int joy = AnyJoystick();
1873 if (joy & JOY_BUTTON_1)
1875 else if (joy & JOY_BUTTON_2)
1881 /* don't eat all CPU time */
1885 if (game_status != MAINMENU)
1890 if (!(req_state & REQ_STAY_OPEN))
1892 CloseDoor(DOOR_CLOSE_1);
1894 if (!(req_state & REQ_STAY_CLOSED) && (old_door_state & DOOR_OPEN_1))
1896 BlitBitmap(bitmap_db_door, bitmap_db_door,
1897 DOOR_GFX_PAGEX2,DOOR_GFX_PAGEY1, DXSIZE,DYSIZE,
1898 DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY1);
1899 OpenDoor(DOOR_OPEN_1);
1905 SetDrawBackgroundMask(REDRAW_FIELD);
1907 #if defined(PLATFORM_UNIX)
1908 /* continue network game after request */
1909 if (options.network &&
1910 game_status == PLAYING &&
1911 req_state & REQUEST_WAIT_FOR)
1912 SendToServer_ContinuePlaying();
1918 unsigned int OpenDoor(unsigned int door_state)
1920 unsigned int new_door_state;
1922 if (door_state & DOOR_COPY_BACK)
1924 BlitBitmap(bitmap_db_door, bitmap_db_door,
1925 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE + VYSIZE,
1926 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
1927 door_state &= ~DOOR_COPY_BACK;
1930 new_door_state = MoveDoor(door_state);
1932 return(new_door_state);
1935 unsigned int CloseDoor(unsigned int door_state)
1937 unsigned int new_door_state;
1939 BlitBitmap(backbuffer, bitmap_db_door,
1940 DX, DY, DXSIZE, DYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
1941 BlitBitmap(backbuffer, bitmap_db_door,
1942 VX, VY, VXSIZE, VYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2);
1944 new_door_state = MoveDoor(door_state);
1946 return(new_door_state);
1949 unsigned int GetDoorState()
1951 return MoveDoor(DOOR_GET_STATE);
1954 unsigned int SetDoorState(unsigned int door_state)
1956 return MoveDoor(door_state | DOOR_SET_STATE);
1959 unsigned int MoveDoor(unsigned int door_state)
1961 static int door1 = DOOR_OPEN_1;
1962 static int door2 = DOOR_CLOSE_2;
1963 static unsigned long door_delay = 0;
1964 int x, start, stepsize = 2;
1965 unsigned long door_delay_value = stepsize * 5;
1967 if (door_state == DOOR_GET_STATE)
1968 return(door1 | door2);
1970 if (door_state & DOOR_SET_STATE)
1972 if (door_state & DOOR_ACTION_1)
1973 door1 = door_state & DOOR_ACTION_1;
1974 if (door_state & DOOR_ACTION_2)
1975 door2 = door_state & DOOR_ACTION_2;
1977 return(door1 | door2);
1980 if (door1 == DOOR_OPEN_1 && door_state & DOOR_OPEN_1)
1981 door_state &= ~DOOR_OPEN_1;
1982 else if (door1 == DOOR_CLOSE_1 && door_state & DOOR_CLOSE_1)
1983 door_state &= ~DOOR_CLOSE_1;
1984 if (door2 == DOOR_OPEN_2 && door_state & DOOR_OPEN_2)
1985 door_state &= ~DOOR_OPEN_2;
1986 else if (door2 == DOOR_CLOSE_2 && door_state & DOOR_CLOSE_2)
1987 door_state &= ~DOOR_CLOSE_2;
1989 if (setup.quick_doors)
1992 door_delay_value = 0;
1994 StopSound(SND_MENU_DOOR_OPENING);
1995 StopSound(SND_MENU_DOOR_CLOSING);
1998 if (global.autoplay_leveldir)
2000 door_state |= DOOR_NO_DELAY;
2001 door_state &= ~DOOR_CLOSE_ALL;
2004 if (door_state & DOOR_ACTION)
2006 if (!(door_state & DOOR_NO_DELAY))
2008 /* opening door sound has priority over simultaneously closing door */
2009 if (door_state & (DOOR_OPEN_1 | DOOR_OPEN_2))
2010 PlaySoundStereo(SND_MENU_DOOR_OPENING, SOUND_MAX_RIGHT);
2011 else if (door_state & (DOOR_CLOSE_1 | DOOR_CLOSE_2))
2012 PlaySoundStereo(SND_MENU_DOOR_CLOSING, SOUND_MAX_RIGHT);
2015 start = ((door_state & DOOR_NO_DELAY) ? DXSIZE : 0);
2017 for(x=start; x<=DXSIZE; x+=stepsize)
2019 Bitmap *bitmap = graphic_info[IMG_GLOBAL_DOOR].bitmap;
2020 GC gc = bitmap->stored_clip_gc;
2022 if (!(door_state & DOOR_NO_DELAY))
2023 WaitUntilDelayReached(&door_delay, door_delay_value);
2025 if (door_state & DOOR_ACTION_1)
2027 int i = (door_state & DOOR_OPEN_1 ? DXSIZE-x : x);
2028 int j = (DXSIZE - i) / 3;
2030 BlitBitmap(bitmap_db_door, drawto,
2031 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1 + i/2,
2032 DXSIZE,DYSIZE - i/2, DX, DY);
2034 ClearRectangle(drawto, DX, DY + DYSIZE - i/2, DXSIZE,i/2);
2036 SetClipOrigin(bitmap, gc, DX - i, (DY + j) - DOOR_GFX_PAGEY1);
2037 BlitBitmapMasked(bitmap, drawto,
2038 DXSIZE, DOOR_GFX_PAGEY1, i, 77,
2039 DX + DXSIZE - i, DY + j);
2040 BlitBitmapMasked(bitmap, drawto,
2041 DXSIZE, DOOR_GFX_PAGEY1 + 140, i, 63,
2042 DX + DXSIZE - i, DY + 140 + j);
2043 SetClipOrigin(bitmap, gc, DX - DXSIZE + i, DY - (DOOR_GFX_PAGEY1 + j));
2044 BlitBitmapMasked(bitmap, drawto,
2045 DXSIZE - i, DOOR_GFX_PAGEY1 + j, i, 77 - j,
2047 BlitBitmapMasked(bitmap, drawto,
2048 DXSIZE-i, DOOR_GFX_PAGEY1 + 140, i, 63,
2051 BlitBitmapMasked(bitmap, drawto,
2052 DXSIZE - i, DOOR_GFX_PAGEY1 + 77, i, 63,
2054 BlitBitmapMasked(bitmap, drawto,
2055 DXSIZE - i, DOOR_GFX_PAGEY1 + 203, i, 77,
2057 SetClipOrigin(bitmap, gc, DX - i, (DY + j) - DOOR_GFX_PAGEY1);
2058 BlitBitmapMasked(bitmap, drawto,
2059 DXSIZE, DOOR_GFX_PAGEY1 + 77, i, 63,
2060 DX + DXSIZE - i, DY + 77 + j);
2061 BlitBitmapMasked(bitmap, drawto,
2062 DXSIZE, DOOR_GFX_PAGEY1 + 203, i, 77 - j,
2063 DX + DXSIZE - i, DY + 203 + j);
2065 redraw_mask |= REDRAW_DOOR_1;
2068 if (door_state & DOOR_ACTION_2)
2070 int i = (door_state & DOOR_OPEN_2 ? VXSIZE - x : x);
2071 int j = (VXSIZE - i) / 3;
2073 BlitBitmap(bitmap_db_door, drawto,
2074 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2 + i/2,
2075 VXSIZE, VYSIZE - i/2, VX, VY);
2077 ClearRectangle(drawto, VX, VY + VYSIZE-i/2, VXSIZE, i/2);
2079 SetClipOrigin(bitmap, gc, VX - i, (VY + j) - DOOR_GFX_PAGEY2);
2080 BlitBitmapMasked(bitmap, drawto,
2081 VXSIZE, DOOR_GFX_PAGEY2, i, VYSIZE / 2,
2082 VX + VXSIZE-i, VY+j);
2083 SetClipOrigin(bitmap, gc,
2084 VX - VXSIZE + i, VY - (DOOR_GFX_PAGEY2 + j));
2085 BlitBitmapMasked(bitmap, drawto,
2086 VXSIZE - i, DOOR_GFX_PAGEY2 + j, i, VYSIZE / 2 - j,
2089 BlitBitmapMasked(bitmap, drawto,
2090 VXSIZE - i, DOOR_GFX_PAGEY2 + VYSIZE / 2,
2091 i, VYSIZE / 2, VX, VY + VYSIZE / 2 - j);
2092 SetClipOrigin(bitmap, gc, VX - i, (VY + j) - DOOR_GFX_PAGEY2);
2093 BlitBitmapMasked(bitmap, drawto,
2094 VXSIZE, DOOR_GFX_PAGEY2 + VYSIZE / 2,
2096 VX + VXSIZE - i, VY + VYSIZE / 2 + j);
2098 redraw_mask |= REDRAW_DOOR_2;
2103 if (game_status == MAINMENU)
2108 if (setup.quick_doors)
2110 StopSound(SND_MENU_DOOR_OPENING);
2111 StopSound(SND_MENU_DOOR_CLOSING);
2114 if (door_state & DOOR_ACTION_1)
2115 door1 = door_state & DOOR_ACTION_1;
2116 if (door_state & DOOR_ACTION_2)
2117 door2 = door_state & DOOR_ACTION_2;
2119 return (door1 | door2);
2122 void DrawSpecialEditorDoor()
2124 /* draw bigger toolbox window */
2125 BlitBitmap(graphic_info[IMG_GLOBAL_DOOR].bitmap, drawto,
2126 DOOR_GFX_PAGEX7, 0, EXSIZE + 8, 8,
2128 BlitBitmap(graphic_info[IMG_GLOBAL_BORDER].bitmap, drawto,
2129 EX - 4, VY - 4, EXSIZE + 8, EYSIZE - VYSIZE + 4,
2132 redraw_mask |= REDRAW_ALL;
2135 void UndrawSpecialEditorDoor()
2137 /* draw normal tape recorder window */
2138 BlitBitmap(graphic_info[IMG_GLOBAL_BORDER].bitmap, drawto,
2139 EX - 4, EY - 12, EXSIZE + 8, EYSIZE - VYSIZE + 12,
2142 redraw_mask |= REDRAW_ALL;
2146 int ReadPixel(DrawBuffer *bitmap, int x, int y)
2148 XImage *pixel_image;
2149 unsigned long pixel_value;
2151 pixel_image = XGetImage(display, bitmap->drawable,
2152 x, y, 1, 1, AllPlanes, ZPixmap);
2153 pixel_value = XGetPixel(pixel_image, 0, 0);
2155 XDestroyImage(pixel_image);
2161 /* ---------- new tool button stuff ---------------------------------------- */
2163 /* graphic position values for tool buttons */
2164 #define TOOL_BUTTON_YES_XPOS 2
2165 #define TOOL_BUTTON_YES_YPOS 250
2166 #define TOOL_BUTTON_YES_GFX_YPOS 0
2167 #define TOOL_BUTTON_YES_XSIZE 46
2168 #define TOOL_BUTTON_YES_YSIZE 28
2169 #define TOOL_BUTTON_NO_XPOS 52
2170 #define TOOL_BUTTON_NO_YPOS TOOL_BUTTON_YES_YPOS
2171 #define TOOL_BUTTON_NO_GFX_YPOS TOOL_BUTTON_YES_GFX_YPOS
2172 #define TOOL_BUTTON_NO_XSIZE TOOL_BUTTON_YES_XSIZE
2173 #define TOOL_BUTTON_NO_YSIZE TOOL_BUTTON_YES_YSIZE
2174 #define TOOL_BUTTON_CONFIRM_XPOS TOOL_BUTTON_YES_XPOS
2175 #define TOOL_BUTTON_CONFIRM_YPOS TOOL_BUTTON_YES_YPOS
2176 #define TOOL_BUTTON_CONFIRM_GFX_YPOS 30
2177 #define TOOL_BUTTON_CONFIRM_XSIZE 96
2178 #define TOOL_BUTTON_CONFIRM_YSIZE TOOL_BUTTON_YES_YSIZE
2179 #define TOOL_BUTTON_PLAYER_XSIZE 30
2180 #define TOOL_BUTTON_PLAYER_YSIZE 30
2181 #define TOOL_BUTTON_PLAYER_GFX_XPOS 5
2182 #define TOOL_BUTTON_PLAYER_GFX_YPOS 185
2183 #define TOOL_BUTTON_PLAYER_XPOS (5 + TOOL_BUTTON_PLAYER_XSIZE / 2)
2184 #define TOOL_BUTTON_PLAYER_YPOS (215 - TOOL_BUTTON_PLAYER_YSIZE / 2)
2185 #define TOOL_BUTTON_PLAYER1_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2186 + 0 * TOOL_BUTTON_PLAYER_XSIZE)
2187 #define TOOL_BUTTON_PLAYER2_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2188 + 1 * TOOL_BUTTON_PLAYER_XSIZE)
2189 #define TOOL_BUTTON_PLAYER3_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2190 + 0 * TOOL_BUTTON_PLAYER_XSIZE)
2191 #define TOOL_BUTTON_PLAYER4_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2192 + 1 * TOOL_BUTTON_PLAYER_XSIZE)
2193 #define TOOL_BUTTON_PLAYER1_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2194 + 0 * TOOL_BUTTON_PLAYER_YSIZE)
2195 #define TOOL_BUTTON_PLAYER2_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2196 + 0 * TOOL_BUTTON_PLAYER_YSIZE)
2197 #define TOOL_BUTTON_PLAYER3_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2198 + 1 * TOOL_BUTTON_PLAYER_YSIZE)
2199 #define TOOL_BUTTON_PLAYER4_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2200 + 1 * TOOL_BUTTON_PLAYER_YSIZE)
2209 } toolbutton_info[NUM_TOOL_BUTTONS] =
2212 TOOL_BUTTON_YES_XPOS, TOOL_BUTTON_YES_GFX_YPOS,
2213 TOOL_BUTTON_YES_XPOS, TOOL_BUTTON_YES_YPOS,
2214 TOOL_BUTTON_YES_XSIZE, TOOL_BUTTON_YES_YSIZE,
2219 TOOL_BUTTON_NO_XPOS, TOOL_BUTTON_NO_GFX_YPOS,
2220 TOOL_BUTTON_NO_XPOS, TOOL_BUTTON_NO_YPOS,
2221 TOOL_BUTTON_NO_XSIZE, TOOL_BUTTON_NO_YSIZE,
2226 TOOL_BUTTON_CONFIRM_XPOS, TOOL_BUTTON_CONFIRM_GFX_YPOS,
2227 TOOL_BUTTON_CONFIRM_XPOS, TOOL_BUTTON_CONFIRM_YPOS,
2228 TOOL_BUTTON_CONFIRM_XSIZE, TOOL_BUTTON_CONFIRM_YSIZE,
2229 TOOL_CTRL_ID_CONFIRM,
2233 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2234 TOOL_BUTTON_PLAYER1_XPOS, TOOL_BUTTON_PLAYER1_YPOS,
2235 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2236 TOOL_CTRL_ID_PLAYER_1,
2240 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2241 TOOL_BUTTON_PLAYER2_XPOS, TOOL_BUTTON_PLAYER2_YPOS,
2242 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2243 TOOL_CTRL_ID_PLAYER_2,
2247 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2248 TOOL_BUTTON_PLAYER3_XPOS, TOOL_BUTTON_PLAYER3_YPOS,
2249 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2250 TOOL_CTRL_ID_PLAYER_3,
2254 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2255 TOOL_BUTTON_PLAYER4_XPOS, TOOL_BUTTON_PLAYER4_YPOS,
2256 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2257 TOOL_CTRL_ID_PLAYER_4,
2262 void CreateToolButtons()
2266 for (i=0; i<NUM_TOOL_BUTTONS; i++)
2268 Bitmap *gd_bitmap = graphic_info[IMG_GLOBAL_DOOR].bitmap;
2269 Bitmap *deco_bitmap = None;
2270 int deco_x = 0, deco_y = 0, deco_xpos = 0, deco_ypos = 0;
2271 struct GadgetInfo *gi;
2272 unsigned long event_mask;
2273 int gd_xoffset, gd_yoffset;
2274 int gd_x1, gd_x2, gd_y;
2277 event_mask = GD_EVENT_RELEASED;
2279 gd_xoffset = toolbutton_info[i].xpos;
2280 gd_yoffset = toolbutton_info[i].ypos;
2281 gd_x1 = DOOR_GFX_PAGEX4 + gd_xoffset;
2282 gd_x2 = DOOR_GFX_PAGEX3 + gd_xoffset;
2283 gd_y = DOOR_GFX_PAGEY1 + gd_yoffset;
2285 if (id >= TOOL_CTRL_ID_PLAYER_1 && id <= TOOL_CTRL_ID_PLAYER_4)
2287 int player_nr = id - TOOL_CTRL_ID_PLAYER_1;
2289 getMiniGraphicSource(PLAYER_NR_GFX(IMG_PLAYER1, player_nr),
2290 &deco_bitmap, &deco_x, &deco_y);
2291 deco_xpos = (toolbutton_info[i].width - MINI_TILEX) / 2;
2292 deco_ypos = (toolbutton_info[i].height - MINI_TILEY) / 2;
2295 gi = CreateGadget(GDI_CUSTOM_ID, id,
2296 GDI_INFO_TEXT, toolbutton_info[i].infotext,
2297 GDI_X, DX + toolbutton_info[i].x,
2298 GDI_Y, DY + toolbutton_info[i].y,
2299 GDI_WIDTH, toolbutton_info[i].width,
2300 GDI_HEIGHT, toolbutton_info[i].height,
2301 GDI_TYPE, GD_TYPE_NORMAL_BUTTON,
2302 GDI_STATE, GD_BUTTON_UNPRESSED,
2303 GDI_DESIGN_UNPRESSED, gd_bitmap, gd_x1, gd_y,
2304 GDI_DESIGN_PRESSED, gd_bitmap, gd_x2, gd_y,
2305 GDI_DECORATION_DESIGN, deco_bitmap, deco_x, deco_y,
2306 GDI_DECORATION_POSITION, deco_xpos, deco_ypos,
2307 GDI_DECORATION_SIZE, MINI_TILEX, MINI_TILEY,
2308 GDI_DECORATION_SHIFTING, 1, 1,
2309 GDI_EVENT_MASK, event_mask,
2310 GDI_CALLBACK_ACTION, HandleToolButtons,
2314 Error(ERR_EXIT, "cannot create gadget");
2316 tool_gadget[id] = gi;
2320 void FreeToolButtons()
2324 for (i=0; i<NUM_TOOL_BUTTONS; i++)
2325 FreeGadget(tool_gadget[i]);
2328 static void UnmapToolButtons()
2332 for (i=0; i<NUM_TOOL_BUTTONS; i++)
2333 UnmapGadget(tool_gadget[i]);
2336 static void HandleToolButtons(struct GadgetInfo *gi)
2338 request_gadget_id = gi->custom_id;
2341 int get_next_element(int element)
2345 case EL_QUICKSAND_FILLING: return EL_QUICKSAND_FULL;
2346 case EL_QUICKSAND_EMPTYING: return EL_QUICKSAND_EMPTY;
2347 case EL_MAGIC_WALL_FILLING: return EL_MAGIC_WALL_FULL;
2348 case EL_MAGIC_WALL_EMPTYING: return EL_MAGIC_WALL_ACTIVE;
2349 case EL_BD_MAGIC_WALL_FILLING: return EL_BD_MAGIC_WALL_FULL;
2350 case EL_BD_MAGIC_WALL_EMPTYING: return EL_BD_MAGIC_WALL_ACTIVE;
2351 case EL_AMOEBA_DRIPPING: return EL_AMOEBA_WET;
2353 default: return element;
2357 int el_act_dir2img(int element, int action, int direction)
2359 direction = MV_DIR_BIT(direction);
2361 return element_info[element].direction_graphic[action][direction];
2364 int el_act2img(int element, int action)
2366 return element_info[element].graphic[action];
2369 int el_dir2img(int element, int direction)
2371 return el_act_dir2img(element, ACTION_DEFAULT, direction);
2374 int el2img(int element)
2376 return element_info[element].graphic[ACTION_DEFAULT];
2379 int el2edimg(int element)
2381 return element_info[element].special_graphic[GFX_SPECIAL_ARG_EDITOR];
2384 int el2preimg(int element)
2386 return element_info[element].special_graphic[GFX_SPECIAL_ARG_PREVIEW];