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)
130 XCopyArea(display,backbuffer,window,gc,
131 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE,
136 int fx = FX, fy = FY;
138 if (setup.soft_scrolling)
140 fx += (ScreenMovDir & (MV_LEFT | MV_RIGHT) ? ScreenGfxPos : 0);
141 fy += (ScreenMovDir & (MV_UP | MV_DOWN) ? ScreenGfxPos : 0);
144 if (setup.soft_scrolling ||
145 ABS(ScreenMovPos) + ScrollStepSize == TILEX ||
146 ABS(ScreenMovPos) == ScrollStepSize ||
147 redraw_tiles > REDRAWTILES_THRESHOLD)
149 XCopyArea(display, buffer, window, gc, fx, fy, SXSIZE, SYSIZE, SX, SY);
153 printf("redrawing all (ScreenGfxPos == %d) because %s\n",
155 (setup.soft_scrolling ?
156 "setup.soft_scrolling" :
157 ABS(ScreenGfxPos) + ScrollStepSize == TILEX ?
158 "ABS(ScreenGfxPos) + ScrollStepSize == TILEX" :
159 ABS(ScreenGfxPos) == ScrollStepSize ?
160 "ABS(ScreenGfxPos) == ScrollStepSize" :
161 "redraw_tiles > REDRAWTILES_THRESHOLD"));
166 redraw_mask &= ~REDRAW_MAIN;
169 if (redraw_mask & REDRAW_DOORS)
171 if (redraw_mask & REDRAW_DOOR_1)
172 XCopyArea(display,backbuffer,window,gc,
173 DX,DY, DXSIZE,DYSIZE,
175 if (redraw_mask & REDRAW_DOOR_2)
177 if ((redraw_mask & REDRAW_DOOR_2) == REDRAW_DOOR_2)
178 XCopyArea(display,backbuffer,window,gc,
179 VX,VY, VXSIZE,VYSIZE,
183 if (redraw_mask & REDRAW_VIDEO_1)
184 XCopyArea(display,backbuffer,window,gc,
185 VX+VIDEO_DISPLAY1_XPOS,VY+VIDEO_DISPLAY1_YPOS,
186 VIDEO_DISPLAY_XSIZE,VIDEO_DISPLAY_YSIZE,
187 VX+VIDEO_DISPLAY1_XPOS,VY+VIDEO_DISPLAY1_YPOS);
188 if (redraw_mask & REDRAW_VIDEO_2)
189 XCopyArea(display,backbuffer,window,gc,
190 VX+VIDEO_DISPLAY2_XPOS,VY+VIDEO_DISPLAY2_YPOS,
191 VIDEO_DISPLAY_XSIZE,VIDEO_DISPLAY_YSIZE,
192 VX+VIDEO_DISPLAY2_XPOS,VY+VIDEO_DISPLAY2_YPOS);
193 if (redraw_mask & REDRAW_VIDEO_3)
194 XCopyArea(display,backbuffer,window,gc,
195 VX+VIDEO_CONTROL_XPOS,VY+VIDEO_CONTROL_YPOS,
196 VIDEO_CONTROL_XSIZE,VIDEO_CONTROL_YSIZE,
197 VX+VIDEO_CONTROL_XPOS,VY+VIDEO_CONTROL_YPOS);
200 if (redraw_mask & REDRAW_DOOR_3)
201 XCopyArea(display, backbuffer, window, gc,
202 EX, EY, EXSIZE, EYSIZE,
204 redraw_mask &= ~REDRAW_DOORS;
207 if (redraw_mask & REDRAW_MICROLEVEL)
209 XCopyArea(display,backbuffer,window,gc,
210 MICROLEV_XPOS, MICROLEV_YPOS, MICROLEV_XSIZE, MICROLEV_YSIZE,
211 MICROLEV_XPOS, MICROLEV_YPOS);
212 XCopyArea(display,backbuffer,window,gc,
213 SX, MICROLABEL_YPOS, SXSIZE, FONT4_YSIZE,
214 SX, MICROLABEL_YPOS);
215 redraw_mask &= ~REDRAW_MICROLEVEL;
218 if (redraw_mask & REDRAW_TILES)
220 for(x=0; x<SCR_FIELDX; x++)
221 for(y=0; y<SCR_FIELDY; y++)
222 if (redraw[redraw_x1 + x][redraw_y1 + y])
223 XCopyArea(display,buffer,window,gc,
224 FX+x*TILEX,FX+y*TILEY, TILEX,TILEY,
225 SX+x*TILEX,SY+y*TILEY);
230 for(x=0; x<MAX_BUF_XSIZE; x++)
231 for(y=0; y<MAX_BUF_YSIZE; y++)
240 long fading_delay = 300;
242 if (setup.fading && (redraw_mask & REDRAW_FIELD))
249 XFillRectangle(display,window,gc,
250 REAL_SX,REAL_SY,FULL_SXSIZE,FULL_SYSIZE);
253 for(i=0;i<2*FULL_SYSIZE;i++)
255 for(y=0;y<FULL_SYSIZE;y++)
257 XCopyArea(display,backbuffer,window,gc,
258 REAL_SX,REAL_SY+i, FULL_SXSIZE,1, REAL_SX,REAL_SY+i);
266 for(i=1;i<FULL_SYSIZE;i+=2)
267 XCopyArea(display,backbuffer,window,gc,
268 REAL_SX,REAL_SY+i, FULL_SXSIZE,1, REAL_SX,REAL_SY+i);
274 XSetClipOrigin(display,clip_gc[PIX_FADEMASK],0,0);
275 XCopyArea(display,backbuffer,window,clip_gc[PIX_FADEMASK],
276 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE, REAL_SX,REAL_SY);
280 XSetClipOrigin(display,clip_gc[PIX_FADEMASK],-1,-1);
281 XCopyArea(display,backbuffer,window,clip_gc[PIX_FADEMASK],
282 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE, REAL_SX,REAL_SY);
286 XSetClipOrigin(display,clip_gc[PIX_FADEMASK],0,-1);
287 XCopyArea(display,backbuffer,window,clip_gc[PIX_FADEMASK],
288 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE, REAL_SX,REAL_SY);
292 XSetClipOrigin(display,clip_gc[PIX_FADEMASK],-1,0);
293 XCopyArea(display,backbuffer,window,clip_gc[PIX_FADEMASK],
294 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE, REAL_SX,REAL_SY);
298 redraw_mask &= ~REDRAW_MAIN;
307 XFillRectangle(display, backbuffer, gc,
308 REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE);
310 if (setup.soft_scrolling && game_status == PLAYING)
312 XFillRectangle(display, fieldbuffer, gc, 0, 0, FXSIZE, FYSIZE);
313 SetDrawtoField(DRAW_BUFFERED);
316 SetDrawtoField(DRAW_BACKBUFFER);
318 if (setup.direct_draw && game_status == PLAYING)
320 XFillRectangle(display, window, gc,
321 REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE);
322 SetDrawtoField(DRAW_DIRECT);
325 redraw_mask |= REDRAW_FIELD;
328 void DrawTextFCentered(int y, int font_type, char *format, ...)
330 char buffer[FULL_SXSIZE / FONT3_XSIZE + 10];
334 font_xsize = (font_type < FC_SPECIAL1 ? FONT2_XSIZE :
335 font_type < FC_SPECIAL2 ? FONT3_XSIZE : FONT4_XSIZE);
337 va_start(ap, format);
338 vsprintf(buffer, format, ap);
341 DrawText(SX + (SXSIZE - strlen(buffer) * font_xsize) / 2, SY + y,
342 buffer, FS_SMALL, font_type);
345 void DrawTextF(int x, int y, int font_type, char *format, ...)
347 char buffer[FULL_SXSIZE / FONT3_XSIZE + 10];
350 va_start(ap, format);
351 vsprintf(buffer, format, ap);
354 DrawText(SX + x, SY + y, buffer, FS_SMALL, font_type);
357 void DrawText(int x, int y, char *text, int font_size, int font_type)
359 DrawTextExt(drawto, gc, x, y, text, font_size, font_type);
362 redraw_mask |= REDRAW_FIELD;
364 redraw_mask |= REDRAW_DOOR_1;
367 void DrawTextExt(Drawable d, GC gc, int x, int y,
368 char *text, int font_size, int font_type)
370 int font_width, font_height, font_start;
372 boolean print_inverse = FALSE;
374 if (font_size != FS_SMALL && font_size != FS_BIG)
375 font_size = FS_SMALL;
376 if (font_type < FC_RED || font_type > FC_SPECIAL2)
379 font_width = (font_size == FS_BIG ? FONT1_XSIZE :
380 font_type < FC_SPECIAL1 ? FONT2_XSIZE :
381 font_type < FC_SPECIAL2 ? FONT3_XSIZE : FONT4_XSIZE);
382 font_height = (font_size == FS_BIG ? FONT1_XSIZE :
383 font_type < FC_SPECIAL2 ? FONT2_XSIZE : FONT4_XSIZE);
384 font_pixmap = (font_size == FS_BIG ? PIX_BIGFONT : PIX_SMALLFONT);
385 font_start = (font_type * (font_size == FS_BIG ? FONT1_YSIZE : FONT2_YSIZE) *
386 FONT_LINES_PER_FONT);
392 if (c == '~' && font_size == FS_SMALL && font_type <= FC_YELLOW)
394 print_inverse = TRUE;
398 if (c >= 'a' && c <= 'z')
400 else if (c == 'ä' || c == 'Ä')
402 else if (c == 'ö' || c == 'Ö')
404 else if (c == 'ü' || c == 'Ü')
407 if (c >= 32 && c <= 95)
409 int src_x = ((c - 32) % FONT_CHARS_PER_LINE) * font_width;
410 int src_y = ((c - 32) / FONT_CHARS_PER_LINE) * font_height + font_start;
411 int dest_x = x, dest_y = y;
415 XCopyArea(display, pix[font_pixmap], d, gc,
416 FONT_CHARS_PER_LINE * font_width,
417 3 * font_height + font_start,
418 font_width, font_height, x, y);
420 XSetClipOrigin(display, clip_gc[font_pixmap],
421 dest_x - src_x, dest_y - src_y);
422 XCopyArea(display, pix[font_pixmap], drawto, clip_gc[font_pixmap],
423 0, 0, font_width, font_height, dest_x, dest_y);
426 XCopyArea(display, pix[font_pixmap], d, gc,
427 src_x, src_y, font_width, font_height, dest_x, dest_y);
434 void DrawAllPlayers()
438 for(i=0; i<MAX_PLAYERS; i++)
439 if (stored_player[i].active)
440 DrawPlayer(&stored_player[i]);
443 void DrawPlayerField(int x, int y)
448 DrawPlayer(PLAYERINFO(x,y));
451 void DrawPlayer(struct PlayerInfo *player)
453 int jx = player->jx, jy = player->jy;
454 int last_jx = player->last_jx, last_jy = player->last_jy;
455 int next_jx = jx + (jx - last_jx), next_jy = jy + (jy - last_jy);
456 int sx = SCREENX(jx), sy = SCREENY(jy);
457 int sxx = 0, syy = 0;
458 int element = Feld[jx][jy];
461 if (!player->active || player->gone ||
462 !IN_SCR_FIELD(SCREENX(last_jx), SCREENY(last_jy)))
466 if (!IN_LEV_FIELD(jx,jy))
468 printf("DrawPlayerField(): x = %d, y = %d\n",jx,jy);
469 printf("DrawPlayerField(): sx = %d, sy = %d\n",sx,sy);
470 printf("DrawPlayerField(): This should never happen!\n");
475 if (element == EL_EXPLODING)
478 /* draw things in the field the player is leaving, if needed */
480 if (last_jx != jx || last_jy != jy)
482 if (Store[last_jx][last_jy])
484 DrawLevelElement(last_jx, last_jy, Store[last_jx][last_jy]);
485 DrawLevelFieldThruMask(last_jx, last_jy);
487 else if (Feld[last_jx][last_jy] == EL_DYNAMIT)
488 DrawDynamite(last_jx, last_jy);
490 DrawLevelField(last_jx, last_jy);
492 if (player->Pushing && IN_SCR_FIELD(SCREENX(next_jx), SCREENY(next_jy)))
496 if (Feld[next_jx][next_jy] == EL_SOKOBAN_FELD_VOLL)
497 DrawLevelElement(next_jx, next_jy, EL_SOKOBAN_FELD_LEER);
499 DrawLevelElement(next_jx, next_jy, EL_LEERRAUM);
502 DrawLevelField(next_jx, next_jy);
506 if (!IN_SCR_FIELD(sx, sy))
509 if (setup.direct_draw)
510 SetDrawtoField(DRAW_BUFFERED);
512 /* draw things behind the player, if needed */
515 DrawLevelElement(jx, jy, Store[jx][jy]);
516 else if (element != EL_DYNAMIT && element != EL_DYNABOMB)
517 DrawLevelField(jx, jy);
519 /* draw player himself */
521 if (player->MovDir == MV_LEFT)
522 graphic = (player->Pushing ? GFX_SPIELER1_PUSH_LEFT : GFX_SPIELER1_LEFT);
523 else if (player->MovDir == MV_RIGHT)
524 graphic = (player->Pushing ? GFX_SPIELER1_PUSH_RIGHT : GFX_SPIELER1_RIGHT);
525 else if (player->MovDir == MV_UP)
526 graphic = GFX_SPIELER1_UP;
527 else /* MV_DOWN || MV_NO_MOVING */
528 graphic = GFX_SPIELER1_DOWN;
530 graphic += player->index_nr * 3*HEROES_PER_LINE;
531 graphic += player->Frame;
535 if (player->MovDir == MV_LEFT || player->MovDir == MV_RIGHT)
536 sxx = player->GfxPos;
538 syy = player->GfxPos;
541 if (!setup.soft_scrolling && ScreenMovPos)
544 DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, NO_CUTTING);
546 if (player->Pushing && player->GfxPos)
548 int px = SCREENX(next_jx), py = SCREENY(next_jy);
550 if (Feld[jx][jy] == EL_SOKOBAN_FELD_LEER ||
551 Feld[next_jx][next_jy] == EL_SOKOBAN_FELD_VOLL)
552 DrawGraphicShiftedThruMask(px, py, sxx, syy, GFX_SOKOBAN_OBJEKT,
556 int element = Feld[next_jx][next_jy];
557 int graphic = el2gfx(element);
559 if (element == EL_FELSBROCKEN && sxx)
561 int phase = (player->GfxPos / (TILEX/4));
563 if (player->MovDir == MV_LEFT)
566 graphic += (phase+4)%4;
569 DrawGraphicShifted(px, py, sxx, syy, graphic, NO_CUTTING, NO_MASKING);
573 /* draw things in front of player (EL_DYNAMIT || EL_DYNABOMB) */
575 if (element == EL_DYNAMIT || element == EL_DYNABOMB)
577 graphic = el2gfx(element);
579 if (element == EL_DYNAMIT)
581 if ((phase = (96 - MovDelay[jx][jy]) / 12) > 6)
586 if ((phase = ((96 - MovDelay[jx][jy]) / 6) % 8) > 3)
590 if (game_emulation == EMU_SUPAPLEX)
591 DrawGraphic(sx, sy, GFX_SP_DISK_RED);
593 DrawGraphicThruMask(sx, sy, graphic + phase);
596 if ((last_jx != jx || last_jy != jy) &&
597 Feld[last_jx][last_jy] == EL_EXPLODING)
599 int phase = Frame[last_jx][last_jy];
603 DrawGraphicThruMask(SCREENX(last_jx), SCREENY(last_jy),
604 GFX_EXPLOSION + ((phase - 1) / delay - 1));
607 if (setup.direct_draw)
609 int dest_x = SX + SCREENX(MIN(jx, last_jx)) * TILEX;
610 int dest_y = SY + SCREENY(MIN(jy, last_jy)) * TILEY;
611 int x_size = TILEX * (1 + ABS(jx - last_jx));
612 int y_size = TILEY * (1 + ABS(jy - last_jy));
614 XCopyArea(display, drawto_field, window, gc,
615 dest_x, dest_y, x_size, y_size, dest_x, dest_y);
616 SetDrawtoField(DRAW_DIRECT);
619 MarkTileDirty(sx,sy);
622 static int getGraphicAnimationPhase(int frames, int delay, int mode)
626 if (mode == ANIM_OSCILLATE)
628 int max_anim_frames = 2 * frames - 2;
629 phase = (FrameCounter % (delay * max_anim_frames)) / delay;
630 phase = (phase < frames ? phase : max_anim_frames - phase);
633 phase = (FrameCounter % (delay * frames)) / delay;
635 if (mode == ANIM_REVERSE)
641 void DrawGraphicAnimationExt(int x, int y, int graphic,
642 int frames, int delay, int mode, int mask_mode)
644 int phase = getGraphicAnimationPhase(frames, delay, mode);
646 if (!(FrameCounter % delay) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
648 if (mask_mode == USE_MASKING)
649 DrawGraphicThruMask(SCREENX(x), SCREENY(y), graphic + phase);
651 DrawGraphic(SCREENX(x), SCREENY(y), graphic + phase);
655 void DrawGraphicAnimation(int x, int y, int graphic,
656 int frames, int delay, int mode)
658 DrawGraphicAnimationExt(x, y, graphic, frames, delay, mode, NO_MASKING);
661 void DrawGraphicAnimationThruMask(int x, int y, int graphic,
662 int frames, int delay, int mode)
664 DrawGraphicAnimationExt(x, y, graphic, frames, delay, mode, USE_MASKING);
667 void DrawGraphic(int x, int y, int graphic)
670 if (!IN_SCR_FIELD(x,y))
672 printf("DrawGraphic(): x = %d, y = %d, graphic = %d\n",x,y,graphic);
673 printf("DrawGraphic(): This should never happen!\n");
678 DrawGraphicExt(drawto_field, gc, FX + x*TILEX, FY + y*TILEY, graphic);
682 void DrawGraphicExt(Drawable d, GC gc, int x, int y, int graphic)
684 if (graphic >= GFX_START_ROCKSSCREEN && graphic <= GFX_END_ROCKSSCREEN)
686 graphic -= GFX_START_ROCKSSCREEN;
687 XCopyArea(display, pix[PIX_BACK], d, gc,
688 SX + (graphic % GFX_PER_LINE) * TILEX,
689 SY + (graphic / GFX_PER_LINE) * TILEY,
692 else if (graphic >= GFX_START_ROCKSMORE && graphic <= GFX_END_ROCKSMORE)
694 graphic -= GFX_START_ROCKSMORE;
695 XCopyArea(display, pix[PIX_MORE], d, gc,
696 (graphic % MORE_PER_LINE) * TILEX,
697 (graphic / MORE_PER_LINE) * TILEY,
700 else if (graphic >= GFX_START_ROCKSHEROES && graphic <= GFX_END_ROCKSHEROES)
702 graphic -= GFX_START_ROCKSHEROES;
703 XCopyArea(display, pix[PIX_HEROES], d, gc,
704 (graphic % HEROES_PER_LINE) * TILEX,
705 (graphic / HEROES_PER_LINE) * TILEY,
708 else if (graphic >= GFX_START_ROCKSFONT && graphic <= GFX_END_ROCKSFONT)
710 graphic -= GFX_START_ROCKSFONT;
711 XCopyArea(display, pix[PIX_BIGFONT], d, gc,
712 (graphic % FONT_CHARS_PER_LINE) * TILEX,
713 (graphic / FONT_CHARS_PER_LINE) * TILEY +
714 FC_SPECIAL1 * FONT_LINES_PER_FONT * TILEY,
718 XFillRectangle(display, d, gc, x, y, TILEX, TILEY);
721 void DrawGraphicThruMask(int x, int y, int graphic)
724 if (!IN_SCR_FIELD(x,y))
726 printf("DrawGraphicThruMask(): x = %d,y = %d, graphic = %d\n",x,y,graphic);
727 printf("DrawGraphicThruMask(): This should never happen!\n");
732 DrawGraphicThruMaskExt(drawto_field, FX + x*TILEX, FY + y*TILEY, graphic);
736 void DrawGraphicThruMaskExt(Drawable d, int dest_x, int dest_y, int graphic)
743 if (graphic >= GFX_START_ROCKSSCREEN && graphic <= GFX_END_ROCKSSCREEN)
745 src_pixmap = pix[PIX_BACK];
746 drawing_gc = clip_gc[PIX_BACK];
747 graphic -= GFX_START_ROCKSSCREEN;
748 src_x = SX + (graphic % GFX_PER_LINE) * TILEX;
749 src_y = SY + (graphic / GFX_PER_LINE) * TILEY;
751 else if (graphic >= GFX_START_ROCKSMORE && graphic <= GFX_END_ROCKSMORE)
753 src_pixmap = pix[PIX_MORE];
754 drawing_gc = clip_gc[PIX_MORE];
755 graphic -= GFX_START_ROCKSMORE;
756 src_x = (graphic % MORE_PER_LINE) * TILEX;
757 src_y = (graphic / MORE_PER_LINE) * TILEY;
759 else if (graphic >= GFX_START_ROCKSHEROES && graphic <= GFX_END_ROCKSHEROES)
761 src_pixmap = pix[PIX_HEROES];
762 drawing_gc = clip_gc[PIX_HEROES];
763 graphic -= GFX_START_ROCKSHEROES;
764 src_x = (graphic % HEROES_PER_LINE) * TILEX;
765 src_y = (graphic / HEROES_PER_LINE) * TILEY;
769 DrawGraphicExt(d, gc, dest_x,dest_y, graphic);
773 if (tile_clipmask[tile] != None)
775 XSetClipMask(display, tile_clip_gc, tile_clipmask[tile]);
776 XSetClipOrigin(display, tile_clip_gc, dest_x, dest_y);
777 XCopyArea(display, src_pixmap, drawto_field, tile_clip_gc,
778 src_x, src_y, TILEX, TILEY, dest_x, dest_y);
783 printf("DrawGraphicThruMask(): tile '%d' needs clipping!\n", tile);
786 XSetClipOrigin(display, drawing_gc, dest_x-src_x, dest_y-src_y);
787 XCopyArea(display, src_pixmap, drawto_field, drawing_gc,
788 src_x, src_y, TILEX, TILEY, dest_x, dest_y);
792 void DrawMiniGraphic(int x, int y, int graphic)
794 DrawMiniGraphicExt(drawto,gc, SX + x*MINI_TILEX, SY + y*MINI_TILEY, graphic);
795 MarkTileDirty(x/2, y/2);
798 void getMiniGraphicSource(int graphic, Pixmap *pixmap, int *x, int *y)
800 if (graphic >= GFX_START_ROCKSSCREEN && graphic <= GFX_END_ROCKSSCREEN)
802 graphic -= GFX_START_ROCKSSCREEN;
803 *pixmap = pix[PIX_BACK];
804 *x = MINI_GFX_STARTX + (graphic % MINI_GFX_PER_LINE) * MINI_TILEX;
805 *y = MINI_GFX_STARTY + (graphic / MINI_GFX_PER_LINE) * MINI_TILEY;
807 else if (graphic >= GFX_START_ROCKSMORE && graphic <= GFX_END_ROCKSMORE)
809 graphic -= GFX_START_ROCKSMORE;
810 *pixmap = pix[PIX_MORE];
811 *x = MINI_MORE_STARTX + (graphic % MINI_MORE_PER_LINE) * MINI_TILEX;
812 *y = MINI_MORE_STARTY + (graphic / MINI_MORE_PER_LINE) * MINI_TILEY;
814 else if (graphic >= GFX_START_ROCKSFONT && graphic <= GFX_END_ROCKSFONT)
816 graphic -= GFX_START_ROCKSFONT;
817 *pixmap = pix[PIX_SMALLFONT];
818 *x = (graphic % FONT_CHARS_PER_LINE) * FONT4_XSIZE;
819 *y = ((graphic / FONT_CHARS_PER_LINE) * FONT4_YSIZE +
820 FC_SPECIAL2 * FONT2_YSIZE * FONT_LINES_PER_FONT);
824 *pixmap = pix[PIX_MORE];
825 *x = MINI_MORE_STARTX;
826 *y = MINI_MORE_STARTY;
830 void DrawMiniGraphicExt(Drawable d, GC gc, int x, int y, int graphic)
832 if (graphic >= GFX_START_ROCKSSCREEN && graphic <= GFX_END_ROCKSSCREEN)
834 graphic -= GFX_START_ROCKSSCREEN;
835 XCopyArea(display, pix[PIX_BACK], d, gc,
836 MINI_GFX_STARTX + (graphic % MINI_GFX_PER_LINE) * MINI_TILEX,
837 MINI_GFX_STARTY + (graphic / MINI_GFX_PER_LINE) * MINI_TILEY,
838 MINI_TILEX, MINI_TILEY, x, y);
840 else if (graphic >= GFX_START_ROCKSMORE && graphic <= GFX_END_ROCKSMORE)
842 graphic -= GFX_START_ROCKSMORE;
843 XCopyArea(display, pix[PIX_MORE], d, gc,
844 MINI_MORE_STARTX + (graphic % MINI_MORE_PER_LINE) * MINI_TILEX,
845 MINI_MORE_STARTY + (graphic / MINI_MORE_PER_LINE) * MINI_TILEY,
846 MINI_TILEX, MINI_TILEY, x, y);
848 else if (graphic >= GFX_START_ROCKSFONT && graphic <= GFX_END_ROCKSFONT)
850 graphic -= GFX_START_ROCKSFONT;
851 XCopyArea(display, pix[PIX_SMALLFONT], d, gc,
852 (graphic % FONT_CHARS_PER_LINE) * FONT4_XSIZE,
853 (graphic / FONT_CHARS_PER_LINE) * FONT4_YSIZE +
854 FC_SPECIAL2 * FONT2_YSIZE * FONT_LINES_PER_FONT,
855 MINI_TILEX, MINI_TILEY, x, y);
858 XFillRectangle(display, d, gc, x, y, MINI_TILEX, MINI_TILEY);
861 void DrawGraphicShifted(int x,int y, int dx,int dy, int graphic,
862 int cut_mode, int mask_mode)
864 int width = TILEX, height = TILEY;
866 int src_x, src_y, dest_x, dest_y;
873 DrawGraphic(x, y, graphic);
877 if (dx || dy) /* Verschiebung der Grafik? */
879 if (x < BX1) /* Element kommt von links ins Bild */
886 else if (x > BX2) /* Element kommt von rechts ins Bild */
892 else if (x==BX1 && dx < 0) /* Element verläßt links das Bild */
898 else if (x==BX2 && dx > 0) /* Element verläßt rechts das Bild */
900 else if (dx) /* allg. Bewegung in x-Richtung */
901 MarkTileDirty(x + SIGN(dx), y);
903 if (y < BY1) /* Element kommt von oben ins Bild */
905 if (cut_mode==CUT_BELOW) /* Element oberhalb des Bildes */
913 else if (y > BY2) /* Element kommt von unten ins Bild */
919 else if (y==BY1 && dy < 0) /* Element verläßt oben das Bild */
925 else if (dy > 0 && cut_mode == CUT_ABOVE)
927 if (y == BY2) /* Element unterhalb des Bildes */
933 MarkTileDirty(x, y + 1);
934 } /* Element verläßt unten das Bild */
935 else if (dy > 0 && (y == BY2 || cut_mode == CUT_BELOW))
937 else if (dy) /* allg. Bewegung in y-Richtung */
938 MarkTileDirty(x, y + SIGN(dy));
941 if (graphic >= GFX_START_ROCKSSCREEN && graphic <= GFX_END_ROCKSSCREEN)
943 src_pixmap = pix[PIX_BACK];
944 drawing_gc = clip_gc[PIX_BACK];
945 graphic -= GFX_START_ROCKSSCREEN;
946 src_x = SX + (graphic % GFX_PER_LINE) * TILEX + cx;
947 src_y = SY + (graphic / GFX_PER_LINE) * TILEY + cy;
949 else if (graphic >= GFX_START_ROCKSMORE && graphic <= GFX_END_ROCKSMORE)
951 src_pixmap = pix[PIX_MORE];
952 drawing_gc = clip_gc[PIX_MORE];
953 graphic -= GFX_START_ROCKSMORE;
954 src_x = (graphic % MORE_PER_LINE) * TILEX + cx;
955 src_y = (graphic / MORE_PER_LINE) * TILEY + cy;
957 else if (graphic >= GFX_START_ROCKSHEROES && graphic <= GFX_END_ROCKSHEROES)
959 src_pixmap = pix[PIX_HEROES];
960 drawing_gc = clip_gc[PIX_HEROES];
961 graphic -= GFX_START_ROCKSHEROES;
962 src_x = (graphic % HEROES_PER_LINE) * TILEX + cx;
963 src_y = (graphic / HEROES_PER_LINE) * TILEY + cy;
965 else /* big font graphics currently not allowed (and not needed) */
968 dest_x = FX + x * TILEX + dx;
969 dest_y = FY + y * TILEY + dy;
972 if (!IN_SCR_FIELD(x,y))
974 printf("DrawGraphicShifted(): x = %d, y = %d, graphic = %d\n",x,y,graphic);
975 printf("DrawGraphicShifted(): This should never happen!\n");
980 if (mask_mode == USE_MASKING)
982 if (tile_clipmask[tile] != None)
984 XSetClipMask(display, tile_clip_gc, tile_clipmask[tile]);
985 XSetClipOrigin(display, tile_clip_gc, dest_x, dest_y);
986 XCopyArea(display, src_pixmap, drawto_field, tile_clip_gc,
987 src_x, src_y, TILEX, TILEY, dest_x, dest_y);
992 printf("DrawGraphicShifted(): tile '%d' needs clipping!\n", tile);
995 XSetClipOrigin(display, drawing_gc, dest_x - src_x, dest_y - src_y);
996 XCopyArea(display, src_pixmap, drawto_field, drawing_gc,
997 src_x, src_y, width, height, dest_x, dest_y);
1001 XCopyArea(display, src_pixmap, drawto_field, gc,
1002 src_x, src_y, width, height, dest_x, dest_y);
1007 void DrawGraphicShiftedThruMask(int x,int y, int dx,int dy, int graphic,
1010 DrawGraphicShifted(x,y, dx,dy, graphic, cut_mode, USE_MASKING);
1013 void DrawScreenElementExt(int x, int y, int dx, int dy, int element,
1014 int cut_mode, int mask_mode)
1016 int ux = LEVELX(x), uy = LEVELY(y);
1017 int graphic = el2gfx(element);
1018 int phase8 = ABS(MovPos[ux][uy]) / (TILEX / 8);
1019 int phase4 = phase8 / 2;
1020 int phase2 = phase8 / 4;
1021 int dir = MovDir[ux][uy];
1023 if (element == EL_PACMAN || element == EL_KAEFER || element == EL_FLIEGER)
1025 graphic += 4 * !phase2;
1029 else if (dir == MV_LEFT)
1031 else if (dir == MV_DOWN)
1034 else if (element == EL_SP_SNIKSNAK)
1037 graphic = GFX_SP_SNIKSNAK_LEFT;
1038 else if (dir == MV_RIGHT)
1039 graphic = GFX_SP_SNIKSNAK_RIGHT;
1040 else if (dir == MV_UP)
1041 graphic = GFX_SP_SNIKSNAK_UP;
1043 graphic = GFX_SP_SNIKSNAK_DOWN;
1045 graphic += (phase8 < 4 ? phase8 : 7 - phase8);
1047 else if (element == EL_SP_ELECTRON)
1049 graphic = GFX2_SP_ELECTRON + getGraphicAnimationPhase(8, 2, ANIM_NORMAL);
1051 else if (element == EL_MAULWURF || element == EL_PINGUIN ||
1052 element == EL_SCHWEIN || element == EL_DRACHE)
1055 graphic = (element == EL_MAULWURF ? GFX_MAULWURF_LEFT :
1056 element == EL_PINGUIN ? GFX_PINGUIN_LEFT :
1057 element == EL_SCHWEIN ? GFX_SCHWEIN_LEFT : GFX_DRACHE_LEFT);
1058 else if (dir == MV_RIGHT)
1059 graphic = (element == EL_MAULWURF ? GFX_MAULWURF_RIGHT :
1060 element == EL_PINGUIN ? GFX_PINGUIN_RIGHT :
1061 element == EL_SCHWEIN ? GFX_SCHWEIN_RIGHT : GFX_DRACHE_RIGHT);
1062 else if (dir == MV_UP)
1063 graphic = (element == EL_MAULWURF ? GFX_MAULWURF_UP :
1064 element == EL_PINGUIN ? GFX_PINGUIN_UP :
1065 element == EL_SCHWEIN ? GFX_SCHWEIN_UP : GFX_DRACHE_UP);
1067 graphic = (element == EL_MAULWURF ? GFX_MAULWURF_DOWN :
1068 element == EL_PINGUIN ? GFX_PINGUIN_DOWN :
1069 element == EL_SCHWEIN ? GFX_SCHWEIN_DOWN : GFX_DRACHE_DOWN);
1073 else if (element == EL_SONDE)
1075 graphic = GFX_SONDE_START + getGraphicAnimationPhase(8, 2, ANIM_NORMAL);
1077 else if (element == EL_SALZSAEURE)
1079 graphic = GFX_GEBLUBBER + getGraphicAnimationPhase(4, 10, ANIM_NORMAL);
1081 else if (element == EL_BUTTERFLY || element == EL_FIREFLY)
1085 else if ((element == EL_FELSBROCKEN || IS_GEM(element)) && !cut_mode)
1087 if (element != EL_SP_INFOTRON)
1088 graphic += phase2 * (element == EL_FELSBROCKEN ? 2 : 1);
1090 else if (element == EL_SIEB_LEER || element == EL_SIEB2_LEER ||
1091 element == EL_SIEB_VOLL || element == EL_SIEB2_VOLL)
1093 graphic += 3 + getGraphicAnimationPhase(4, 4, ANIM_REVERSE);
1095 else if (IS_AMOEBOID(element))
1097 graphic = (element == EL_AMOEBE_TOT ? GFX_AMOEBE_TOT : GFX_AMOEBE_LEBT);
1098 graphic += (x + 2 * y + 4) % 4;
1100 else if (element == EL_MAUER_LEBT)
1102 boolean links_massiv = FALSE, rechts_massiv = FALSE;
1104 if (!IN_LEV_FIELD(ux-1, uy) || IS_MAUER(Feld[ux-1][uy]))
1105 links_massiv = TRUE;
1106 if (!IN_LEV_FIELD(ux+1, uy) || IS_MAUER(Feld[ux+1][uy]))
1107 rechts_massiv = TRUE;
1109 if (links_massiv && rechts_massiv)
1110 graphic = GFX_MAUERWERK;
1111 else if (links_massiv)
1112 graphic = GFX_MAUER_R;
1113 else if (rechts_massiv)
1114 graphic = GFX_MAUER_L;
1118 DrawGraphicShifted(x, y, dx, dy, graphic, cut_mode, mask_mode);
1119 else if (mask_mode == USE_MASKING)
1120 DrawGraphicThruMask(x, y, graphic);
1122 DrawGraphic(x, y, graphic);
1125 void DrawLevelElementExt(int x, int y, int dx, int dy, int element,
1126 int cut_mode, int mask_mode)
1128 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1129 DrawScreenElementExt(SCREENX(x), SCREENY(y), dx, dy, element,
1130 cut_mode, mask_mode);
1133 void DrawScreenElementShifted(int x, int y, int dx, int dy, int element,
1136 DrawScreenElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
1139 void DrawLevelElementShifted(int x, int y, int dx, int dy, int element,
1142 DrawLevelElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
1145 void DrawScreenElementThruMask(int x, int y, int element)
1147 DrawScreenElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
1150 void DrawLevelElementThruMask(int x, int y, int element)
1152 DrawLevelElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
1155 void DrawLevelFieldThruMask(int x, int y)
1157 DrawLevelElementExt(x, y, 0, 0, Feld[x][y], NO_CUTTING, USE_MASKING);
1160 void ErdreichAnbroeckeln(int x, int y)
1162 int i, width, height, cx,cy;
1163 int ux = LEVELX(x), uy = LEVELY(y);
1164 int element, graphic;
1166 static int xy[4][2] =
1174 if (!IN_LEV_FIELD(ux, uy))
1177 element = Feld[ux][uy];
1179 if (element == EL_ERDREICH)
1181 if (!IN_SCR_FIELD(x, y))
1184 graphic = GFX_ERDENRAND;
1190 uxx = ux + xy[i][0];
1191 uyy = uy + xy[i][1];
1192 if (!IN_LEV_FIELD(uxx, uyy))
1195 element = Feld[uxx][uyy];
1197 if (element == EL_ERDREICH)
1200 if (i == 1 || i == 2)
1204 cx = (i == 2 ? TILEX - snip : 0);
1212 cy = (i == 3 ? TILEY - snip : 0);
1215 XCopyArea(display, pix[PIX_BACK], drawto_field, gc,
1216 SX + (graphic % GFX_PER_LINE) * TILEX + cx,
1217 SY + (graphic / GFX_PER_LINE) * TILEY + cy,
1218 width, height, FX + x * TILEX + cx, FY + y * TILEY + cy);
1221 MarkTileDirty(x, y);
1225 graphic = GFX_ERDENRAND;
1229 int xx, yy, uxx, uyy;
1233 uxx = ux + xy[i][0];
1234 uyy = uy + xy[i][1];
1236 if (!IN_LEV_FIELD(uxx, uyy) || Feld[uxx][uyy] != EL_ERDREICH ||
1237 !IN_SCR_FIELD(xx, yy))
1240 if (i == 1 || i == 2)
1244 cx = (i == 1 ? TILEX - snip : 0);
1252 cy = (i==0 ? TILEY-snip : 0);
1255 XCopyArea(display, pix[PIX_BACK], drawto_field, gc,
1256 SX + (graphic % GFX_PER_LINE) * TILEX + cx,
1257 SY + (graphic / GFX_PER_LINE) * TILEY + cy,
1258 width, height, FX + xx * TILEX + cx, FY + yy * TILEY + cy);
1260 MarkTileDirty(xx, yy);
1265 void DrawScreenElement(int x, int y, int element)
1267 DrawScreenElementExt(x, y, 0, 0, element, NO_CUTTING, NO_MASKING);
1268 ErdreichAnbroeckeln(x, y);
1271 void DrawLevelElement(int x, int y, int element)
1273 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1274 DrawScreenElement(SCREENX(x), SCREENY(y), element);
1277 void DrawScreenField(int x, int y)
1279 int ux = LEVELX(x), uy = LEVELY(y);
1282 if (!IN_LEV_FIELD(ux, uy))
1284 if (ux < -1 || ux > lev_fieldx || uy < -1 || uy > lev_fieldy)
1285 element = EL_LEERRAUM;
1287 element = BorderElement;
1289 DrawScreenElement(x, y, element);
1293 element = Feld[ux][uy];
1295 if (IS_MOVING(ux, uy))
1297 int horiz_move = (MovDir[ux][uy] == MV_LEFT || MovDir[ux][uy] == MV_RIGHT);
1298 boolean cut_mode = NO_CUTTING;
1300 if (Store[ux][uy] == EL_MORAST_LEER ||
1301 Store[ux][uy] == EL_SIEB_LEER ||
1302 Store[ux][uy] == EL_SIEB2_LEER ||
1303 Store[ux][uy] == EL_AMOEBE_NASS)
1304 cut_mode = CUT_ABOVE;
1305 else if (Store[ux][uy] == EL_MORAST_VOLL ||
1306 Store[ux][uy] == EL_SIEB_VOLL ||
1307 Store[ux][uy] == EL_SIEB2_VOLL)
1308 cut_mode = CUT_BELOW;
1310 if (cut_mode == CUT_ABOVE)
1311 DrawScreenElementShifted(x, y, 0, 0, Store[ux][uy], NO_CUTTING);
1313 DrawScreenElement(x, y, EL_LEERRAUM);
1316 DrawScreenElementShifted(x, y, MovPos[ux][uy], 0, element, NO_CUTTING);
1318 DrawScreenElementShifted(x, y, 0, MovPos[ux][uy], element, cut_mode);
1320 if (Store[ux][uy] == EL_SALZSAEURE)
1321 DrawLevelElementThruMask(ux, uy + 1, EL_SALZSAEURE);
1323 else if (IS_BLOCKED(ux, uy))
1328 boolean cut_mode = NO_CUTTING;
1330 Blocked2Moving(ux, uy, &oldx, &oldy);
1333 horiz_move = (MovDir[oldx][oldy] == MV_LEFT ||
1334 MovDir[oldx][oldy] == MV_RIGHT);
1336 if (Store[oldx][oldy] == EL_MORAST_LEER ||
1337 Store[oldx][oldy] == EL_SIEB_LEER ||
1338 Store[oldx][oldy] == EL_SIEB2_LEER ||
1339 Store[oldx][oldy] == EL_AMOEBE_NASS)
1340 cut_mode = CUT_ABOVE;
1342 DrawScreenElement(x, y, EL_LEERRAUM);
1343 element = Feld[oldx][oldy];
1346 DrawScreenElementShifted(sx,sy, MovPos[oldx][oldy],0,element,NO_CUTTING);
1348 DrawScreenElementShifted(sx,sy, 0,MovPos[oldx][oldy],element,cut_mode);
1350 else if (IS_DRAWABLE(element))
1351 DrawScreenElement(x, y, element);
1353 DrawScreenElement(x, y, EL_LEERRAUM);
1356 void DrawLevelField(int x, int y)
1358 if (IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1359 DrawScreenField(SCREENX(x), SCREENY(y));
1360 else if (IS_MOVING(x, y))
1364 Moving2Blocked(x, y, &newx, &newy);
1365 if (IN_SCR_FIELD(SCREENX(newx), SCREENY(newy)))
1366 DrawScreenField(SCREENX(newx), SCREENY(newy));
1368 else if (IS_BLOCKED(x, y))
1372 Blocked2Moving(x, y, &oldx, &oldy);
1373 if (IN_SCR_FIELD(SCREENX(oldx), SCREENY(oldy)))
1374 DrawScreenField(SCREENX(oldx), SCREENY(oldy));
1378 void DrawMiniElement(int x, int y, int element)
1384 DrawMiniGraphic(x, y, -1);
1388 graphic = el2gfx(element);
1389 DrawMiniGraphic(x, y, graphic);
1392 void DrawMiniElementOrWall(int sx, int sy, int scroll_x, int scroll_y)
1394 int x = sx + scroll_x, y = sy + scroll_y;
1396 if (x < -1 || x > lev_fieldx || y < -1 || y > lev_fieldy)
1397 DrawMiniElement(sx, sy, EL_LEERRAUM);
1398 else if (x > -1 && x < lev_fieldx && y > -1 && y < lev_fieldy)
1399 DrawMiniElement(sx, sy, Feld[x][y]);
1400 else if (x == -1 && y == -1)
1401 DrawMiniGraphic(sx, sy, GFX_STEEL_UPPER_LEFT);
1402 else if (x == lev_fieldx && y == -1)
1403 DrawMiniGraphic(sx, sy, GFX_STEEL_UPPER_RIGHT);
1404 else if (x == -1 && y == lev_fieldy)
1405 DrawMiniGraphic(sx, sy, GFX_STEEL_LOWER_LEFT);
1406 else if (x == lev_fieldx && y == lev_fieldy)
1407 DrawMiniGraphic(sx, sy, GFX_STEEL_LOWER_RIGHT);
1408 else if (x == -1 || x == lev_fieldx)
1409 DrawMiniGraphic(sx, sy, GFX_STEEL_VERTICAL);
1410 else if (y == -1 || y == lev_fieldy)
1411 DrawMiniGraphic(sx, sy, GFX_STEEL_HORIZONTAL);
1414 void DrawMicroElement(int xpos, int ypos, int element)
1418 if (element == EL_LEERRAUM)
1421 graphic = el2gfx(element);
1423 if (graphic >= GFX_START_ROCKSMORE && graphic <= GFX_END_ROCKSMORE)
1425 graphic -= GFX_START_ROCKSMORE;
1426 XCopyArea(display, pix[PIX_MORE], drawto, gc,
1427 MICRO_MORE_STARTX + (graphic % MICRO_MORE_PER_LINE) *MICRO_TILEX,
1428 MICRO_MORE_STARTY + (graphic / MICRO_MORE_PER_LINE) *MICRO_TILEY,
1429 MICRO_TILEX, MICRO_TILEY, xpos, ypos);
1432 XCopyArea(display, pix[PIX_BACK], drawto, gc,
1433 MICRO_GFX_STARTX + (graphic % MICRO_GFX_PER_LINE) * MICRO_TILEX,
1434 MICRO_GFX_STARTY + (graphic / MICRO_GFX_PER_LINE) * MICRO_TILEY,
1435 MICRO_TILEX, MICRO_TILEY, xpos, ypos);
1444 for(x=BX1; x<=BX2; x++)
1445 for(y=BY1; y<=BY2; y++)
1446 DrawScreenField(x, y);
1448 if (setup.soft_scrolling)
1449 XCopyArea(display, fieldbuffer, backbuffer, gc,
1450 FX, FY, SXSIZE, SYSIZE, SX, SY);
1452 redraw_mask |= (REDRAW_FIELD | REDRAW_FROM_BACKBUFFER);
1455 void DrawMiniLevel(int scroll_x, int scroll_y)
1459 for(x=0; x<ED_FIELDX; x++)
1460 for(y=0; y<ED_FIELDY; y++)
1461 DrawMiniElementOrWall(x, y, scroll_x, scroll_y);
1463 redraw_mask |= REDRAW_FIELD;
1466 static void DrawMicroLevelExt(int xpos, int ypos, int from_x, int from_y)
1470 /* determine border element for this level */
1473 XFillRectangle(display, drawto, gc,
1474 xpos, ypos, MICROLEV_XSIZE, MICROLEV_YSIZE);
1476 if (lev_fieldx < STD_LEV_FIELDX)
1477 xpos += (STD_LEV_FIELDX - lev_fieldx) / 2 * MICRO_TILEX;
1478 if (lev_fieldy < STD_LEV_FIELDY)
1479 ypos += (STD_LEV_FIELDY - lev_fieldy) / 2 * MICRO_TILEY;
1481 xpos += MICRO_TILEX;
1482 ypos += MICRO_TILEY;
1484 for(x=-1; x<=STD_LEV_FIELDX; x++)
1486 for(y=-1; y<=STD_LEV_FIELDY; y++)
1488 int lx = from_x + x, ly = from_y + y;
1490 if (lx >= 0 && lx < lev_fieldx && ly >= 0 && ly < lev_fieldy)
1491 DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
1493 else if (lx >= -1 && lx < lev_fieldx+1 && ly >= -1 && ly < lev_fieldy+1)
1494 DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
1499 redraw_mask |= REDRAW_MICROLEVEL;
1502 static void DrawMicroLevelLabelExt(int mode)
1504 char label_text[100];
1506 XFillRectangle(display, drawto,gc,
1507 SX, MICROLABEL_YPOS, SXSIZE, FONT4_YSIZE);
1509 strcpy(label_text, (mode == 1 ? level.name :
1510 mode == 2 ? "created by" :
1511 mode == 3 ? level.author : ""));
1513 if (strlen(label_text) > 0)
1515 int size, lxpos, lypos;
1517 label_text[SXSIZE / FONT4_XSIZE] = '\0';
1519 size = strlen(label_text);
1520 lxpos = SX + (SXSIZE - size * FONT4_XSIZE) / 2;
1521 lypos = MICROLABEL_YPOS;
1523 DrawText(lxpos, lypos, label_text, FS_SMALL, FC_SPECIAL2);
1526 redraw_mask |= REDRAW_MICROLEVEL;
1529 void DrawMicroLevel(int xpos, int ypos, boolean restart)
1531 static unsigned long scroll_delay = 0;
1532 static unsigned long label_delay = 0;
1533 static int from_x, from_y, scroll_direction;
1534 static int label_state, label_counter;
1538 from_x = from_y = 0;
1539 scroll_direction = MV_RIGHT;
1543 DrawMicroLevelExt(xpos, ypos, from_x, from_y);
1544 DrawMicroLevelLabelExt(label_state);
1546 /* initialize delay counters */
1547 DelayReached(&scroll_delay, 0);
1548 DelayReached(&label_delay, 0);
1553 /* scroll micro level, if needed */
1554 if ((lev_fieldx > STD_LEV_FIELDX || lev_fieldy > STD_LEV_FIELDY) &&
1555 DelayReached(&scroll_delay, MICROLEVEL_SCROLL_DELAY))
1557 switch (scroll_direction)
1563 scroll_direction = MV_UP;
1567 if (from_x < lev_fieldx - STD_LEV_FIELDX)
1570 scroll_direction = MV_DOWN;
1577 scroll_direction = MV_RIGHT;
1581 if (from_y < lev_fieldy - STD_LEV_FIELDY)
1584 scroll_direction = MV_LEFT;
1591 DrawMicroLevelExt(xpos, ypos, from_x, from_y);
1594 /* redraw micro level label, if needed */
1595 if (strcmp(level.name, NAMELESS_LEVEL_NAME) != 0 &&
1596 strcmp(level.author, ANONYMOUS_NAME) != 0 &&
1597 strcmp(level.author, leveldir[leveldir_nr].name) != 0 &&
1598 DelayReached(&label_delay, MICROLEVEL_LABEL_DELAY))
1600 label_counter = (label_counter + 1) % 23;
1601 label_state = (label_counter >= 0 && label_counter <= 7 ? 1 :
1602 label_counter >= 9 && label_counter <= 12 ? 2 :
1603 label_counter >= 14 && label_counter <= 21 ? 3 : 0);
1604 DrawMicroLevelLabelExt(label_state);
1608 int REQ_in_range(int x, int y)
1610 if (y > DY+249 && y < DY+278)
1612 if (x > DX+1 && x < DX+48)
1614 else if (x > DX+51 && x < DX+98)
1620 boolean Request(char *text, unsigned int req_state)
1622 int mx, my, ty, result = -1;
1623 unsigned int old_door_state;
1626 /* pause network game while waiting for request to answer */
1627 if (options.network &&
1628 game_status == PLAYING &&
1629 req_state & REQUEST_WAIT_FOR)
1630 SendToServer_PausePlaying();
1633 old_door_state = GetDoorState();
1637 CloseDoor(DOOR_CLOSE_1);
1639 /* save old door content */
1640 XCopyArea(display, pix[PIX_DB_DOOR], pix[PIX_DB_DOOR], gc,
1641 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE,
1642 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1);
1644 /* clear door drawing field */
1646 XFillRectangle(display, pix[PIX_DB_DOOR], gc,
1647 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE);
1649 XFillRectangle(display, drawto, gc, DX, DY, DXSIZE, DYSIZE);
1652 /* write text for request */
1653 for(ty=0; ty<13; ty++)
1661 for(tl=0,tx=0; tx<7; tl++,tx++)
1664 if (!tc || tc == 32)
1676 DrawTextExt(pix[PIX_DB_DOOR], gc,
1677 DOOR_GFX_PAGEX1 + 51 - (tl * 14)/2, SY + ty * 16,
1678 txt, FS_SMALL, FC_YELLOW);
1680 DrawTextExt(drawto, gc,
1681 DX + 51 - (tl * 14)/2, DY + 8 + ty * 16,
1682 txt, FS_SMALL, FC_YELLOW);
1684 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);
1730 OpenDoor(DOOR_OPEN_1);
1733 if (!(req_state & REQUEST_WAIT_FOR))
1736 if (game_status != MAINMENU)
1739 button_status = MB_RELEASED;
1741 request_gadget_id = -1;
1745 if (XPending(display))
1749 XNextEvent(display, &event);
1762 if (event.type == MotionNotify)
1769 if (!XQueryPointer(display, window, &root, &child,
1770 &root_x, &root_y, &win_x, &win_y, &mask))
1776 motion_status = TRUE;
1777 mx = ((XMotionEvent *) &event)->x;
1778 my = ((XMotionEvent *) &event)->y;
1782 motion_status = FALSE;
1783 mx = ((XButtonEvent *) &event)->x;
1784 my = ((XButtonEvent *) &event)->y;
1785 if (event.type==ButtonPress)
1786 button_status = ((XButtonEvent *) &event)->button;
1788 button_status = MB_RELEASED;
1794 if (req_state & REQ_ASK)
1795 choice = CheckYesNoButtons(mx,my,button_status);
1796 else if (req_state & REQ_CONFIRM)
1797 choice = CheckConfirmButton(mx,my,button_status);
1799 choice = CheckPlayerButtons(mx,my,button_status);
1809 case BUTTON_CONFIRM:
1810 result = TRUE | FALSE;
1813 case BUTTON_PLAYER_1:
1816 case BUTTON_PLAYER_2:
1819 case BUTTON_PLAYER_3:
1822 case BUTTON_PLAYER_4:
1831 /* this sets 'request_gadget_id' */
1832 HandleGadgets(mx, my, button_status);
1834 switch(request_gadget_id)
1836 case TOOL_CTRL_ID_YES:
1839 case TOOL_CTRL_ID_NO:
1842 case TOOL_CTRL_ID_CONFIRM:
1843 result = TRUE | FALSE;
1846 case TOOL_CTRL_ID_PLAYER_1:
1849 case TOOL_CTRL_ID_PLAYER_2:
1852 case TOOL_CTRL_ID_PLAYER_3:
1855 case TOOL_CTRL_ID_PLAYER_4:
1868 switch(XLookupKeysym((XKeyEvent *)&event,
1869 ((XKeyEvent *)&event)->state))
1882 if (req_state & REQ_PLAYER)
1887 key_joystick_mapping = 0;
1891 HandleOtherEvents(&event);
1895 else if (AnyJoystickButton() == JOY_BUTTON_NEW_PRESSED)
1897 int joy = AnyJoystick();
1899 if (joy & JOY_BUTTON_1)
1901 else if (joy & JOY_BUTTON_2)
1907 /* don't eat all CPU time */
1911 if (game_status != MAINMENU)
1916 if (!(req_state & REQ_STAY_OPEN))
1918 CloseDoor(DOOR_CLOSE_1);
1920 if (!(req_state & REQ_STAY_CLOSED) && (old_door_state & DOOR_OPEN_1))
1922 XCopyArea(display,pix[PIX_DB_DOOR],pix[PIX_DB_DOOR],gc,
1923 DOOR_GFX_PAGEX2,DOOR_GFX_PAGEY1, DXSIZE,DYSIZE,
1924 DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY1);
1925 OpenDoor(DOOR_OPEN_1);
1932 /* continue network game after request */
1933 if (options.network &&
1934 game_status == PLAYING &&
1935 req_state & REQUEST_WAIT_FOR)
1936 SendToServer_ContinuePlaying();
1942 unsigned int OpenDoor(unsigned int door_state)
1944 unsigned int new_door_state;
1946 if (door_state & DOOR_COPY_BACK)
1948 XCopyArea(display, pix[PIX_DB_DOOR], pix[PIX_DB_DOOR], gc,
1949 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE + VYSIZE,
1950 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
1951 door_state &= ~DOOR_COPY_BACK;
1954 new_door_state = MoveDoor(door_state);
1956 return(new_door_state);
1959 unsigned int CloseDoor(unsigned int door_state)
1961 unsigned int new_door_state;
1963 XCopyArea(display, backbuffer, pix[PIX_DB_DOOR], gc,
1964 DX, DY, DXSIZE, DYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
1965 XCopyArea(display, backbuffer, pix[PIX_DB_DOOR], gc,
1966 VX, VY, VXSIZE, VYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2);
1968 new_door_state = MoveDoor(door_state);
1970 return(new_door_state);
1973 unsigned int GetDoorState()
1975 return(MoveDoor(DOOR_GET_STATE));
1978 unsigned int MoveDoor(unsigned int door_state)
1980 static int door1 = DOOR_OPEN_1;
1981 static int door2 = DOOR_CLOSE_2;
1982 static unsigned long door_delay = 0;
1983 int x, start, stepsize = 2;
1984 unsigned long door_delay_value = stepsize * 5;
1986 if (door_state == DOOR_GET_STATE)
1987 return(door1 | door2);
1989 if (door1 == DOOR_OPEN_1 && door_state & DOOR_OPEN_1)
1990 door_state &= ~DOOR_OPEN_1;
1991 else if (door1 == DOOR_CLOSE_1 && door_state & DOOR_CLOSE_1)
1992 door_state &= ~DOOR_CLOSE_1;
1993 if (door2 == DOOR_OPEN_2 && door_state & DOOR_OPEN_2)
1994 door_state &= ~DOOR_OPEN_2;
1995 else if (door2 == DOOR_CLOSE_2 && door_state & DOOR_CLOSE_2)
1996 door_state &= ~DOOR_CLOSE_2;
1998 if (setup.quick_doors)
2001 door_delay_value = 0;
2002 StopSound(SND_OEFFNEN);
2005 if (door_state & DOOR_ACTION)
2007 if (!(door_state & DOOR_NO_DELAY))
2008 PlaySoundStereo(SND_OEFFNEN, PSND_MAX_RIGHT);
2010 start = ((door_state & DOOR_NO_DELAY) ? DXSIZE : 0);
2012 for(x=start; x<=DXSIZE; x+=stepsize)
2014 WaitUntilDelayReached(&door_delay, door_delay_value);
2016 if (door_state & DOOR_ACTION_1)
2018 int i = (door_state & DOOR_OPEN_1 ? DXSIZE-x : x);
2019 int j = (DXSIZE - i) / 3;
2021 XCopyArea(display, pix[PIX_DB_DOOR], drawto, gc,
2022 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1 + i/2,
2023 DXSIZE,DYSIZE - i/2, DX, DY);
2025 XFillRectangle(display, drawto, gc, DX, DY + DYSIZE - i/2, DXSIZE,i/2);
2027 XSetClipOrigin(display, clip_gc[PIX_DOOR],
2028 DX - i, (DY + j) - DOOR_GFX_PAGEY1);
2029 XCopyArea(display, pix[PIX_DOOR], drawto,clip_gc[PIX_DOOR],
2030 DXSIZE, DOOR_GFX_PAGEY1, i, 77, DX + DXSIZE - i, DY + j);
2031 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2032 DXSIZE, DOOR_GFX_PAGEY1 + 140, i, 63, DX + DXSIZE - i,
2034 XSetClipOrigin(display, clip_gc[PIX_DOOR],
2035 DX - DXSIZE + i, DY - (DOOR_GFX_PAGEY1 + j));
2036 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2037 DXSIZE - i, DOOR_GFX_PAGEY1 + j, i, 77 - j, DX, DY);
2038 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2039 DXSIZE-i, DOOR_GFX_PAGEY1 + 140, i, 63, DX, DY + 140 - j);
2041 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2042 DXSIZE - i, DOOR_GFX_PAGEY1 + 77, i, 63,
2044 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2045 DXSIZE - i, DOOR_GFX_PAGEY1 + 203, i, 77,
2047 XSetClipOrigin(display, clip_gc[PIX_DOOR],
2048 DX - i, (DY + j) - DOOR_GFX_PAGEY1);
2049 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2050 DXSIZE, DOOR_GFX_PAGEY1 + 77, i, 63,
2051 DX + DXSIZE - i, DY + 77 + j);
2052 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2053 DXSIZE, DOOR_GFX_PAGEY1 + 203, i, 77 - j,
2054 DX + DXSIZE - i, DY + 203 + j);
2056 redraw_mask |= REDRAW_DOOR_1;
2059 if (door_state & DOOR_ACTION_2)
2061 int i = (door_state & DOOR_OPEN_2 ? VXSIZE - x : x);
2062 int j = (VXSIZE - i) / 3;
2064 XCopyArea(display, pix[PIX_DB_DOOR], drawto, gc,
2065 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2 + i/2,
2066 VXSIZE, VYSIZE - i/2, VX, VY);
2068 XFillRectangle(display, drawto, gc, VX, VY + VYSIZE-i/2, VXSIZE, i/2);
2070 XSetClipOrigin(display, clip_gc[PIX_DOOR],
2071 VX - i, (VY + j) - DOOR_GFX_PAGEY2);
2072 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2073 VXSIZE, DOOR_GFX_PAGEY2, i, VYSIZE / 2, VX + VXSIZE-i, VY+j);
2074 XSetClipOrigin(display, clip_gc[PIX_DOOR],
2075 VX - VXSIZE + i, VY - (DOOR_GFX_PAGEY2 + j));
2076 XCopyArea(display, pix[PIX_DOOR], drawto,clip_gc[PIX_DOOR],
2077 VXSIZE - i, DOOR_GFX_PAGEY2 + j, i, VYSIZE / 2 - j, VX, VY);
2079 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2080 VXSIZE - i, DOOR_GFX_PAGEY2 + VYSIZE / 2, i, VYSIZE / 2,
2081 VX, VY + VYSIZE / 2 - j);
2082 XSetClipOrigin(display, clip_gc[PIX_DOOR],
2083 VX - i, (VY + j) - DOOR_GFX_PAGEY2);
2084 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2085 VXSIZE, DOOR_GFX_PAGEY2 + VYSIZE / 2, i, VYSIZE / 2 - j,
2086 VX + VXSIZE - i, VY + VYSIZE / 2 + j);
2088 redraw_mask |= REDRAW_DOOR_2;
2096 XCopyArea(display, drawto, window, gc, DX, DY, DXSIZE, DYSIZE, DX, DY);
2101 if (game_status == MAINMENU)
2106 if (setup.quick_doors)
2107 StopSound(SND_OEFFNEN);
2109 if (door_state & DOOR_ACTION_1)
2110 door1 = door_state & DOOR_ACTION_1;
2111 if (door_state & DOOR_ACTION_2)
2112 door2 = door_state & DOOR_ACTION_2;
2114 return(door1 | door2);
2117 int ReadPixel(Drawable d, int x, int y)
2119 XImage *pixel_image;
2120 unsigned long pixel_value;
2122 pixel_image = XGetImage(display, d, x, y, 1, 1, AllPlanes, ZPixmap);
2123 pixel_value = XGetPixel(pixel_image, 0, 0);
2125 XDestroyImage(pixel_image);
2130 /* ---------- new tool button stuff ---------------------------------------- */
2132 /* graphic position values for tool buttons */
2133 #define TOOL_BUTTON_YES_XPOS 2
2134 #define TOOL_BUTTON_YES_YPOS 250
2135 #define TOOL_BUTTON_YES_GFX_YPOS 0
2136 #define TOOL_BUTTON_YES_XSIZE 46
2137 #define TOOL_BUTTON_YES_YSIZE 28
2138 #define TOOL_BUTTON_NO_XPOS 52
2139 #define TOOL_BUTTON_NO_YPOS TOOL_BUTTON_YES_YPOS
2140 #define TOOL_BUTTON_NO_GFX_YPOS TOOL_BUTTON_YES_GFX_YPOS
2141 #define TOOL_BUTTON_NO_XSIZE TOOL_BUTTON_YES_XSIZE
2142 #define TOOL_BUTTON_NO_YSIZE TOOL_BUTTON_YES_YSIZE
2143 #define TOOL_BUTTON_CONFIRM_XPOS TOOL_BUTTON_YES_XPOS
2144 #define TOOL_BUTTON_CONFIRM_YPOS TOOL_BUTTON_YES_YPOS
2145 #define TOOL_BUTTON_CONFIRM_GFX_YPOS 30
2146 #define TOOL_BUTTON_CONFIRM_XSIZE 96
2147 #define TOOL_BUTTON_CONFIRM_YSIZE TOOL_BUTTON_YES_YSIZE
2148 #define TOOL_BUTTON_PLAYER_XSIZE 30
2149 #define TOOL_BUTTON_PLAYER_YSIZE 30
2150 #define TOOL_BUTTON_PLAYER_GFX_XPOS 5
2151 #define TOOL_BUTTON_PLAYER_GFX_YPOS 185
2152 #define TOOL_BUTTON_PLAYER_XPOS (5 + TOOL_BUTTON_PLAYER_XSIZE / 2)
2153 #define TOOL_BUTTON_PLAYER_YPOS (215 - TOOL_BUTTON_PLAYER_YSIZE / 2)
2154 #define TOOL_BUTTON_PLAYER1_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2155 + 0 * TOOL_BUTTON_PLAYER_XSIZE)
2156 #define TOOL_BUTTON_PLAYER2_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2157 + 1 * TOOL_BUTTON_PLAYER_XSIZE)
2158 #define TOOL_BUTTON_PLAYER3_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2159 + 0 * TOOL_BUTTON_PLAYER_XSIZE)
2160 #define TOOL_BUTTON_PLAYER4_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2161 + 1 * TOOL_BUTTON_PLAYER_XSIZE)
2162 #define TOOL_BUTTON_PLAYER1_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2163 + 0 * TOOL_BUTTON_PLAYER_YSIZE)
2164 #define TOOL_BUTTON_PLAYER2_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2165 + 0 * TOOL_BUTTON_PLAYER_YSIZE)
2166 #define TOOL_BUTTON_PLAYER3_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2167 + 1 * TOOL_BUTTON_PLAYER_YSIZE)
2168 #define TOOL_BUTTON_PLAYER4_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2169 + 1 * TOOL_BUTTON_PLAYER_YSIZE)
2178 } toolbutton_info[NUM_TOOL_BUTTONS] =
2181 TOOL_BUTTON_YES_XPOS, TOOL_BUTTON_YES_GFX_YPOS,
2182 TOOL_BUTTON_YES_XPOS, TOOL_BUTTON_YES_YPOS,
2183 TOOL_BUTTON_YES_XSIZE, TOOL_BUTTON_YES_YSIZE,
2188 TOOL_BUTTON_NO_XPOS, TOOL_BUTTON_NO_GFX_YPOS,
2189 TOOL_BUTTON_NO_XPOS, TOOL_BUTTON_NO_YPOS,
2190 TOOL_BUTTON_NO_XSIZE, TOOL_BUTTON_NO_YSIZE,
2195 TOOL_BUTTON_CONFIRM_XPOS, TOOL_BUTTON_CONFIRM_GFX_YPOS,
2196 TOOL_BUTTON_CONFIRM_XPOS, TOOL_BUTTON_CONFIRM_YPOS,
2197 TOOL_BUTTON_CONFIRM_XSIZE, TOOL_BUTTON_CONFIRM_YSIZE,
2198 TOOL_CTRL_ID_CONFIRM,
2202 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2203 TOOL_BUTTON_PLAYER1_XPOS, TOOL_BUTTON_PLAYER1_YPOS,
2204 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2205 TOOL_CTRL_ID_PLAYER_1,
2209 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2210 TOOL_BUTTON_PLAYER2_XPOS, TOOL_BUTTON_PLAYER2_YPOS,
2211 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2212 TOOL_CTRL_ID_PLAYER_2,
2216 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2217 TOOL_BUTTON_PLAYER3_XPOS, TOOL_BUTTON_PLAYER3_YPOS,
2218 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2219 TOOL_CTRL_ID_PLAYER_3,
2223 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2224 TOOL_BUTTON_PLAYER4_XPOS, TOOL_BUTTON_PLAYER4_YPOS,
2225 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2226 TOOL_CTRL_ID_PLAYER_4,
2231 void CreateToolButtons()
2235 for (i=0; i<NUM_TOOL_BUTTONS; i++)
2237 Pixmap gd_pixmap = pix[PIX_DOOR];
2238 Pixmap deco_pixmap = 0;
2239 int deco_x, deco_y, deco_xpos, deco_ypos;
2240 struct GadgetInfo *gi;
2241 unsigned long event_mask;
2242 int gd_xoffset, gd_yoffset;
2243 int gd_x1, gd_x2, gd_y;
2246 event_mask = GD_EVENT_RELEASED;
2248 gd_xoffset = toolbutton_info[i].xpos;
2249 gd_yoffset = toolbutton_info[i].ypos;
2250 gd_x1 = DOOR_GFX_PAGEX4 + gd_xoffset;
2251 gd_x2 = DOOR_GFX_PAGEX3 + gd_xoffset;
2252 gd_y = DOOR_GFX_PAGEY1 + gd_yoffset;
2254 if (id >= TOOL_CTRL_ID_PLAYER_1 && id <= TOOL_CTRL_ID_PLAYER_4)
2256 getMiniGraphicSource(GFX_SPIELER1 + id - TOOL_CTRL_ID_PLAYER_1,
2257 &deco_pixmap, &deco_x, &deco_y);
2258 deco_xpos = (toolbutton_info[i].width - MINI_TILEX) / 2;
2259 deco_ypos = (toolbutton_info[i].height - MINI_TILEY) / 2;
2262 gi = CreateGadget(GDI_CUSTOM_ID, id,
2263 GDI_INFO_TEXT, toolbutton_info[i].infotext,
2264 GDI_X, DX + toolbutton_info[i].x,
2265 GDI_Y, DY + toolbutton_info[i].y,
2266 GDI_WIDTH, toolbutton_info[i].width,
2267 GDI_HEIGHT, toolbutton_info[i].height,
2268 GDI_TYPE, GD_TYPE_NORMAL_BUTTON,
2269 GDI_STATE, GD_BUTTON_UNPRESSED,
2270 GDI_DESIGN_UNPRESSED, gd_pixmap, gd_x1, gd_y,
2271 GDI_DESIGN_PRESSED, gd_pixmap, gd_x2, gd_y,
2272 GDI_DECORATION_DESIGN, deco_pixmap, deco_x, deco_y,
2273 GDI_DECORATION_POSITION, deco_xpos, deco_ypos,
2274 GDI_DECORATION_SIZE, MINI_TILEX, MINI_TILEY,
2275 GDI_DECORATION_SHIFTING, 1, 1,
2276 GDI_EVENT_MASK, event_mask,
2277 GDI_CALLBACK_ACTION, HandleToolButtons,
2281 Error(ERR_EXIT, "cannot create gadget");
2283 tool_gadget[id] = gi;
2287 static void UnmapToolButtons()
2291 for (i=0; i<NUM_TOOL_BUTTONS; i++)
2292 UnmapGadget(tool_gadget[i]);
2295 static void HandleToolButtons(struct GadgetInfo *gi)
2297 request_gadget_id = gi->custom_id;
2301 int id = gi->custom_id;
2303 if (game_status != PLAYING)
2308 case GAME_CTRL_ID_STOP:
2311 CloseDoor(DOOR_CLOSE_1);
2312 game_status = MAINMENU;
2317 if (Request("Do you really want to quit the game ?",
2318 REQ_ASK | REQ_STAY_CLOSED))
2321 if (options.network)
2322 SendToServer_StopPlaying();
2326 game_status = MAINMENU;
2331 OpenDoor(DOOR_OPEN_1 | DOOR_COPY_BACK);
2334 case GAME_CTRL_ID_PAUSE:
2335 if (options.network)
2339 SendToServer_ContinuePlaying();
2341 SendToServer_PausePlaying();
2348 case GAME_CTRL_ID_PLAY:
2352 if (options.network)
2353 SendToServer_ContinuePlaying();
2357 tape.pausing = FALSE;
2358 DrawVideoDisplay(VIDEO_STATE_PAUSE_OFF,0);
2363 case SOUND_CTRL_ID_MUSIC:
2364 if (setup.sound_music)
2366 setup.sound_music = FALSE;
2367 FadeSound(background_loop[level_nr % num_bg_loops]);
2369 else if (sound_loops_allowed)
2371 setup.sound = setup.sound_music = TRUE;
2372 PlaySoundLoop(background_loop[level_nr % num_bg_loops]);
2376 case SOUND_CTRL_ID_LOOPS:
2377 if (setup.sound_loops)
2378 setup.sound_loops = FALSE;
2379 else if (sound_loops_allowed)
2380 setup.sound = setup.sound_loops = TRUE;
2383 case SOUND_CTRL_ID_SIMPLE:
2384 if (setup.sound_simple)
2385 setup.sound_simple = FALSE;
2386 else if (sound_status==SOUND_AVAILABLE)
2387 setup.sound = setup.sound_simple = TRUE;
2399 int el2gfx(int element)
2403 case EL_LEERRAUM: return -1;
2404 case EL_ERDREICH: return GFX_ERDREICH;
2405 case EL_MAUERWERK: return GFX_MAUERWERK;
2406 case EL_FELSBODEN: return GFX_FELSBODEN;
2407 case EL_FELSBROCKEN: return GFX_FELSBROCKEN;
2408 case EL_SCHLUESSEL: return GFX_SCHLUESSEL;
2409 case EL_EDELSTEIN: return GFX_EDELSTEIN;
2410 case EL_AUSGANG_ZU: return GFX_AUSGANG_ZU;
2411 case EL_AUSGANG_ACT: return GFX_AUSGANG_ACT;
2412 case EL_AUSGANG_AUF: return GFX_AUSGANG_AUF;
2413 case EL_SPIELFIGUR: return GFX_SPIELFIGUR;
2414 case EL_SPIELER1: return GFX_SPIELER1;
2415 case EL_SPIELER2: return GFX_SPIELER2;
2416 case EL_SPIELER3: return GFX_SPIELER3;
2417 case EL_SPIELER4: return GFX_SPIELER4;
2418 case EL_KAEFER: return GFX_KAEFER;
2419 case EL_KAEFER_R: return GFX_KAEFER_R;
2420 case EL_KAEFER_O: return GFX_KAEFER_O;
2421 case EL_KAEFER_L: return GFX_KAEFER_L;
2422 case EL_KAEFER_U: return GFX_KAEFER_U;
2423 case EL_FLIEGER: return GFX_FLIEGER;
2424 case EL_FLIEGER_R: return GFX_FLIEGER_R;
2425 case EL_FLIEGER_O: return GFX_FLIEGER_O;
2426 case EL_FLIEGER_L: return GFX_FLIEGER_L;
2427 case EL_FLIEGER_U: return GFX_FLIEGER_U;
2428 case EL_BUTTERFLY: return GFX_BUTTERFLY;
2429 case EL_BUTTERFLY_R: return GFX_BUTTERFLY_R;
2430 case EL_BUTTERFLY_O: return GFX_BUTTERFLY_O;
2431 case EL_BUTTERFLY_L: return GFX_BUTTERFLY_L;
2432 case EL_BUTTERFLY_U: return GFX_BUTTERFLY_U;
2433 case EL_FIREFLY: return GFX_FIREFLY;
2434 case EL_FIREFLY_R: return GFX_FIREFLY_R;
2435 case EL_FIREFLY_O: return GFX_FIREFLY_O;
2436 case EL_FIREFLY_L: return GFX_FIREFLY_L;
2437 case EL_FIREFLY_U: return GFX_FIREFLY_U;
2438 case EL_MAMPFER: return GFX_MAMPFER;
2439 case EL_ROBOT: return GFX_ROBOT;
2440 case EL_BETON: return GFX_BETON;
2441 case EL_DIAMANT: return GFX_DIAMANT;
2442 case EL_MORAST_LEER: return GFX_MORAST_LEER;
2443 case EL_MORAST_VOLL: return GFX_MORAST_VOLL;
2444 case EL_TROPFEN: return GFX_TROPFEN;
2445 case EL_BOMBE: return GFX_BOMBE;
2446 case EL_SIEB_INAKTIV: return GFX_SIEB_INAKTIV;
2447 case EL_SIEB_LEER: return GFX_SIEB_LEER;
2448 case EL_SIEB_VOLL: return GFX_SIEB_VOLL;
2449 case EL_SIEB_TOT: return GFX_SIEB_TOT;
2450 case EL_SALZSAEURE: return GFX_SALZSAEURE;
2451 case EL_AMOEBE_TOT: return GFX_AMOEBE_TOT;
2452 case EL_AMOEBE_NASS: return GFX_AMOEBE_NASS;
2453 case EL_AMOEBE_NORM: return GFX_AMOEBE_NORM;
2454 case EL_AMOEBE_VOLL: return GFX_AMOEBE_VOLL;
2455 case EL_AMOEBE_BD: return GFX_AMOEBE_BD;
2456 case EL_AMOEBA2DIAM: return GFX_AMOEBA2DIAM;
2457 case EL_KOKOSNUSS: return GFX_KOKOSNUSS;
2458 case EL_LIFE: return GFX_LIFE;
2459 case EL_LIFE_ASYNC: return GFX_LIFE_ASYNC;
2460 case EL_DYNAMIT: return GFX_DYNAMIT;
2461 case EL_BADEWANNE: return GFX_BADEWANNE;
2462 case EL_BADEWANNE1: return GFX_BADEWANNE1;
2463 case EL_BADEWANNE2: return GFX_BADEWANNE2;
2464 case EL_BADEWANNE3: return GFX_BADEWANNE3;
2465 case EL_BADEWANNE4: return GFX_BADEWANNE4;
2466 case EL_BADEWANNE5: return GFX_BADEWANNE5;
2467 case EL_ABLENK_AUS: return GFX_ABLENK_AUS;
2468 case EL_ABLENK_EIN: return GFX_ABLENK_EIN;
2469 case EL_SCHLUESSEL1: return GFX_SCHLUESSEL1;
2470 case EL_SCHLUESSEL2: return GFX_SCHLUESSEL2;
2471 case EL_SCHLUESSEL3: return GFX_SCHLUESSEL3;
2472 case EL_SCHLUESSEL4: return GFX_SCHLUESSEL4;
2473 case EL_PFORTE1: return GFX_PFORTE1;
2474 case EL_PFORTE2: return GFX_PFORTE2;
2475 case EL_PFORTE3: return GFX_PFORTE3;
2476 case EL_PFORTE4: return GFX_PFORTE4;
2477 case EL_PFORTE1X: return GFX_PFORTE1X;
2478 case EL_PFORTE2X: return GFX_PFORTE2X;
2479 case EL_PFORTE3X: return GFX_PFORTE3X;
2480 case EL_PFORTE4X: return GFX_PFORTE4X;
2481 case EL_DYNAMIT_AUS: return GFX_DYNAMIT_AUS;
2482 case EL_PACMAN: return GFX_PACMAN;
2483 case EL_PACMAN_R: return GFX_PACMAN_R;
2484 case EL_PACMAN_O: return GFX_PACMAN_O;
2485 case EL_PACMAN_L: return GFX_PACMAN_L;
2486 case EL_PACMAN_U: return GFX_PACMAN_U;
2487 case EL_UNSICHTBAR: return GFX_UNSICHTBAR;
2488 case EL_ERZ_EDEL: return GFX_ERZ_EDEL;
2489 case EL_ERZ_DIAM: return GFX_ERZ_DIAM;
2490 case EL_BIRNE_AUS: return GFX_BIRNE_AUS;
2491 case EL_BIRNE_EIN: return GFX_BIRNE_EIN;
2492 case EL_ZEIT_VOLL: return GFX_ZEIT_VOLL;
2493 case EL_ZEIT_LEER: return GFX_ZEIT_LEER;
2494 case EL_MAUER_LEBT: return GFX_MAUER_LEBT;
2495 case EL_MAUER_X: return GFX_MAUER_X;
2496 case EL_MAUER_Y: return GFX_MAUER_Y;
2497 case EL_MAUER_XY: return GFX_MAUER_XY;
2498 case EL_EDELSTEIN_BD: return GFX_EDELSTEIN_BD;
2499 case EL_EDELSTEIN_GELB: return GFX_EDELSTEIN_GELB;
2500 case EL_EDELSTEIN_ROT: return GFX_EDELSTEIN_ROT;
2501 case EL_EDELSTEIN_LILA: return GFX_EDELSTEIN_LILA;
2502 case EL_ERZ_EDEL_BD: return GFX_ERZ_EDEL_BD;
2503 case EL_ERZ_EDEL_GELB: return GFX_ERZ_EDEL_GELB;
2504 case EL_ERZ_EDEL_ROT: return GFX_ERZ_EDEL_ROT;
2505 case EL_ERZ_EDEL_LILA: return GFX_ERZ_EDEL_LILA;
2506 case EL_MAMPFER2: return GFX_MAMPFER2;
2507 case EL_SIEB2_INAKTIV: return GFX_SIEB2_INAKTIV;
2508 case EL_SIEB2_LEER: return GFX_SIEB2_LEER;
2509 case EL_SIEB2_VOLL: return GFX_SIEB2_VOLL;
2510 case EL_SIEB2_TOT: return GFX_SIEB2_TOT;
2511 case EL_DYNABOMB: return GFX_DYNABOMB;
2512 case EL_DYNABOMB_NR: return GFX_DYNABOMB_NR;
2513 case EL_DYNABOMB_SZ: return GFX_DYNABOMB_SZ;
2514 case EL_DYNABOMB_XL: return GFX_DYNABOMB_XL;
2515 case EL_SOKOBAN_OBJEKT: return GFX_SOKOBAN_OBJEKT;
2516 case EL_SOKOBAN_FELD_LEER: return GFX_SOKOBAN_FELD_LEER;
2517 case EL_SOKOBAN_FELD_VOLL: return GFX_SOKOBAN_FELD_VOLL;
2518 case EL_MAULWURF: return GFX_MAULWURF;
2519 case EL_PINGUIN: return GFX_PINGUIN;
2520 case EL_SCHWEIN: return GFX_SCHWEIN;
2521 case EL_DRACHE: return GFX_DRACHE;
2522 case EL_SONDE: return GFX_SONDE;
2523 case EL_PFEIL_L: return GFX_PFEIL_L;
2524 case EL_PFEIL_R: return GFX_PFEIL_R;
2525 case EL_PFEIL_O: return GFX_PFEIL_O;
2526 case EL_PFEIL_U: return GFX_PFEIL_U;
2527 case EL_SPEED_PILL: return GFX_SPEED_PILL;
2528 case EL_SP_TERMINAL_ACTIVE: return GFX_SP_TERMINAL;
2529 case EL_SP_BUG_ACTIVE: return GFX_SP_BUG_ACTIVE;
2530 case EL_INVISIBLE_STEEL: return GFX_INVISIBLE_STEEL;
2534 if (IS_CHAR(element))
2535 return GFX_CHAR_START + (element - EL_CHAR_START);
2536 else if (element >= EL_SP_START && element <= EL_SP_END)
2538 int nr_element = element - EL_SP_START;
2539 int gfx_per_line = 8;
2541 (nr_element / gfx_per_line) * MORE_PER_LINE +
2542 (nr_element % gfx_per_line);
2544 return GFX_START_ROCKSMORE + nr_graphic;