1 /***********************************************************
2 * Rocks'n'Diamonds -- McDuffin Strikes Back! *
3 *----------------------------------------------------------*
4 * (c) 1995-98 Artsoft Entertainment *
8 * phone: ++49 +521 290471 *
9 * email: aeglos@valinor.owl.de *
10 *----------------------------------------------------------*
12 ***********************************************************/
17 #include <machine/joystick.h>
31 extern boolean wait_for_vsync;
34 /* tool button identifiers */
35 #define TOOL_CTRL_ID_YES 0
36 #define TOOL_CTRL_ID_NO 1
37 #define TOOL_CTRL_ID_CONFIRM 2
38 #define TOOL_CTRL_ID_PLAYER_1 3
39 #define TOOL_CTRL_ID_PLAYER_2 4
40 #define TOOL_CTRL_ID_PLAYER_3 5
41 #define TOOL_CTRL_ID_PLAYER_4 6
43 #define NUM_TOOL_BUTTONS 7
45 /* forward declaration for internal use */
46 static void UnmapToolButtons();
47 static void HandleToolButtons(struct GadgetInfo *);
49 static struct GadgetInfo *tool_gadget[NUM_TOOL_BUTTONS];
50 static int request_gadget_id = -1;
52 void SetDrawtoField(int mode)
54 if (mode == DRAW_BUFFERED && setup.soft_scrolling)
65 drawto_field = fieldbuffer;
67 else /* DRAW_DIRECT, DRAW_BACKBUFFER */
78 drawto_field = (mode == DRAW_DIRECT ? window : backbuffer);
85 Drawable buffer = (drawto_field == window ? backbuffer : drawto_field);
87 if (setup.direct_draw && game_status == PLAYING)
88 redraw_mask &= ~REDRAW_MAIN;
90 if (redraw_mask & REDRAW_TILES && redraw_tiles > REDRAWTILES_THRESHOLD)
91 redraw_mask |= REDRAW_FIELD;
93 if (redraw_mask & REDRAW_FIELD)
94 redraw_mask &= ~REDRAW_TILES;
97 if (redraw_mask & REDRAW_FIELD ||
98 (ScreenGfxPos && setup.soft_scrolling && game_status == PLAYING))
99 redraw_mask &= ~REDRAW_TILES;
105 /* synchronize X11 graphics at this point; if we would synchronize the
106 display immediately after the buffer switching (after the XFlush),
107 this could mean that we have to wait for the graphics to complete,
108 although we could go on doing calculations for the next frame */
110 XSync(display, FALSE);
114 wait_for_vsync = TRUE;
118 if (redraw_mask & REDRAW_ALL)
120 XCopyArea(display,backbuffer,window,gc,
121 0,0, WIN_XSIZE,WIN_YSIZE,
126 if (redraw_mask & REDRAW_FIELD)
128 if (game_status != PLAYING || redraw_mask & REDRAW_FROM_BACKBUFFER)
129 XCopyArea(display,backbuffer,window,gc,
130 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE,
134 int fx = FX, fy = FY;
136 if (setup.soft_scrolling)
138 fx += (ScreenMovDir & (MV_LEFT | MV_RIGHT) ? ScreenGfxPos : 0);
139 fy += (ScreenMovDir & (MV_UP | MV_DOWN) ? ScreenGfxPos : 0);
142 if (setup.soft_scrolling ||
143 ABS(ScreenMovPos) + ScrollStepSize == TILEX ||
144 ABS(ScreenMovPos) == ScrollStepSize ||
145 redraw_tiles > REDRAWTILES_THRESHOLD)
147 XCopyArea(display, buffer, window, gc, fx, fy, SXSIZE, SYSIZE, SX, SY);
151 printf("redrawing all (ScreenGfxPos == %d) because %s\n",
153 (setup.soft_scrolling ?
154 "setup.soft_scrolling" :
155 ABS(ScreenGfxPos) + ScrollStepSize == TILEX ?
156 "ABS(ScreenGfxPos) + ScrollStepSize == TILEX" :
157 ABS(ScreenGfxPos) == ScrollStepSize ?
158 "ABS(ScreenGfxPos) == ScrollStepSize" :
159 "redraw_tiles > REDRAWTILES_THRESHOLD"));
164 redraw_mask &= ~REDRAW_MAIN;
167 if (redraw_mask & REDRAW_DOORS)
169 if (redraw_mask & REDRAW_DOOR_1)
170 XCopyArea(display,backbuffer,window,gc,
171 DX,DY, DXSIZE,DYSIZE,
173 if (redraw_mask & REDRAW_DOOR_2)
175 if ((redraw_mask & REDRAW_DOOR_2) == REDRAW_DOOR_2)
176 XCopyArea(display,backbuffer,window,gc,
177 VX,VY, VXSIZE,VYSIZE,
181 if (redraw_mask & REDRAW_VIDEO_1)
182 XCopyArea(display,backbuffer,window,gc,
183 VX+VIDEO_DISPLAY1_XPOS,VY+VIDEO_DISPLAY1_YPOS,
184 VIDEO_DISPLAY_XSIZE,VIDEO_DISPLAY_YSIZE,
185 VX+VIDEO_DISPLAY1_XPOS,VY+VIDEO_DISPLAY1_YPOS);
186 if (redraw_mask & REDRAW_VIDEO_2)
187 XCopyArea(display,backbuffer,window,gc,
188 VX+VIDEO_DISPLAY2_XPOS,VY+VIDEO_DISPLAY2_YPOS,
189 VIDEO_DISPLAY_XSIZE,VIDEO_DISPLAY_YSIZE,
190 VX+VIDEO_DISPLAY2_XPOS,VY+VIDEO_DISPLAY2_YPOS);
191 if (redraw_mask & REDRAW_VIDEO_3)
192 XCopyArea(display,backbuffer,window,gc,
193 VX+VIDEO_CONTROL_XPOS,VY+VIDEO_CONTROL_YPOS,
194 VIDEO_CONTROL_XSIZE,VIDEO_CONTROL_YSIZE,
195 VX+VIDEO_CONTROL_XPOS,VY+VIDEO_CONTROL_YPOS);
198 if (redraw_mask & REDRAW_DOOR_3)
199 XCopyArea(display, backbuffer, window, gc,
200 EX, EY, EXSIZE, EYSIZE,
202 redraw_mask &= ~REDRAW_DOORS;
205 if (redraw_mask & REDRAW_MICROLEVEL)
207 XCopyArea(display,backbuffer,window,gc,
208 MICROLEV_XPOS, MICROLEV_YPOS, MICROLEV_XSIZE, MICROLEV_YSIZE,
209 MICROLEV_XPOS, MICROLEV_YPOS);
210 XCopyArea(display,backbuffer,window,gc,
211 SX, MICROLABEL_YPOS, SXSIZE, FONT4_YSIZE,
212 SX, MICROLABEL_YPOS);
213 redraw_mask &= ~REDRAW_MICROLEVEL;
216 if (redraw_mask & REDRAW_TILES)
218 for(x=0; x<SCR_FIELDX; x++)
219 for(y=0; y<SCR_FIELDY; y++)
220 if (redraw[redraw_x1 + x][redraw_y1 + y])
221 XCopyArea(display,buffer,window,gc,
222 FX+x*TILEX,FX+y*TILEY, TILEX,TILEY,
223 SX+x*TILEX,SY+y*TILEY);
228 for(x=0; x<MAX_BUF_XSIZE; x++)
229 for(y=0; y<MAX_BUF_YSIZE; y++)
238 long fading_delay = 300;
240 if (setup.fading && (redraw_mask & REDRAW_FIELD))
247 XFillRectangle(display,window,gc,
248 REAL_SX,REAL_SY,FULL_SXSIZE,FULL_SYSIZE);
251 for(i=0;i<2*FULL_SYSIZE;i++)
253 for(y=0;y<FULL_SYSIZE;y++)
255 XCopyArea(display,backbuffer,window,gc,
256 REAL_SX,REAL_SY+i, FULL_SXSIZE,1, REAL_SX,REAL_SY+i);
264 for(i=1;i<FULL_SYSIZE;i+=2)
265 XCopyArea(display,backbuffer,window,gc,
266 REAL_SX,REAL_SY+i, FULL_SXSIZE,1, REAL_SX,REAL_SY+i);
272 XSetClipOrigin(display,clip_gc[PIX_FADEMASK],0,0);
273 XCopyArea(display,backbuffer,window,clip_gc[PIX_FADEMASK],
274 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE, REAL_SX,REAL_SY);
278 XSetClipOrigin(display,clip_gc[PIX_FADEMASK],-1,-1);
279 XCopyArea(display,backbuffer,window,clip_gc[PIX_FADEMASK],
280 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE, REAL_SX,REAL_SY);
284 XSetClipOrigin(display,clip_gc[PIX_FADEMASK],0,-1);
285 XCopyArea(display,backbuffer,window,clip_gc[PIX_FADEMASK],
286 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE, REAL_SX,REAL_SY);
290 XSetClipOrigin(display,clip_gc[PIX_FADEMASK],-1,0);
291 XCopyArea(display,backbuffer,window,clip_gc[PIX_FADEMASK],
292 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE, REAL_SX,REAL_SY);
296 redraw_mask &= ~REDRAW_MAIN;
305 XFillRectangle(display, backbuffer, gc,
306 REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE);
308 if (setup.soft_scrolling && game_status == PLAYING)
310 XFillRectangle(display, fieldbuffer, gc, 0, 0, FXSIZE, FYSIZE);
311 SetDrawtoField(DRAW_BUFFERED);
314 SetDrawtoField(DRAW_BACKBUFFER);
316 if (setup.direct_draw && game_status == PLAYING)
318 XFillRectangle(display, window, gc,
319 REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE);
320 SetDrawtoField(DRAW_DIRECT);
323 redraw_mask |= REDRAW_FIELD;
326 void DrawTextFCentered(int y, int font_type, char *format, ...)
328 char buffer[FULL_SXSIZE / FONT3_XSIZE + 10];
332 font_xsize = (font_type < FC_SPECIAL1 ? FONT2_XSIZE :
333 font_type < FC_SPECIAL2 ? FONT3_XSIZE : FONT4_XSIZE);
335 va_start(ap, format);
336 vsprintf(buffer, format, ap);
339 DrawText(SX + (SXSIZE - strlen(buffer) * font_xsize) / 2, SY + y,
340 buffer, FS_SMALL, font_type);
343 void DrawTextF(int x, int y, int font_type, char *format, ...)
345 char buffer[FULL_SXSIZE / FONT3_XSIZE + 10];
348 va_start(ap, format);
349 vsprintf(buffer, format, ap);
352 DrawText(SX + x, SY + y, buffer, FS_SMALL, font_type);
355 void DrawText(int x, int y, char *text, int font_size, int font_type)
357 DrawTextExt(drawto, gc, x, y, text, font_size, font_type);
360 redraw_mask |= REDRAW_FIELD;
362 redraw_mask |= REDRAW_DOOR_1;
365 void DrawTextExt(Drawable d, GC gc, int x, int y,
366 char *text, int font_size, int font_type)
368 int font_width, font_height, font_start;
370 boolean print_inverse = FALSE;
372 if (font_size != FS_SMALL && font_size != FS_BIG)
373 font_size = FS_SMALL;
374 if (font_type < FC_RED || font_type > FC_SPECIAL2)
377 font_width = (font_size == FS_BIG ? FONT1_XSIZE :
378 font_type < FC_SPECIAL1 ? FONT2_XSIZE :
379 font_type < FC_SPECIAL2 ? FONT3_XSIZE : FONT4_XSIZE);
380 font_height = (font_size == FS_BIG ? FONT1_XSIZE :
381 font_type < FC_SPECIAL2 ? FONT2_XSIZE : FONT4_XSIZE);
382 font_pixmap = (font_size == FS_BIG ? PIX_BIGFONT : PIX_SMALLFONT);
383 font_start = (font_type * (font_size == FS_BIG ? FONT1_YSIZE : FONT2_YSIZE) *
384 FONT_LINES_PER_FONT);
390 if (c == '~' && font_size == FS_SMALL && font_type <= FC_YELLOW)
392 print_inverse = TRUE;
396 if (c >= 'a' && c <= 'z')
398 else if (c == 'ä' || c == 'Ä')
400 else if (c == 'ö' || c == 'Ö')
402 else if (c == 'ü' || c == 'Ü')
405 if (c >= 32 && c <= 95)
407 int src_x = ((c - 32) % FONT_CHARS_PER_LINE) * font_width;
408 int src_y = ((c - 32) / FONT_CHARS_PER_LINE) * font_height + font_start;
409 int dest_x = x, dest_y = y;
413 XCopyArea(display, pix[font_pixmap], d, gc,
414 FONT_CHARS_PER_LINE * font_width,
415 3 * font_height + font_start,
416 font_width, font_height, x, y);
418 XSetClipOrigin(display, clip_gc[font_pixmap],
419 dest_x - src_x, dest_y - src_y);
420 XCopyArea(display, pix[font_pixmap], drawto, clip_gc[font_pixmap],
421 0, 0, font_width, font_height, dest_x, dest_y);
424 XCopyArea(display, pix[font_pixmap], d, gc,
425 src_x, src_y, font_width, font_height, dest_x, dest_y);
432 void DrawAllPlayers()
436 for(i=0; i<MAX_PLAYERS; i++)
437 if (stored_player[i].active)
438 DrawPlayer(&stored_player[i]);
441 void DrawPlayerField(int x, int y)
446 DrawPlayer(PLAYERINFO(x,y));
449 void DrawPlayer(struct PlayerInfo *player)
451 int jx = player->jx, jy = player->jy;
452 int last_jx = player->last_jx, last_jy = player->last_jy;
453 int next_jx = jx + (jx - last_jx), next_jy = jy + (jy - last_jy);
454 int sx = SCREENX(jx), sy = SCREENY(jy);
455 int sxx = 0, syy = 0;
456 int element = Feld[jx][jy];
459 if (!player->active || player->gone ||
460 !IN_SCR_FIELD(SCREENX(last_jx), SCREENY(last_jy)))
464 if (!IN_LEV_FIELD(jx,jy))
466 printf("DrawPlayerField(): x = %d, y = %d\n",jx,jy);
467 printf("DrawPlayerField(): sx = %d, sy = %d\n",sx,sy);
468 printf("DrawPlayerField(): This should never happen!\n");
473 if (element == EL_EXPLODING)
476 /* draw things in the field the player is leaving, if needed */
478 if (last_jx != jx || last_jy != jy)
480 if (Store[last_jx][last_jy])
482 DrawLevelElement(last_jx, last_jy, Store[last_jx][last_jy]);
483 DrawLevelFieldThruMask(last_jx, last_jy);
485 else if (Feld[last_jx][last_jy] == EL_DYNAMIT)
486 DrawDynamite(last_jx, last_jy);
488 DrawLevelField(last_jx, last_jy);
490 if (player->Pushing && IN_SCR_FIELD(SCREENX(next_jx), SCREENY(next_jy)))
494 if (Feld[next_jx][next_jy] == EL_SOKOBAN_FELD_VOLL)
495 DrawLevelElement(next_jx, next_jy, EL_SOKOBAN_FELD_LEER);
497 DrawLevelElement(next_jx, next_jy, EL_LEERRAUM);
500 DrawLevelField(next_jx, next_jy);
504 if (!IN_SCR_FIELD(sx, sy))
507 if (setup.direct_draw)
508 SetDrawtoField(DRAW_BUFFERED);
510 /* draw things behind the player, if needed */
513 DrawLevelElement(jx, jy, Store[jx][jy]);
514 else if (element != EL_DYNAMIT && element != EL_DYNABOMB)
515 DrawLevelField(jx, jy);
517 /* draw player himself */
519 if (player->MovDir == MV_LEFT)
520 graphic = (player->Pushing ? GFX_SPIELER1_PUSH_LEFT : GFX_SPIELER1_LEFT);
521 else if (player->MovDir == MV_RIGHT)
522 graphic = (player->Pushing ? GFX_SPIELER1_PUSH_RIGHT : GFX_SPIELER1_RIGHT);
523 else if (player->MovDir == MV_UP)
524 graphic = GFX_SPIELER1_UP;
525 else /* MV_DOWN || MV_NO_MOVING */
526 graphic = GFX_SPIELER1_DOWN;
528 graphic += player->index_nr * 3*HEROES_PER_LINE;
529 graphic += player->Frame;
533 if (player->MovDir == MV_LEFT || player->MovDir == MV_RIGHT)
534 sxx = player->GfxPos;
536 syy = player->GfxPos;
539 if (!setup.soft_scrolling && ScreenMovPos)
542 DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, NO_CUTTING);
544 if (player->Pushing && player->GfxPos)
546 int px = SCREENX(next_jx), py = SCREENY(next_jy);
548 if (Feld[jx][jy] == EL_SOKOBAN_FELD_LEER ||
549 Feld[next_jx][next_jy] == EL_SOKOBAN_FELD_VOLL)
550 DrawGraphicShiftedThruMask(px, py, sxx, syy, GFX_SOKOBAN_OBJEKT,
554 int element = Feld[next_jx][next_jy];
555 int graphic = el2gfx(element);
557 if (element == EL_FELSBROCKEN && sxx)
559 int phase = (player->GfxPos / (TILEX/4));
561 if (player->MovDir == MV_LEFT)
564 graphic += (phase+4)%4;
567 DrawGraphicShifted(px, py, sxx, syy, graphic, NO_CUTTING, NO_MASKING);
571 /* draw things in front of player (EL_DYNAMIT || EL_DYNABOMB) */
573 if (element == EL_DYNAMIT || element == EL_DYNABOMB)
575 graphic = el2gfx(element);
577 if (element == EL_DYNAMIT)
579 if ((phase = (96 - MovDelay[jx][jy]) / 12) > 6)
584 if ((phase = ((96 - MovDelay[jx][jy]) / 6) % 8) > 3)
588 if (game_emulation == EMU_SUPAPLEX)
589 DrawGraphic(sx, sy, GFX_SP_DISK_RED);
591 DrawGraphicThruMask(sx, sy, graphic + phase);
594 if ((last_jx != jx || last_jy != jy) &&
595 Feld[last_jx][last_jy] == EL_EXPLODING)
597 int phase = Frame[last_jx][last_jy];
601 DrawGraphicThruMask(SCREENX(last_jx), SCREENY(last_jy),
602 GFX_EXPLOSION + ((phase - 1) / delay - 1));
605 if (setup.direct_draw)
607 int dest_x = SX + SCREENX(MIN(jx, last_jx)) * TILEX;
608 int dest_y = SY + SCREENY(MIN(jy, last_jy)) * TILEY;
609 int x_size = TILEX * (1 + ABS(jx - last_jx));
610 int y_size = TILEY * (1 + ABS(jy - last_jy));
612 XCopyArea(display, drawto_field, window, gc,
613 dest_x, dest_y, x_size, y_size, dest_x, dest_y);
614 SetDrawtoField(DRAW_DIRECT);
617 MarkTileDirty(sx,sy);
620 static int getGraphicAnimationPhase(int frames, int delay, int mode)
624 if (mode == ANIM_OSCILLATE)
626 int max_anim_frames = 2 * frames - 2;
627 phase = (FrameCounter % (delay * max_anim_frames)) / delay;
628 phase = (phase < frames ? phase : max_anim_frames - phase);
631 phase = (FrameCounter % (delay * frames)) / delay;
633 if (mode == ANIM_REVERSE)
639 void DrawGraphicAnimationExt(int x, int y, int graphic,
640 int frames, int delay, int mode, int mask_mode)
642 int phase = getGraphicAnimationPhase(frames, delay, mode);
644 if (!(FrameCounter % delay) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
646 if (mask_mode == USE_MASKING)
647 DrawGraphicThruMask(SCREENX(x), SCREENY(y), graphic + phase);
649 DrawGraphic(SCREENX(x), SCREENY(y), graphic + phase);
653 void DrawGraphicAnimation(int x, int y, int graphic,
654 int frames, int delay, int mode)
656 DrawGraphicAnimationExt(x, y, graphic, frames, delay, mode, NO_MASKING);
659 void DrawGraphicAnimationThruMask(int x, int y, int graphic,
660 int frames, int delay, int mode)
662 DrawGraphicAnimationExt(x, y, graphic, frames, delay, mode, USE_MASKING);
665 void DrawGraphic(int x, int y, int graphic)
668 if (!IN_SCR_FIELD(x,y))
670 printf("DrawGraphic(): x = %d, y = %d, graphic = %d\n",x,y,graphic);
671 printf("DrawGraphic(): This should never happen!\n");
676 DrawGraphicExt(drawto_field, gc, FX + x*TILEX, FY + y*TILEY, graphic);
680 void DrawGraphicExt(Drawable d, GC gc, int x, int y, int graphic)
682 if (graphic >= GFX_START_ROCKSSCREEN && graphic <= GFX_END_ROCKSSCREEN)
684 graphic -= GFX_START_ROCKSSCREEN;
685 XCopyArea(display, pix[PIX_BACK], d, gc,
686 SX + (graphic % GFX_PER_LINE) * TILEX,
687 SY + (graphic / GFX_PER_LINE) * TILEY,
690 else if (graphic >= GFX_START_ROCKSMORE && graphic <= GFX_END_ROCKSMORE)
692 graphic -= GFX_START_ROCKSMORE;
693 XCopyArea(display, pix[PIX_MORE], d, gc,
694 (graphic % MORE_PER_LINE) * TILEX,
695 (graphic / MORE_PER_LINE) * TILEY,
698 else if (graphic >= GFX_START_ROCKSHEROES && graphic <= GFX_END_ROCKSHEROES)
700 graphic -= GFX_START_ROCKSHEROES;
701 XCopyArea(display, pix[PIX_HEROES], d, gc,
702 (graphic % HEROES_PER_LINE) * TILEX,
703 (graphic / HEROES_PER_LINE) * TILEY,
706 else if (graphic >= GFX_START_ROCKSFONT && graphic <= GFX_END_ROCKSFONT)
708 graphic -= GFX_START_ROCKSFONT;
709 XCopyArea(display, pix[PIX_BIGFONT], d, gc,
710 (graphic % FONT_CHARS_PER_LINE) * TILEX,
711 (graphic / FONT_CHARS_PER_LINE) * TILEY +
712 FC_SPECIAL1 * FONT_LINES_PER_FONT * TILEY,
716 XFillRectangle(display, d, gc, x, y, TILEX, TILEY);
719 void DrawGraphicThruMask(int x, int y, int graphic)
722 if (!IN_SCR_FIELD(x,y))
724 printf("DrawGraphicThruMask(): x = %d,y = %d, graphic = %d\n",x,y,graphic);
725 printf("DrawGraphicThruMask(): This should never happen!\n");
730 DrawGraphicThruMaskExt(drawto_field, FX + x*TILEX, FY + y*TILEY, graphic);
734 void DrawGraphicThruMaskExt(Drawable d, int dest_x, int dest_y, int graphic)
741 if (graphic >= GFX_START_ROCKSSCREEN && graphic <= GFX_END_ROCKSSCREEN)
743 src_pixmap = pix[PIX_BACK];
744 drawing_gc = clip_gc[PIX_BACK];
745 graphic -= GFX_START_ROCKSSCREEN;
746 src_x = SX + (graphic % GFX_PER_LINE) * TILEX;
747 src_y = SY + (graphic / GFX_PER_LINE) * TILEY;
749 else if (graphic >= GFX_START_ROCKSMORE && graphic <= GFX_END_ROCKSMORE)
751 src_pixmap = pix[PIX_MORE];
752 drawing_gc = clip_gc[PIX_MORE];
753 graphic -= GFX_START_ROCKSMORE;
754 src_x = (graphic % MORE_PER_LINE) * TILEX;
755 src_y = (graphic / MORE_PER_LINE) * TILEY;
757 else if (graphic >= GFX_START_ROCKSHEROES && graphic <= GFX_END_ROCKSHEROES)
759 src_pixmap = pix[PIX_HEROES];
760 drawing_gc = clip_gc[PIX_HEROES];
761 graphic -= GFX_START_ROCKSHEROES;
762 src_x = (graphic % HEROES_PER_LINE) * TILEX;
763 src_y = (graphic / HEROES_PER_LINE) * TILEY;
767 DrawGraphicExt(d, gc, dest_x,dest_y, graphic);
771 if (tile_clipmask[tile] != None)
773 XSetClipMask(display, tile_clip_gc, tile_clipmask[tile]);
774 XSetClipOrigin(display, tile_clip_gc, dest_x, dest_y);
775 XCopyArea(display, src_pixmap, drawto_field, tile_clip_gc,
776 src_x, src_y, TILEX, TILEY, dest_x, dest_y);
781 printf("DrawGraphicThruMask(): tile '%d' needs clipping!\n", tile);
784 XSetClipOrigin(display, drawing_gc, dest_x-src_x, dest_y-src_y);
785 XCopyArea(display, src_pixmap, drawto_field, drawing_gc,
786 src_x, src_y, TILEX, TILEY, dest_x, dest_y);
790 void DrawMiniGraphic(int x, int y, int graphic)
792 DrawMiniGraphicExt(drawto,gc, SX + x*MINI_TILEX, SY + y*MINI_TILEY, graphic);
793 MarkTileDirty(x/2, y/2);
796 void getMiniGraphicSource(int graphic, Pixmap *pixmap, int *x, int *y)
798 if (graphic >= GFX_START_ROCKSSCREEN && graphic <= GFX_END_ROCKSSCREEN)
800 graphic -= GFX_START_ROCKSSCREEN;
801 *pixmap = pix[PIX_BACK];
802 *x = MINI_GFX_STARTX + (graphic % MINI_GFX_PER_LINE) * MINI_TILEX;
803 *y = MINI_GFX_STARTY + (graphic / MINI_GFX_PER_LINE) * MINI_TILEY;
805 else if (graphic >= GFX_START_ROCKSMORE && graphic <= GFX_END_ROCKSMORE)
807 graphic -= GFX_START_ROCKSMORE;
808 *pixmap = pix[PIX_MORE];
809 *x = MINI_MORE_STARTX + (graphic % MINI_MORE_PER_LINE) * MINI_TILEX;
810 *y = MINI_MORE_STARTY + (graphic / MINI_MORE_PER_LINE) * MINI_TILEY;
812 else if (graphic >= GFX_START_ROCKSFONT && graphic <= GFX_END_ROCKSFONT)
814 graphic -= GFX_START_ROCKSFONT;
815 *pixmap = pix[PIX_SMALLFONT];
816 *x = (graphic % FONT_CHARS_PER_LINE) * FONT4_XSIZE;
817 *y = ((graphic / FONT_CHARS_PER_LINE) * FONT4_YSIZE +
818 FC_SPECIAL2 * FONT2_YSIZE * FONT_LINES_PER_FONT);
822 *pixmap = pix[PIX_MORE];
823 *x = MINI_MORE_STARTX;
824 *y = MINI_MORE_STARTY;
828 void DrawMiniGraphicExt(Drawable d, GC gc, int x, int y, int graphic)
830 if (graphic >= GFX_START_ROCKSSCREEN && graphic <= GFX_END_ROCKSSCREEN)
832 graphic -= GFX_START_ROCKSSCREEN;
833 XCopyArea(display, pix[PIX_BACK], d, gc,
834 MINI_GFX_STARTX + (graphic % MINI_GFX_PER_LINE) * MINI_TILEX,
835 MINI_GFX_STARTY + (graphic / MINI_GFX_PER_LINE) * MINI_TILEY,
836 MINI_TILEX, MINI_TILEY, x, y);
838 else if (graphic >= GFX_START_ROCKSMORE && graphic <= GFX_END_ROCKSMORE)
840 graphic -= GFX_START_ROCKSMORE;
841 XCopyArea(display, pix[PIX_MORE], d, gc,
842 MINI_MORE_STARTX + (graphic % MINI_MORE_PER_LINE) * MINI_TILEX,
843 MINI_MORE_STARTY + (graphic / MINI_MORE_PER_LINE) * MINI_TILEY,
844 MINI_TILEX, MINI_TILEY, x, y);
846 else if (graphic >= GFX_START_ROCKSFONT && graphic <= GFX_END_ROCKSFONT)
848 graphic -= GFX_START_ROCKSFONT;
849 XCopyArea(display, pix[PIX_SMALLFONT], d, gc,
850 (graphic % FONT_CHARS_PER_LINE) * FONT4_XSIZE,
851 (graphic / FONT_CHARS_PER_LINE) * FONT4_YSIZE +
852 FC_SPECIAL2 * FONT2_YSIZE * FONT_LINES_PER_FONT,
853 MINI_TILEX, MINI_TILEY, x, y);
856 XFillRectangle(display, d, gc, x, y, MINI_TILEX, MINI_TILEY);
859 void DrawGraphicShifted(int x,int y, int dx,int dy, int graphic,
860 int cut_mode, int mask_mode)
862 int width = TILEX, height = TILEY;
864 int src_x, src_y, dest_x, dest_y;
871 DrawGraphic(x, y, graphic);
875 if (dx || dy) /* Verschiebung der Grafik? */
877 if (x < BX1) /* Element kommt von links ins Bild */
884 else if (x > BX2) /* Element kommt von rechts ins Bild */
890 else if (x==BX1 && dx < 0) /* Element verläßt links das Bild */
896 else if (x==BX2 && dx > 0) /* Element verläßt rechts das Bild */
898 else if (dx) /* allg. Bewegung in x-Richtung */
899 MarkTileDirty(x + SIGN(dx), y);
901 if (y < BY1) /* Element kommt von oben ins Bild */
903 if (cut_mode==CUT_BELOW) /* Element oberhalb des Bildes */
911 else if (y > BY2) /* Element kommt von unten ins Bild */
917 else if (y==BY1 && dy < 0) /* Element verläßt oben das Bild */
923 else if (dy > 0 && cut_mode == CUT_ABOVE)
925 if (y == BY2) /* Element unterhalb des Bildes */
931 MarkTileDirty(x, y + 1);
932 } /* Element verläßt unten das Bild */
933 else if (dy > 0 && (y == BY2 || cut_mode == CUT_BELOW))
935 else if (dy) /* allg. Bewegung in y-Richtung */
936 MarkTileDirty(x, y + SIGN(dy));
939 if (graphic >= GFX_START_ROCKSSCREEN && graphic <= GFX_END_ROCKSSCREEN)
941 src_pixmap = pix[PIX_BACK];
942 drawing_gc = clip_gc[PIX_BACK];
943 graphic -= GFX_START_ROCKSSCREEN;
944 src_x = SX + (graphic % GFX_PER_LINE) * TILEX + cx;
945 src_y = SY + (graphic / GFX_PER_LINE) * TILEY + cy;
947 else if (graphic >= GFX_START_ROCKSMORE && graphic <= GFX_END_ROCKSMORE)
949 src_pixmap = pix[PIX_MORE];
950 drawing_gc = clip_gc[PIX_MORE];
951 graphic -= GFX_START_ROCKSMORE;
952 src_x = (graphic % MORE_PER_LINE) * TILEX + cx;
953 src_y = (graphic / MORE_PER_LINE) * TILEY + cy;
955 else if (graphic >= GFX_START_ROCKSHEROES && graphic <= GFX_END_ROCKSHEROES)
957 src_pixmap = pix[PIX_HEROES];
958 drawing_gc = clip_gc[PIX_HEROES];
959 graphic -= GFX_START_ROCKSHEROES;
960 src_x = (graphic % HEROES_PER_LINE) * TILEX + cx;
961 src_y = (graphic / HEROES_PER_LINE) * TILEY + cy;
963 else /* big font graphics currently not allowed (and not needed) */
966 dest_x = FX + x * TILEX + dx;
967 dest_y = FY + y * TILEY + dy;
970 if (!IN_SCR_FIELD(x,y))
972 printf("DrawGraphicShifted(): x = %d, y = %d, graphic = %d\n",x,y,graphic);
973 printf("DrawGraphicShifted(): This should never happen!\n");
978 if (mask_mode == USE_MASKING)
980 if (tile_clipmask[tile] != None)
982 XSetClipMask(display, tile_clip_gc, tile_clipmask[tile]);
983 XSetClipOrigin(display, tile_clip_gc, dest_x, dest_y);
984 XCopyArea(display, src_pixmap, drawto_field, tile_clip_gc,
985 src_x, src_y, TILEX, TILEY, dest_x, dest_y);
990 printf("DrawGraphicShifted(): tile '%d' needs clipping!\n", tile);
993 XSetClipOrigin(display, drawing_gc, dest_x - src_x, dest_y - src_y);
994 XCopyArea(display, src_pixmap, drawto_field, drawing_gc,
995 src_x, src_y, width, height, dest_x, dest_y);
999 XCopyArea(display, src_pixmap, drawto_field, gc,
1000 src_x, src_y, width, height, dest_x, dest_y);
1005 void DrawGraphicShiftedThruMask(int x,int y, int dx,int dy, int graphic,
1008 DrawGraphicShifted(x,y, dx,dy, graphic, cut_mode, USE_MASKING);
1011 void DrawScreenElementExt(int x, int y, int dx, int dy, int element,
1012 int cut_mode, int mask_mode)
1014 int ux = LEVELX(x), uy = LEVELY(y);
1015 int graphic = el2gfx(element);
1016 int phase8 = ABS(MovPos[ux][uy]) / (TILEX / 8);
1017 int phase4 = phase8 / 2;
1018 int phase2 = phase8 / 4;
1019 int dir = MovDir[ux][uy];
1021 if (element == EL_PACMAN || element == EL_KAEFER || element == EL_FLIEGER)
1023 graphic += 4 * !phase2;
1027 else if (dir == MV_LEFT)
1029 else if (dir == MV_DOWN)
1032 else if (element == EL_SP_SNIKSNAK)
1035 graphic = GFX_SP_SNIKSNAK_LEFT;
1036 else if (dir == MV_RIGHT)
1037 graphic = GFX_SP_SNIKSNAK_RIGHT;
1038 else if (dir == MV_UP)
1039 graphic = GFX_SP_SNIKSNAK_UP;
1041 graphic = GFX_SP_SNIKSNAK_DOWN;
1043 graphic += (phase8 < 4 ? phase8 : 7 - phase8);
1045 else if (element == EL_SP_ELECTRON)
1047 graphic = GFX2_SP_ELECTRON + getGraphicAnimationPhase(8, 2, ANIM_NORMAL);
1049 else if (element == EL_MAULWURF || element == EL_PINGUIN ||
1050 element == EL_SCHWEIN || element == EL_DRACHE)
1053 graphic = (element == EL_MAULWURF ? GFX_MAULWURF_LEFT :
1054 element == EL_PINGUIN ? GFX_PINGUIN_LEFT :
1055 element == EL_SCHWEIN ? GFX_SCHWEIN_LEFT : GFX_DRACHE_LEFT);
1056 else if (dir == MV_RIGHT)
1057 graphic = (element == EL_MAULWURF ? GFX_MAULWURF_RIGHT :
1058 element == EL_PINGUIN ? GFX_PINGUIN_RIGHT :
1059 element == EL_SCHWEIN ? GFX_SCHWEIN_RIGHT : GFX_DRACHE_RIGHT);
1060 else if (dir == MV_UP)
1061 graphic = (element == EL_MAULWURF ? GFX_MAULWURF_UP :
1062 element == EL_PINGUIN ? GFX_PINGUIN_UP :
1063 element == EL_SCHWEIN ? GFX_SCHWEIN_UP : GFX_DRACHE_UP);
1065 graphic = (element == EL_MAULWURF ? GFX_MAULWURF_DOWN :
1066 element == EL_PINGUIN ? GFX_PINGUIN_DOWN :
1067 element == EL_SCHWEIN ? GFX_SCHWEIN_DOWN : GFX_DRACHE_DOWN);
1071 else if (element == EL_SONDE)
1073 graphic = GFX_SONDE_START + getGraphicAnimationPhase(8, 2, ANIM_NORMAL);
1075 else if (element == EL_SALZSAEURE)
1077 graphic = GFX_GEBLUBBER + getGraphicAnimationPhase(4, 10, ANIM_NORMAL);
1079 else if (element == EL_BUTTERFLY || element == EL_FIREFLY)
1083 else if ((element == EL_FELSBROCKEN || IS_GEM(element)) && !cut_mode)
1085 if (element != EL_SP_INFOTRON)
1086 graphic += phase2 * (element == EL_FELSBROCKEN ? 2 : 1);
1088 else if (element == EL_SIEB_LEER || element == EL_SIEB2_LEER ||
1089 element == EL_SIEB_VOLL || element == EL_SIEB2_VOLL)
1091 graphic += 3 + getGraphicAnimationPhase(4, 4, ANIM_REVERSE);
1093 else if (IS_AMOEBOID(element))
1095 graphic = (element == EL_AMOEBE_TOT ? GFX_AMOEBE_TOT : GFX_AMOEBE_LEBT);
1096 graphic += (x + 2 * y + 4) % 4;
1098 else if (element == EL_MAUER_LEBT)
1100 boolean links_massiv = FALSE, rechts_massiv = FALSE;
1102 if (!IN_LEV_FIELD(ux-1, uy) || IS_MAUER(Feld[ux-1][uy]))
1103 links_massiv = TRUE;
1104 if (!IN_LEV_FIELD(ux+1, uy) || IS_MAUER(Feld[ux+1][uy]))
1105 rechts_massiv = TRUE;
1107 if (links_massiv && rechts_massiv)
1108 graphic = GFX_MAUERWERK;
1109 else if (links_massiv)
1110 graphic = GFX_MAUER_R;
1111 else if (rechts_massiv)
1112 graphic = GFX_MAUER_L;
1116 DrawGraphicShifted(x, y, dx, dy, graphic, cut_mode, mask_mode);
1117 else if (mask_mode == USE_MASKING)
1118 DrawGraphicThruMask(x, y, graphic);
1120 DrawGraphic(x, y, graphic);
1123 void DrawLevelElementExt(int x, int y, int dx, int dy, int element,
1124 int cut_mode, int mask_mode)
1126 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1127 DrawScreenElementExt(SCREENX(x), SCREENY(y), dx, dy, element,
1128 cut_mode, mask_mode);
1131 void DrawScreenElementShifted(int x, int y, int dx, int dy, int element,
1134 DrawScreenElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
1137 void DrawLevelElementShifted(int x, int y, int dx, int dy, int element,
1140 DrawLevelElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
1143 void DrawScreenElementThruMask(int x, int y, int element)
1145 DrawScreenElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
1148 void DrawLevelElementThruMask(int x, int y, int element)
1150 DrawLevelElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
1153 void DrawLevelFieldThruMask(int x, int y)
1155 DrawLevelElementExt(x, y, 0, 0, Feld[x][y], NO_CUTTING, USE_MASKING);
1158 void ErdreichAnbroeckeln(int x, int y)
1160 int i, width, height, cx,cy;
1161 int ux = LEVELX(x), uy = LEVELY(y);
1162 int element, graphic;
1164 static int xy[4][2] =
1172 if (!IN_LEV_FIELD(ux, uy))
1175 element = Feld[ux][uy];
1177 if (element == EL_ERDREICH)
1179 if (!IN_SCR_FIELD(x, y))
1182 graphic = GFX_ERDENRAND;
1188 uxx = ux + xy[i][0];
1189 uyy = uy + xy[i][1];
1190 if (!IN_LEV_FIELD(uxx, uyy))
1193 element = Feld[uxx][uyy];
1195 if (element == EL_ERDREICH)
1198 if (i == 1 || i == 2)
1202 cx = (i == 2 ? TILEX - snip : 0);
1210 cy = (i == 3 ? TILEY - snip : 0);
1213 XCopyArea(display, pix[PIX_BACK], drawto_field, gc,
1214 SX + (graphic % GFX_PER_LINE) * TILEX + cx,
1215 SY + (graphic / GFX_PER_LINE) * TILEY + cy,
1216 width, height, FX + x * TILEX + cx, FY + y * TILEY + cy);
1219 MarkTileDirty(x, y);
1223 graphic = GFX_ERDENRAND;
1227 int xx, yy, uxx, uyy;
1231 uxx = ux + xy[i][0];
1232 uyy = uy + xy[i][1];
1234 if (!IN_LEV_FIELD(uxx, uyy) || Feld[uxx][uyy] != EL_ERDREICH ||
1235 !IN_SCR_FIELD(xx, yy))
1238 if (i == 1 || i == 2)
1242 cx = (i == 1 ? TILEX - snip : 0);
1250 cy = (i==0 ? TILEY-snip : 0);
1253 XCopyArea(display, pix[PIX_BACK], drawto_field, gc,
1254 SX + (graphic % GFX_PER_LINE) * TILEX + cx,
1255 SY + (graphic / GFX_PER_LINE) * TILEY + cy,
1256 width, height, FX + xx * TILEX + cx, FY + yy * TILEY + cy);
1258 MarkTileDirty(xx, yy);
1263 void DrawScreenElement(int x, int y, int element)
1265 DrawScreenElementExt(x, y, 0, 0, element, NO_CUTTING, NO_MASKING);
1266 ErdreichAnbroeckeln(x, y);
1269 void DrawLevelElement(int x, int y, int element)
1271 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1272 DrawScreenElement(SCREENX(x), SCREENY(y), element);
1275 void DrawScreenField(int x, int y)
1277 int ux = LEVELX(x), uy = LEVELY(y);
1280 if (!IN_LEV_FIELD(ux, uy))
1282 if (ux < -1 || ux > lev_fieldx || uy < -1 || uy > lev_fieldy)
1283 element = EL_LEERRAUM;
1285 element = BorderElement;
1287 DrawScreenElement(x, y, element);
1291 element = Feld[ux][uy];
1293 if (IS_MOVING(ux, uy))
1295 int horiz_move = (MovDir[ux][uy] == MV_LEFT || MovDir[ux][uy] == MV_RIGHT);
1296 boolean cut_mode = NO_CUTTING;
1298 if (Store[ux][uy] == EL_MORAST_LEER ||
1299 Store[ux][uy] == EL_SIEB_LEER ||
1300 Store[ux][uy] == EL_SIEB2_LEER ||
1301 Store[ux][uy] == EL_AMOEBE_NASS)
1302 cut_mode = CUT_ABOVE;
1303 else if (Store[ux][uy] == EL_MORAST_VOLL ||
1304 Store[ux][uy] == EL_SIEB_VOLL ||
1305 Store[ux][uy] == EL_SIEB2_VOLL)
1306 cut_mode = CUT_BELOW;
1308 if (cut_mode == CUT_ABOVE)
1309 DrawScreenElementShifted(x, y, 0, 0, Store[ux][uy], NO_CUTTING);
1311 DrawScreenElement(x, y, EL_LEERRAUM);
1314 DrawScreenElementShifted(x, y, MovPos[ux][uy], 0, element, NO_CUTTING);
1316 DrawScreenElementShifted(x, y, 0, MovPos[ux][uy], element, cut_mode);
1318 if (Store[ux][uy] == EL_SALZSAEURE)
1319 DrawLevelElementThruMask(ux, uy + 1, EL_SALZSAEURE);
1321 else if (IS_BLOCKED(ux, uy))
1326 boolean cut_mode = NO_CUTTING;
1328 Blocked2Moving(ux, uy, &oldx, &oldy);
1331 horiz_move = (MovDir[oldx][oldy] == MV_LEFT ||
1332 MovDir[oldx][oldy] == MV_RIGHT);
1334 if (Store[oldx][oldy] == EL_MORAST_LEER ||
1335 Store[oldx][oldy] == EL_SIEB_LEER ||
1336 Store[oldx][oldy] == EL_SIEB2_LEER ||
1337 Store[oldx][oldy] == EL_AMOEBE_NASS)
1338 cut_mode = CUT_ABOVE;
1340 DrawScreenElement(x, y, EL_LEERRAUM);
1341 element = Feld[oldx][oldy];
1344 DrawScreenElementShifted(sx,sy, MovPos[oldx][oldy],0,element,NO_CUTTING);
1346 DrawScreenElementShifted(sx,sy, 0,MovPos[oldx][oldy],element,cut_mode);
1348 else if (IS_DRAWABLE(element))
1349 DrawScreenElement(x, y, element);
1351 DrawScreenElement(x, y, EL_LEERRAUM);
1354 void DrawLevelField(int x, int y)
1356 if (IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1357 DrawScreenField(SCREENX(x), SCREENY(y));
1358 else if (IS_MOVING(x, y))
1362 Moving2Blocked(x, y, &newx, &newy);
1363 if (IN_SCR_FIELD(SCREENX(newx), SCREENY(newy)))
1364 DrawScreenField(SCREENX(newx), SCREENY(newy));
1366 else if (IS_BLOCKED(x, y))
1370 Blocked2Moving(x, y, &oldx, &oldy);
1371 if (IN_SCR_FIELD(SCREENX(oldx), SCREENY(oldy)))
1372 DrawScreenField(SCREENX(oldx), SCREENY(oldy));
1376 void DrawMiniElement(int x, int y, int element)
1382 DrawMiniGraphic(x, y, -1);
1386 graphic = el2gfx(element);
1387 DrawMiniGraphic(x, y, graphic);
1390 void DrawMiniElementOrWall(int sx, int sy, int scroll_x, int scroll_y)
1392 int x = sx + scroll_x, y = sy + scroll_y;
1394 if (x < -1 || x > lev_fieldx || y < -1 || y > lev_fieldy)
1395 DrawMiniElement(sx, sy, EL_LEERRAUM);
1396 else if (x > -1 && x < lev_fieldx && y > -1 && y < lev_fieldy)
1397 DrawMiniElement(sx, sy, Feld[x][y]);
1398 else if (x == -1 && y == -1)
1399 DrawMiniGraphic(sx, sy, GFX_STEEL_UPPER_LEFT);
1400 else if (x == lev_fieldx && y == -1)
1401 DrawMiniGraphic(sx, sy, GFX_STEEL_UPPER_RIGHT);
1402 else if (x == -1 && y == lev_fieldy)
1403 DrawMiniGraphic(sx, sy, GFX_STEEL_LOWER_LEFT);
1404 else if (x == lev_fieldx && y == lev_fieldy)
1405 DrawMiniGraphic(sx, sy, GFX_STEEL_LOWER_RIGHT);
1406 else if (x == -1 || x == lev_fieldx)
1407 DrawMiniGraphic(sx, sy, GFX_STEEL_VERTICAL);
1408 else if (y == -1 || y == lev_fieldy)
1409 DrawMiniGraphic(sx, sy, GFX_STEEL_HORIZONTAL);
1412 void DrawMicroElement(int xpos, int ypos, int element)
1416 if (element == EL_LEERRAUM)
1419 graphic = el2gfx(element);
1421 if (graphic >= GFX_START_ROCKSMORE && graphic <= GFX_END_ROCKSMORE)
1423 graphic -= GFX_START_ROCKSMORE;
1424 XCopyArea(display, pix[PIX_MORE], drawto, gc,
1425 MICRO_MORE_STARTX + (graphic % MICRO_MORE_PER_LINE) *MICRO_TILEX,
1426 MICRO_MORE_STARTY + (graphic / MICRO_MORE_PER_LINE) *MICRO_TILEY,
1427 MICRO_TILEX, MICRO_TILEY, xpos, ypos);
1430 XCopyArea(display, pix[PIX_BACK], drawto, gc,
1431 MICRO_GFX_STARTX + (graphic % MICRO_GFX_PER_LINE) * MICRO_TILEX,
1432 MICRO_GFX_STARTY + (graphic / MICRO_GFX_PER_LINE) * MICRO_TILEY,
1433 MICRO_TILEX, MICRO_TILEY, xpos, ypos);
1442 for(x=BX1; x<=BX2; x++)
1443 for(y=BY1; y<=BY2; y++)
1444 DrawScreenField(x, y);
1446 if (setup.soft_scrolling)
1447 XCopyArea(display, fieldbuffer, backbuffer, gc,
1448 FX, FY, SXSIZE, SYSIZE, SX, SY);
1450 redraw_mask |= (REDRAW_FIELD | REDRAW_FROM_BACKBUFFER);
1453 void DrawMiniLevel(int scroll_x, int scroll_y)
1457 for(x=0; x<ED_FIELDX; x++)
1458 for(y=0; y<ED_FIELDY; y++)
1459 DrawMiniElementOrWall(x, y, scroll_x, scroll_y);
1461 redraw_mask |= REDRAW_FIELD;
1464 static void DrawMicroLevelExt(int xpos, int ypos, int from_x, int from_y)
1468 /* determine border element for this level */
1471 XFillRectangle(display, drawto, gc,
1472 xpos, ypos, MICROLEV_XSIZE, MICROLEV_YSIZE);
1474 if (lev_fieldx < STD_LEV_FIELDX)
1475 xpos += (STD_LEV_FIELDX - lev_fieldx) / 2 * MICRO_TILEX;
1476 if (lev_fieldy < STD_LEV_FIELDY)
1477 ypos += (STD_LEV_FIELDY - lev_fieldy) / 2 * MICRO_TILEY;
1479 xpos += MICRO_TILEX;
1480 ypos += MICRO_TILEY;
1482 for(x=-1; x<=STD_LEV_FIELDX; x++)
1484 for(y=-1; y<=STD_LEV_FIELDY; y++)
1486 int lx = from_x + x, ly = from_y + y;
1488 if (lx >= 0 && lx < lev_fieldx && ly >= 0 && ly < lev_fieldy)
1489 DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
1491 else if (lx >= -1 && lx < lev_fieldx+1 && ly >= -1 && ly < lev_fieldy+1)
1492 DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
1497 redraw_mask |= REDRAW_MICROLEVEL;
1500 static void DrawMicroLevelLabelExt(int mode)
1502 char label_text[100];
1504 XFillRectangle(display, drawto,gc,
1505 SX, MICROLABEL_YPOS, SXSIZE, FONT4_YSIZE);
1507 strcpy(label_text, (mode == 1 ? level.name :
1508 mode == 2 ? "created by" :
1509 mode == 3 ? level.author : ""));
1511 if (strlen(label_text) > 0)
1513 int size, lxpos, lypos;
1515 label_text[SXSIZE / FONT4_XSIZE] = '\0';
1517 size = strlen(label_text);
1518 lxpos = SX + (SXSIZE - size * FONT4_XSIZE) / 2;
1519 lypos = MICROLABEL_YPOS;
1521 DrawText(lxpos, lypos, label_text, FS_SMALL, FC_SPECIAL2);
1524 redraw_mask |= REDRAW_MICROLEVEL;
1527 void DrawMicroLevel(int xpos, int ypos, boolean restart)
1529 static unsigned long scroll_delay = 0;
1530 static unsigned long label_delay = 0;
1531 static int from_x, from_y, scroll_direction;
1532 static int label_state, label_counter;
1536 from_x = from_y = 0;
1537 scroll_direction = MV_RIGHT;
1541 DrawMicroLevelExt(xpos, ypos, from_x, from_y);
1542 DrawMicroLevelLabelExt(label_state);
1544 /* initialize delay counters */
1545 DelayReached(&scroll_delay, 0);
1546 DelayReached(&label_delay, 0);
1551 /* scroll micro level, if needed */
1552 if ((lev_fieldx > STD_LEV_FIELDX || lev_fieldy > STD_LEV_FIELDY) &&
1553 DelayReached(&scroll_delay, MICROLEVEL_SCROLL_DELAY))
1555 switch (scroll_direction)
1561 scroll_direction = MV_UP;
1565 if (from_x < lev_fieldx - STD_LEV_FIELDX)
1568 scroll_direction = MV_DOWN;
1575 scroll_direction = MV_RIGHT;
1579 if (from_y < lev_fieldy - STD_LEV_FIELDY)
1582 scroll_direction = MV_LEFT;
1589 DrawMicroLevelExt(xpos, ypos, from_x, from_y);
1592 /* redraw micro level label, if needed */
1593 if (strcmp(level.name, NAMELESS_LEVEL_NAME) != 0 &&
1594 strcmp(level.author, ANONYMOUS_NAME) != 0 &&
1595 strcmp(level.author, leveldir[leveldir_nr].name) != 0 &&
1596 DelayReached(&label_delay, MICROLEVEL_LABEL_DELAY))
1598 label_counter = (label_counter + 1) % 23;
1599 label_state = (label_counter >= 0 && label_counter <= 7 ? 1 :
1600 label_counter >= 9 && label_counter <= 12 ? 2 :
1601 label_counter >= 14 && label_counter <= 21 ? 3 : 0);
1602 DrawMicroLevelLabelExt(label_state);
1606 int REQ_in_range(int x, int y)
1608 if (y > DY+249 && y < DY+278)
1610 if (x > DX+1 && x < DX+48)
1612 else if (x > DX+51 && x < DX+98)
1618 boolean Request(char *text, unsigned int req_state)
1620 int mx, my, ty, result = -1;
1621 unsigned int old_door_state;
1624 /* pause network game while waiting for request to answer */
1625 if (options.network &&
1626 game_status == PLAYING &&
1627 req_state & REQUEST_WAIT_FOR)
1628 SendToServer_PausePlaying();
1631 old_door_state = GetDoorState();
1635 CloseDoor(DOOR_CLOSE_1);
1637 /* save old door content */
1638 XCopyArea(display, pix[PIX_DB_DOOR], pix[PIX_DB_DOOR], gc,
1639 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE,
1640 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1);
1642 /* clear door drawing field */
1644 XFillRectangle(display, pix[PIX_DB_DOOR], gc,
1645 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE);
1647 XFillRectangle(display, drawto, gc, DX, DY, DXSIZE, DYSIZE);
1650 /* write text for request */
1651 for(ty=0; ty<13; ty++)
1659 for(tl=0,tx=0; tx<7; tl++,tx++)
1662 if (!tc || tc == 32)
1674 DrawTextExt(pix[PIX_DB_DOOR], gc,
1675 DOOR_GFX_PAGEX1 + 51 - (tl * 14)/2, SY + ty * 16,
1676 txt, FS_SMALL, FC_YELLOW);
1678 DrawTextExt(drawto, gc,
1679 DX + 51 - (tl * 14)/2, DY + 8 + ty * 16,
1680 txt, FS_SMALL, FC_YELLOW);
1682 text += tl + (tc == 32 ? 1 : 0);
1688 if (req_state & REQ_ASK)
1690 DrawYesNoButton(BUTTON_OK, DB_INIT);
1691 DrawYesNoButton(BUTTON_NO, DB_INIT);
1693 else if (req_state & REQ_CONFIRM)
1695 DrawConfirmButton(BUTTON_CONFIRM, DB_INIT);
1697 else if (req_state & REQ_PLAYER)
1699 DrawPlayerButton(BUTTON_PLAYER_1, DB_INIT);
1700 DrawPlayerButton(BUTTON_PLAYER_2, DB_INIT);
1701 DrawPlayerButton(BUTTON_PLAYER_3, DB_INIT);
1702 DrawPlayerButton(BUTTON_PLAYER_4, DB_INIT);
1706 if (req_state & REQ_ASK)
1708 MapGadget(tool_gadget[TOOL_CTRL_ID_YES]);
1709 MapGadget(tool_gadget[TOOL_CTRL_ID_NO]);
1711 else if (req_state & REQ_CONFIRM)
1713 MapGadget(tool_gadget[TOOL_CTRL_ID_CONFIRM]);
1715 else if (req_state & REQ_PLAYER)
1717 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_1]);
1718 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_2]);
1719 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_3]);
1720 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_4]);
1723 /* copy request gadgets to door backbuffer */
1724 XCopyArea(display, drawto, pix[PIX_DB_DOOR], gc,
1725 DX, DY, DXSIZE, DYSIZE,
1726 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
1732 OpenDoor(DOOR_OPEN_1);
1735 if (!(req_state & REQUEST_WAIT_FOR))
1738 if (game_status != MAINMENU)
1741 button_status = MB_RELEASED;
1743 request_gadget_id = -1;
1747 if (XPending(display))
1751 XNextEvent(display, &event);
1761 if (event.type == MotionNotify)
1768 if (!XQueryPointer(display, window, &root, &child,
1769 &root_x, &root_y, &win_x, &win_y, &mask))
1775 motion_status = TRUE;
1776 mx = ((XMotionEvent *) &event)->x;
1777 my = ((XMotionEvent *) &event)->y;
1781 motion_status = FALSE;
1782 mx = ((XButtonEvent *) &event)->x;
1783 my = ((XButtonEvent *) &event)->y;
1784 if (event.type==ButtonPress)
1785 button_status = ((XButtonEvent *) &event)->button;
1787 button_status = MB_RELEASED;
1793 if (req_state & REQ_ASK)
1794 choice = CheckYesNoButtons(mx,my,button_status);
1795 else if (req_state & REQ_CONFIRM)
1796 choice = CheckConfirmButton(mx,my,button_status);
1798 choice = CheckPlayerButtons(mx,my,button_status);
1808 case BUTTON_CONFIRM:
1809 result = TRUE | FALSE;
1812 case BUTTON_PLAYER_1:
1815 case BUTTON_PLAYER_2:
1818 case BUTTON_PLAYER_3:
1821 case BUTTON_PLAYER_4:
1830 /* this sets 'request_gadget_id' */
1831 HandleGadgets(mx, my, button_status);
1833 switch(request_gadget_id)
1835 case TOOL_CTRL_ID_YES:
1838 case TOOL_CTRL_ID_NO:
1841 case TOOL_CTRL_ID_CONFIRM:
1842 result = TRUE | FALSE;
1845 case TOOL_CTRL_ID_PLAYER_1:
1848 case TOOL_CTRL_ID_PLAYER_2:
1851 case TOOL_CTRL_ID_PLAYER_3:
1854 case TOOL_CTRL_ID_PLAYER_4:
1867 switch(XLookupKeysym((XKeyEvent *)&event,
1868 ((XKeyEvent *)&event)->state))
1881 if (req_state & REQ_PLAYER)
1886 key_joystick_mapping = 0;
1890 HandleOtherEvents(&event);
1894 else if (AnyJoystickButton() == JOY_BUTTON_NEW_PRESSED)
1896 int joy = AnyJoystick();
1898 if (joy & JOY_BUTTON_1)
1900 else if (joy & JOY_BUTTON_2)
1906 /* don't eat all CPU time */
1910 if (game_status != MAINMENU)
1915 if (!(req_state & REQ_STAY_OPEN))
1917 CloseDoor(DOOR_CLOSE_1);
1919 if (!(req_state & REQ_STAY_CLOSED) && (old_door_state & DOOR_OPEN_1))
1921 XCopyArea(display,pix[PIX_DB_DOOR],pix[PIX_DB_DOOR],gc,
1922 DOOR_GFX_PAGEX2,DOOR_GFX_PAGEY1, DXSIZE,DYSIZE,
1923 DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY1);
1924 OpenDoor(DOOR_OPEN_1);
1931 /* continue network game after request */
1932 if (options.network &&
1933 game_status == PLAYING &&
1934 req_state & REQUEST_WAIT_FOR)
1935 SendToServer_ContinuePlaying();
1941 unsigned int OpenDoor(unsigned int door_state)
1943 unsigned int new_door_state;
1945 if (door_state & DOOR_COPY_BACK)
1947 XCopyArea(display, pix[PIX_DB_DOOR], pix[PIX_DB_DOOR], gc,
1948 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE + VYSIZE,
1949 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
1950 door_state &= ~DOOR_COPY_BACK;
1953 new_door_state = MoveDoor(door_state);
1955 return(new_door_state);
1958 unsigned int CloseDoor(unsigned int door_state)
1960 unsigned int new_door_state;
1962 XCopyArea(display, backbuffer, pix[PIX_DB_DOOR], gc,
1963 DX, DY, DXSIZE, DYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
1964 XCopyArea(display, backbuffer, pix[PIX_DB_DOOR], gc,
1965 VX, VY, VXSIZE, VYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2);
1967 new_door_state = MoveDoor(door_state);
1969 return(new_door_state);
1972 unsigned int GetDoorState()
1974 return(MoveDoor(DOOR_GET_STATE));
1977 unsigned int MoveDoor(unsigned int door_state)
1979 static int door1 = DOOR_OPEN_1;
1980 static int door2 = DOOR_CLOSE_2;
1981 static unsigned long door_delay = 0;
1982 int x, start, stepsize = 2;
1983 unsigned long door_delay_value = stepsize * 5;
1985 if (door_state == DOOR_GET_STATE)
1986 return(door1 | door2);
1988 if (door1 == DOOR_OPEN_1 && door_state & DOOR_OPEN_1)
1989 door_state &= ~DOOR_OPEN_1;
1990 else if (door1 == DOOR_CLOSE_1 && door_state & DOOR_CLOSE_1)
1991 door_state &= ~DOOR_CLOSE_1;
1992 if (door2 == DOOR_OPEN_2 && door_state & DOOR_OPEN_2)
1993 door_state &= ~DOOR_OPEN_2;
1994 else if (door2 == DOOR_CLOSE_2 && door_state & DOOR_CLOSE_2)
1995 door_state &= ~DOOR_CLOSE_2;
1997 if (setup.quick_doors)
2000 door_delay_value = 0;
2001 StopSound(SND_OEFFNEN);
2004 if (door_state & DOOR_ACTION)
2006 if (!(door_state & DOOR_NO_DELAY))
2007 PlaySoundStereo(SND_OEFFNEN, PSND_MAX_RIGHT);
2009 start = ((door_state & DOOR_NO_DELAY) ? DXSIZE : 0);
2011 for(x=start; x<=DXSIZE; x+=stepsize)
2013 WaitUntilDelayReached(&door_delay, door_delay_value);
2015 if (door_state & DOOR_ACTION_1)
2017 int i = (door_state & DOOR_OPEN_1 ? DXSIZE-x : x);
2018 int j = (DXSIZE - i) / 3;
2020 XCopyArea(display, pix[PIX_DB_DOOR], drawto, gc,
2021 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1 + i/2,
2022 DXSIZE,DYSIZE - i/2, DX, DY);
2024 XFillRectangle(display, drawto, gc, DX, DY + DYSIZE - i/2, DXSIZE,i/2);
2026 XSetClipOrigin(display, clip_gc[PIX_DOOR],
2027 DX - i, (DY + j) - DOOR_GFX_PAGEY1);
2028 XCopyArea(display, pix[PIX_DOOR], drawto,clip_gc[PIX_DOOR],
2029 DXSIZE, DOOR_GFX_PAGEY1, i, 77, DX + DXSIZE - i, DY + j);
2030 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2031 DXSIZE, DOOR_GFX_PAGEY1 + 140, i, 63, DX + DXSIZE - i,
2033 XSetClipOrigin(display, clip_gc[PIX_DOOR],
2034 DX - DXSIZE + i, DY - (DOOR_GFX_PAGEY1 + j));
2035 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2036 DXSIZE - i, DOOR_GFX_PAGEY1 + j, i, 77 - j, DX, DY);
2037 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2038 DXSIZE-i, DOOR_GFX_PAGEY1 + 140, i, 63, DX, DY + 140 - j);
2040 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2041 DXSIZE - i, DOOR_GFX_PAGEY1 + 77, i, 63,
2043 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2044 DXSIZE - i, DOOR_GFX_PAGEY1 + 203, i, 77,
2046 XSetClipOrigin(display, clip_gc[PIX_DOOR],
2047 DX - i, (DY + j) - DOOR_GFX_PAGEY1);
2048 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2049 DXSIZE, DOOR_GFX_PAGEY1 + 77, i, 63,
2050 DX + DXSIZE - i, DY + 77 + j);
2051 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2052 DXSIZE, DOOR_GFX_PAGEY1 + 203, i, 77 - j,
2053 DX + DXSIZE - i, DY + 203 + j);
2055 redraw_mask |= REDRAW_DOOR_1;
2058 if (door_state & DOOR_ACTION_2)
2060 int i = (door_state & DOOR_OPEN_2 ? VXSIZE - x : x);
2061 int j = (VXSIZE - i) / 3;
2063 XCopyArea(display, pix[PIX_DB_DOOR], drawto, gc,
2064 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2 + i/2,
2065 VXSIZE, VYSIZE - i/2, VX, VY);
2067 XFillRectangle(display, drawto, gc, VX, VY + VYSIZE-i/2, VXSIZE, i/2);
2069 XSetClipOrigin(display, clip_gc[PIX_DOOR],
2070 VX - i, (VY + j) - DOOR_GFX_PAGEY2);
2071 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2072 VXSIZE, DOOR_GFX_PAGEY2, i, VYSIZE / 2, VX + VXSIZE-i, VY+j);
2073 XSetClipOrigin(display, clip_gc[PIX_DOOR],
2074 VX - VXSIZE + i, VY - (DOOR_GFX_PAGEY2 + j));
2075 XCopyArea(display, pix[PIX_DOOR], drawto,clip_gc[PIX_DOOR],
2076 VXSIZE - i, DOOR_GFX_PAGEY2 + j, i, VYSIZE / 2 - j, VX, VY);
2078 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2079 VXSIZE - i, DOOR_GFX_PAGEY2 + VYSIZE / 2, i, VYSIZE / 2,
2080 VX, VY + VYSIZE / 2 - j);
2081 XSetClipOrigin(display, clip_gc[PIX_DOOR],
2082 VX - i, (VY + j) - DOOR_GFX_PAGEY2);
2083 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2084 VXSIZE, DOOR_GFX_PAGEY2 + VYSIZE / 2, i, VYSIZE / 2 - j,
2085 VX + VXSIZE - i, VY + VYSIZE / 2 + j);
2087 redraw_mask |= REDRAW_DOOR_2;
2092 if (game_status == MAINMENU)
2097 if (setup.quick_doors)
2098 StopSound(SND_OEFFNEN);
2100 if (door_state & DOOR_ACTION_1)
2101 door1 = door_state & DOOR_ACTION_1;
2102 if (door_state & DOOR_ACTION_2)
2103 door2 = door_state & DOOR_ACTION_2;
2105 return(door1 | door2);
2108 int ReadPixel(Drawable d, int x, int y)
2110 XImage *pixel_image;
2111 unsigned long pixel_value;
2113 pixel_image = XGetImage(display, d, x, y, 1, 1, AllPlanes, ZPixmap);
2114 pixel_value = XGetPixel(pixel_image, 0, 0);
2116 XDestroyImage(pixel_image);
2121 /* ---------- new tool button stuff ---------------------------------------- */
2123 /* graphic position values for tool buttons */
2124 #define TOOL_BUTTON_YES_XPOS 2
2125 #define TOOL_BUTTON_YES_YPOS 250
2126 #define TOOL_BUTTON_YES_GFX_YPOS 0
2127 #define TOOL_BUTTON_YES_XSIZE 46
2128 #define TOOL_BUTTON_YES_YSIZE 28
2129 #define TOOL_BUTTON_NO_XPOS 52
2130 #define TOOL_BUTTON_NO_YPOS TOOL_BUTTON_YES_YPOS
2131 #define TOOL_BUTTON_NO_GFX_YPOS TOOL_BUTTON_YES_GFX_YPOS
2132 #define TOOL_BUTTON_NO_XSIZE TOOL_BUTTON_YES_XSIZE
2133 #define TOOL_BUTTON_NO_YSIZE TOOL_BUTTON_YES_YSIZE
2134 #define TOOL_BUTTON_CONFIRM_XPOS TOOL_BUTTON_YES_XPOS
2135 #define TOOL_BUTTON_CONFIRM_YPOS TOOL_BUTTON_YES_YPOS
2136 #define TOOL_BUTTON_CONFIRM_GFX_YPOS 30
2137 #define TOOL_BUTTON_CONFIRM_XSIZE 96
2138 #define TOOL_BUTTON_CONFIRM_YSIZE TOOL_BUTTON_YES_YSIZE
2139 #define TOOL_BUTTON_PLAYER_XSIZE 30
2140 #define TOOL_BUTTON_PLAYER_YSIZE 30
2141 #define TOOL_BUTTON_PLAYER_GFX_XPOS 5
2142 #define TOOL_BUTTON_PLAYER_GFX_YPOS 185
2143 #define TOOL_BUTTON_PLAYER_XPOS (5 + TOOL_BUTTON_PLAYER_XSIZE / 2)
2144 #define TOOL_BUTTON_PLAYER_YPOS (215 - TOOL_BUTTON_PLAYER_YSIZE / 2)
2145 #define TOOL_BUTTON_PLAYER1_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2146 + 0 * TOOL_BUTTON_PLAYER_XSIZE)
2147 #define TOOL_BUTTON_PLAYER2_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2148 + 1 * TOOL_BUTTON_PLAYER_XSIZE)
2149 #define TOOL_BUTTON_PLAYER3_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2150 + 0 * TOOL_BUTTON_PLAYER_XSIZE)
2151 #define TOOL_BUTTON_PLAYER4_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2152 + 1 * TOOL_BUTTON_PLAYER_XSIZE)
2153 #define TOOL_BUTTON_PLAYER1_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2154 + 0 * TOOL_BUTTON_PLAYER_YSIZE)
2155 #define TOOL_BUTTON_PLAYER2_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2156 + 0 * TOOL_BUTTON_PLAYER_YSIZE)
2157 #define TOOL_BUTTON_PLAYER3_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2158 + 1 * TOOL_BUTTON_PLAYER_YSIZE)
2159 #define TOOL_BUTTON_PLAYER4_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2160 + 1 * TOOL_BUTTON_PLAYER_YSIZE)
2169 } toolbutton_info[NUM_TOOL_BUTTONS] =
2172 TOOL_BUTTON_YES_XPOS, TOOL_BUTTON_YES_GFX_YPOS,
2173 TOOL_BUTTON_YES_XPOS, TOOL_BUTTON_YES_YPOS,
2174 TOOL_BUTTON_YES_XSIZE, TOOL_BUTTON_YES_YSIZE,
2179 TOOL_BUTTON_NO_XPOS, TOOL_BUTTON_NO_GFX_YPOS,
2180 TOOL_BUTTON_NO_XPOS, TOOL_BUTTON_NO_YPOS,
2181 TOOL_BUTTON_NO_XSIZE, TOOL_BUTTON_NO_YSIZE,
2186 TOOL_BUTTON_CONFIRM_XPOS, TOOL_BUTTON_CONFIRM_GFX_YPOS,
2187 TOOL_BUTTON_CONFIRM_XPOS, TOOL_BUTTON_CONFIRM_YPOS,
2188 TOOL_BUTTON_CONFIRM_XSIZE, TOOL_BUTTON_CONFIRM_YSIZE,
2189 TOOL_CTRL_ID_CONFIRM,
2193 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2194 TOOL_BUTTON_PLAYER1_XPOS, TOOL_BUTTON_PLAYER1_YPOS,
2195 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2196 TOOL_CTRL_ID_PLAYER_1,
2200 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2201 TOOL_BUTTON_PLAYER2_XPOS, TOOL_BUTTON_PLAYER2_YPOS,
2202 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2203 TOOL_CTRL_ID_PLAYER_2,
2207 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2208 TOOL_BUTTON_PLAYER3_XPOS, TOOL_BUTTON_PLAYER3_YPOS,
2209 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2210 TOOL_CTRL_ID_PLAYER_3,
2214 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2215 TOOL_BUTTON_PLAYER4_XPOS, TOOL_BUTTON_PLAYER4_YPOS,
2216 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2217 TOOL_CTRL_ID_PLAYER_4,
2222 void CreateToolButtons()
2226 for (i=0; i<NUM_TOOL_BUTTONS; i++)
2228 Pixmap gd_pixmap = pix[PIX_DOOR];
2229 Pixmap deco_pixmap = 0;
2230 int deco_x, deco_y, deco_xpos, deco_ypos;
2231 struct GadgetInfo *gi;
2232 unsigned long event_mask;
2233 int gd_xoffset, gd_yoffset;
2234 int gd_x1, gd_x2, gd_y;
2237 event_mask = GD_EVENT_RELEASED;
2239 gd_xoffset = toolbutton_info[i].xpos;
2240 gd_yoffset = toolbutton_info[i].ypos;
2241 gd_x1 = DOOR_GFX_PAGEX4 + gd_xoffset;
2242 gd_x2 = DOOR_GFX_PAGEX3 + gd_xoffset;
2243 gd_y = DOOR_GFX_PAGEY1 + gd_yoffset;
2245 if (id >= TOOL_CTRL_ID_PLAYER_1 && id <= TOOL_CTRL_ID_PLAYER_4)
2247 getMiniGraphicSource(GFX_SPIELER1 + id - TOOL_CTRL_ID_PLAYER_1,
2248 &deco_pixmap, &deco_x, &deco_y);
2249 deco_xpos = (toolbutton_info[i].width - MINI_TILEX) / 2;
2250 deco_ypos = (toolbutton_info[i].height - MINI_TILEY) / 2;
2253 gi = CreateGadget(GDI_CUSTOM_ID, id,
2254 GDI_INFO_TEXT, toolbutton_info[i].infotext,
2255 GDI_X, DX + toolbutton_info[i].x,
2256 GDI_Y, DY + toolbutton_info[i].y,
2257 GDI_WIDTH, toolbutton_info[i].width,
2258 GDI_HEIGHT, toolbutton_info[i].height,
2259 GDI_TYPE, GD_TYPE_NORMAL_BUTTON,
2260 GDI_STATE, GD_BUTTON_UNPRESSED,
2261 GDI_DESIGN_UNPRESSED, gd_pixmap, gd_x1, gd_y,
2262 GDI_DESIGN_PRESSED, gd_pixmap, gd_x2, gd_y,
2263 GDI_DECORATION_DESIGN, deco_pixmap, deco_x, deco_y,
2264 GDI_DECORATION_POSITION, deco_xpos, deco_ypos,
2265 GDI_DECORATION_SIZE, MINI_TILEX, MINI_TILEY,
2266 GDI_DECORATION_SHIFTING, 1, 1,
2267 GDI_EVENT_MASK, event_mask,
2268 GDI_CALLBACK_ACTION, HandleToolButtons,
2272 Error(ERR_EXIT, "cannot create gadget");
2274 tool_gadget[id] = gi;
2278 static void UnmapToolButtons()
2282 for (i=0; i<NUM_TOOL_BUTTONS; i++)
2283 UnmapGadget(tool_gadget[i]);
2286 static void HandleToolButtons(struct GadgetInfo *gi)
2288 request_gadget_id = gi->custom_id;
2292 int id = gi->custom_id;
2294 if (game_status != PLAYING)
2299 case GAME_CTRL_ID_STOP:
2302 CloseDoor(DOOR_CLOSE_1);
2303 game_status = MAINMENU;
2308 if (Request("Do you really want to quit the game ?",
2309 REQ_ASK | REQ_STAY_CLOSED))
2312 if (options.network)
2313 SendToServer_StopPlaying();
2317 game_status = MAINMENU;
2322 OpenDoor(DOOR_OPEN_1 | DOOR_COPY_BACK);
2325 case GAME_CTRL_ID_PAUSE:
2326 if (options.network)
2330 SendToServer_ContinuePlaying();
2332 SendToServer_PausePlaying();
2339 case GAME_CTRL_ID_PLAY:
2343 if (options.network)
2344 SendToServer_ContinuePlaying();
2348 tape.pausing = FALSE;
2349 DrawVideoDisplay(VIDEO_STATE_PAUSE_OFF,0);
2354 case SOUND_CTRL_ID_MUSIC:
2355 if (setup.sound_music)
2357 setup.sound_music = FALSE;
2358 FadeSound(background_loop[level_nr % num_bg_loops]);
2360 else if (sound_loops_allowed)
2362 setup.sound = setup.sound_music = TRUE;
2363 PlaySoundLoop(background_loop[level_nr % num_bg_loops]);
2367 case SOUND_CTRL_ID_LOOPS:
2368 if (setup.sound_loops)
2369 setup.sound_loops = FALSE;
2370 else if (sound_loops_allowed)
2371 setup.sound = setup.sound_loops = TRUE;
2374 case SOUND_CTRL_ID_SIMPLE:
2375 if (setup.sound_simple)
2376 setup.sound_simple = FALSE;
2377 else if (sound_status==SOUND_AVAILABLE)
2378 setup.sound = setup.sound_simple = TRUE;
2390 int el2gfx(int element)
2394 case EL_LEERRAUM: return -1;
2395 case EL_ERDREICH: return GFX_ERDREICH;
2396 case EL_MAUERWERK: return GFX_MAUERWERK;
2397 case EL_FELSBODEN: return GFX_FELSBODEN;
2398 case EL_FELSBROCKEN: return GFX_FELSBROCKEN;
2399 case EL_SCHLUESSEL: return GFX_SCHLUESSEL;
2400 case EL_EDELSTEIN: return GFX_EDELSTEIN;
2401 case EL_AUSGANG_ZU: return GFX_AUSGANG_ZU;
2402 case EL_AUSGANG_ACT: return GFX_AUSGANG_ACT;
2403 case EL_AUSGANG_AUF: return GFX_AUSGANG_AUF;
2404 case EL_SPIELFIGUR: return GFX_SPIELFIGUR;
2405 case EL_SPIELER1: return GFX_SPIELER1;
2406 case EL_SPIELER2: return GFX_SPIELER2;
2407 case EL_SPIELER3: return GFX_SPIELER3;
2408 case EL_SPIELER4: return GFX_SPIELER4;
2409 case EL_KAEFER: return GFX_KAEFER;
2410 case EL_KAEFER_R: return GFX_KAEFER_R;
2411 case EL_KAEFER_O: return GFX_KAEFER_O;
2412 case EL_KAEFER_L: return GFX_KAEFER_L;
2413 case EL_KAEFER_U: return GFX_KAEFER_U;
2414 case EL_FLIEGER: return GFX_FLIEGER;
2415 case EL_FLIEGER_R: return GFX_FLIEGER_R;
2416 case EL_FLIEGER_O: return GFX_FLIEGER_O;
2417 case EL_FLIEGER_L: return GFX_FLIEGER_L;
2418 case EL_FLIEGER_U: return GFX_FLIEGER_U;
2419 case EL_BUTTERFLY: return GFX_BUTTERFLY;
2420 case EL_BUTTERFLY_R: return GFX_BUTTERFLY_R;
2421 case EL_BUTTERFLY_O: return GFX_BUTTERFLY_O;
2422 case EL_BUTTERFLY_L: return GFX_BUTTERFLY_L;
2423 case EL_BUTTERFLY_U: return GFX_BUTTERFLY_U;
2424 case EL_FIREFLY: return GFX_FIREFLY;
2425 case EL_FIREFLY_R: return GFX_FIREFLY_R;
2426 case EL_FIREFLY_O: return GFX_FIREFLY_O;
2427 case EL_FIREFLY_L: return GFX_FIREFLY_L;
2428 case EL_FIREFLY_U: return GFX_FIREFLY_U;
2429 case EL_MAMPFER: return GFX_MAMPFER;
2430 case EL_ROBOT: return GFX_ROBOT;
2431 case EL_BETON: return GFX_BETON;
2432 case EL_DIAMANT: return GFX_DIAMANT;
2433 case EL_MORAST_LEER: return GFX_MORAST_LEER;
2434 case EL_MORAST_VOLL: return GFX_MORAST_VOLL;
2435 case EL_TROPFEN: return GFX_TROPFEN;
2436 case EL_BOMBE: return GFX_BOMBE;
2437 case EL_SIEB_INAKTIV: return GFX_SIEB_INAKTIV;
2438 case EL_SIEB_LEER: return GFX_SIEB_LEER;
2439 case EL_SIEB_VOLL: return GFX_SIEB_VOLL;
2440 case EL_SIEB_TOT: return GFX_SIEB_TOT;
2441 case EL_SALZSAEURE: return GFX_SALZSAEURE;
2442 case EL_AMOEBE_TOT: return GFX_AMOEBE_TOT;
2443 case EL_AMOEBE_NASS: return GFX_AMOEBE_NASS;
2444 case EL_AMOEBE_NORM: return GFX_AMOEBE_NORM;
2445 case EL_AMOEBE_VOLL: return GFX_AMOEBE_VOLL;
2446 case EL_AMOEBE_BD: return GFX_AMOEBE_BD;
2447 case EL_AMOEBA2DIAM: return GFX_AMOEBA2DIAM;
2448 case EL_KOKOSNUSS: return GFX_KOKOSNUSS;
2449 case EL_LIFE: return GFX_LIFE;
2450 case EL_LIFE_ASYNC: return GFX_LIFE_ASYNC;
2451 case EL_DYNAMIT: return GFX_DYNAMIT;
2452 case EL_BADEWANNE: return GFX_BADEWANNE;
2453 case EL_BADEWANNE1: return GFX_BADEWANNE1;
2454 case EL_BADEWANNE2: return GFX_BADEWANNE2;
2455 case EL_BADEWANNE3: return GFX_BADEWANNE3;
2456 case EL_BADEWANNE4: return GFX_BADEWANNE4;
2457 case EL_BADEWANNE5: return GFX_BADEWANNE5;
2458 case EL_ABLENK_AUS: return GFX_ABLENK_AUS;
2459 case EL_ABLENK_EIN: return GFX_ABLENK_EIN;
2460 case EL_SCHLUESSEL1: return GFX_SCHLUESSEL1;
2461 case EL_SCHLUESSEL2: return GFX_SCHLUESSEL2;
2462 case EL_SCHLUESSEL3: return GFX_SCHLUESSEL3;
2463 case EL_SCHLUESSEL4: return GFX_SCHLUESSEL4;
2464 case EL_PFORTE1: return GFX_PFORTE1;
2465 case EL_PFORTE2: return GFX_PFORTE2;
2466 case EL_PFORTE3: return GFX_PFORTE3;
2467 case EL_PFORTE4: return GFX_PFORTE4;
2468 case EL_PFORTE1X: return GFX_PFORTE1X;
2469 case EL_PFORTE2X: return GFX_PFORTE2X;
2470 case EL_PFORTE3X: return GFX_PFORTE3X;
2471 case EL_PFORTE4X: return GFX_PFORTE4X;
2472 case EL_DYNAMIT_AUS: return GFX_DYNAMIT_AUS;
2473 case EL_PACMAN: return GFX_PACMAN;
2474 case EL_PACMAN_R: return GFX_PACMAN_R;
2475 case EL_PACMAN_O: return GFX_PACMAN_O;
2476 case EL_PACMAN_L: return GFX_PACMAN_L;
2477 case EL_PACMAN_U: return GFX_PACMAN_U;
2478 case EL_UNSICHTBAR: return GFX_UNSICHTBAR;
2479 case EL_ERZ_EDEL: return GFX_ERZ_EDEL;
2480 case EL_ERZ_DIAM: return GFX_ERZ_DIAM;
2481 case EL_BIRNE_AUS: return GFX_BIRNE_AUS;
2482 case EL_BIRNE_EIN: return GFX_BIRNE_EIN;
2483 case EL_ZEIT_VOLL: return GFX_ZEIT_VOLL;
2484 case EL_ZEIT_LEER: return GFX_ZEIT_LEER;
2485 case EL_MAUER_LEBT: return GFX_MAUER_LEBT;
2486 case EL_MAUER_X: return GFX_MAUER_X;
2487 case EL_MAUER_Y: return GFX_MAUER_Y;
2488 case EL_MAUER_XY: return GFX_MAUER_XY;
2489 case EL_EDELSTEIN_BD: return GFX_EDELSTEIN_BD;
2490 case EL_EDELSTEIN_GELB: return GFX_EDELSTEIN_GELB;
2491 case EL_EDELSTEIN_ROT: return GFX_EDELSTEIN_ROT;
2492 case EL_EDELSTEIN_LILA: return GFX_EDELSTEIN_LILA;
2493 case EL_ERZ_EDEL_BD: return GFX_ERZ_EDEL_BD;
2494 case EL_ERZ_EDEL_GELB: return GFX_ERZ_EDEL_GELB;
2495 case EL_ERZ_EDEL_ROT: return GFX_ERZ_EDEL_ROT;
2496 case EL_ERZ_EDEL_LILA: return GFX_ERZ_EDEL_LILA;
2497 case EL_MAMPFER2: return GFX_MAMPFER2;
2498 case EL_SIEB2_INAKTIV: return GFX_SIEB2_INAKTIV;
2499 case EL_SIEB2_LEER: return GFX_SIEB2_LEER;
2500 case EL_SIEB2_VOLL: return GFX_SIEB2_VOLL;
2501 case EL_SIEB2_TOT: return GFX_SIEB2_TOT;
2502 case EL_DYNABOMB: return GFX_DYNABOMB;
2503 case EL_DYNABOMB_NR: return GFX_DYNABOMB_NR;
2504 case EL_DYNABOMB_SZ: return GFX_DYNABOMB_SZ;
2505 case EL_DYNABOMB_XL: return GFX_DYNABOMB_XL;
2506 case EL_SOKOBAN_OBJEKT: return GFX_SOKOBAN_OBJEKT;
2507 case EL_SOKOBAN_FELD_LEER: return GFX_SOKOBAN_FELD_LEER;
2508 case EL_SOKOBAN_FELD_VOLL: return GFX_SOKOBAN_FELD_VOLL;
2509 case EL_MAULWURF: return GFX_MAULWURF;
2510 case EL_PINGUIN: return GFX_PINGUIN;
2511 case EL_SCHWEIN: return GFX_SCHWEIN;
2512 case EL_DRACHE: return GFX_DRACHE;
2513 case EL_SONDE: return GFX_SONDE;
2514 case EL_PFEIL_L: return GFX_PFEIL_L;
2515 case EL_PFEIL_R: return GFX_PFEIL_R;
2516 case EL_PFEIL_O: return GFX_PFEIL_O;
2517 case EL_PFEIL_U: return GFX_PFEIL_U;
2518 case EL_SPEED_PILL: return GFX_SPEED_PILL;
2519 case EL_SP_TERMINAL_ACTIVE: return GFX_SP_TERMINAL;
2520 case EL_SP_BUG_ACTIVE: return GFX_SP_BUG_ACTIVE;
2521 case EL_INVISIBLE_STEEL: return GFX_INVISIBLE_STEEL;
2525 if (IS_CHAR(element))
2526 return GFX_CHAR_START + (element - EL_CHAR_START);
2527 else if (element >= EL_SP_START && element <= EL_SP_END)
2529 int nr_element = element - EL_SP_START;
2530 int gfx_per_line = 8;
2532 (nr_element / gfx_per_line) * MORE_PER_LINE +
2533 (nr_element % gfx_per_line);
2535 return GFX_START_ROCKSMORE + nr_graphic;