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 int getGraphicAnimationPhase(int, int, int);
47 static void UnmapToolButtons();
48 static void HandleToolButtons(struct GadgetInfo *);
50 static struct GadgetInfo *tool_gadget[NUM_TOOL_BUTTONS];
51 static int request_gadget_id = -1;
53 void SetDrawtoField(int mode)
55 if (mode == DRAW_BUFFERED && setup.soft_scrolling)
66 drawto_field = fieldbuffer;
68 else /* DRAW_DIRECT, DRAW_BACKBUFFER */
79 drawto_field = (mode == DRAW_DIRECT ? window : backbuffer);
86 Drawable buffer = (drawto_field == window ? backbuffer : drawto_field);
88 if (setup.direct_draw && game_status == PLAYING)
89 redraw_mask &= ~REDRAW_MAIN;
91 if (redraw_mask & REDRAW_TILES && redraw_tiles > REDRAWTILES_THRESHOLD)
92 redraw_mask |= REDRAW_FIELD;
94 if (redraw_mask & REDRAW_FIELD)
95 redraw_mask &= ~REDRAW_TILES;
100 /* synchronize X11 graphics at this point; if we would synchronize the
101 display immediately after the buffer switching (after the XFlush),
102 this could mean that we have to wait for the graphics to complete,
103 although we could go on doing calculations for the next frame */
105 XSync(display, FALSE);
107 if (redraw_mask & REDRAW_ALL)
109 XCopyArea(display, backbuffer, window, gc,
110 0, 0, WIN_XSIZE, WIN_YSIZE,
115 if (redraw_mask & REDRAW_FIELD)
117 if (game_status != PLAYING || redraw_mask & REDRAW_FROM_BACKBUFFER)
119 XCopyArea(display, backbuffer, window, gc,
120 REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE,
125 int fx = FX, fy = FY;
127 if (setup.soft_scrolling)
129 fx += (ScreenMovDir & (MV_LEFT | MV_RIGHT) ? ScreenGfxPos : 0);
130 fy += (ScreenMovDir & (MV_UP | MV_DOWN) ? ScreenGfxPos : 0);
133 if (setup.soft_scrolling ||
134 ABS(ScreenMovPos) + ScrollStepSize == TILEX ||
135 ABS(ScreenMovPos) == ScrollStepSize ||
136 redraw_tiles > REDRAWTILES_THRESHOLD)
138 XCopyArea(display, buffer, window, gc, fx, fy, SXSIZE, SYSIZE, SX, SY);
142 printf("redrawing all (ScreenGfxPos == %d) because %s\n",
144 (setup.soft_scrolling ?
145 "setup.soft_scrolling" :
146 ABS(ScreenGfxPos) + ScrollStepSize == TILEX ?
147 "ABS(ScreenGfxPos) + ScrollStepSize == TILEX" :
148 ABS(ScreenGfxPos) == ScrollStepSize ?
149 "ABS(ScreenGfxPos) == ScrollStepSize" :
150 "redraw_tiles > REDRAWTILES_THRESHOLD"));
155 redraw_mask &= ~REDRAW_MAIN;
158 if (redraw_mask & REDRAW_DOORS)
160 if (redraw_mask & REDRAW_DOOR_1)
161 XCopyArea(display, backbuffer, window, gc,
162 DX, DY, DXSIZE, DYSIZE,
164 if (redraw_mask & REDRAW_DOOR_2)
166 if ((redraw_mask & REDRAW_DOOR_2) == REDRAW_DOOR_2)
167 XCopyArea(display,backbuffer,window,gc,
168 VX,VY, VXSIZE,VYSIZE,
172 if (redraw_mask & REDRAW_VIDEO_1)
173 XCopyArea(display,backbuffer,window,gc,
174 VX+VIDEO_DISPLAY1_XPOS,VY+VIDEO_DISPLAY1_YPOS,
175 VIDEO_DISPLAY_XSIZE,VIDEO_DISPLAY_YSIZE,
176 VX+VIDEO_DISPLAY1_XPOS,VY+VIDEO_DISPLAY1_YPOS);
177 if (redraw_mask & REDRAW_VIDEO_2)
178 XCopyArea(display,backbuffer,window,gc,
179 VX+VIDEO_DISPLAY2_XPOS,VY+VIDEO_DISPLAY2_YPOS,
180 VIDEO_DISPLAY_XSIZE,VIDEO_DISPLAY_YSIZE,
181 VX+VIDEO_DISPLAY2_XPOS,VY+VIDEO_DISPLAY2_YPOS);
182 if (redraw_mask & REDRAW_VIDEO_3)
183 XCopyArea(display,backbuffer,window,gc,
184 VX+VIDEO_CONTROL_XPOS,VY+VIDEO_CONTROL_YPOS,
185 VIDEO_CONTROL_XSIZE,VIDEO_CONTROL_YSIZE,
186 VX+VIDEO_CONTROL_XPOS,VY+VIDEO_CONTROL_YPOS);
189 if (redraw_mask & REDRAW_DOOR_3)
190 XCopyArea(display, backbuffer, window, gc,
191 EX, EY, EXSIZE, EYSIZE,
193 redraw_mask &= ~REDRAW_DOORS;
196 if (redraw_mask & REDRAW_MICROLEVEL)
198 XCopyArea(display,backbuffer,window,gc,
199 MICROLEV_XPOS, MICROLEV_YPOS, MICROLEV_XSIZE, MICROLEV_YSIZE,
200 MICROLEV_XPOS, MICROLEV_YPOS);
201 XCopyArea(display,backbuffer,window,gc,
202 SX, MICROLABEL_YPOS, SXSIZE, FONT4_YSIZE,
203 SX, MICROLABEL_YPOS);
204 redraw_mask &= ~REDRAW_MICROLEVEL;
207 if (redraw_mask & REDRAW_TILES)
209 for(x=0; x<SCR_FIELDX; x++)
210 for(y=0; y<SCR_FIELDY; y++)
211 if (redraw[redraw_x1 + x][redraw_y1 + y])
212 XCopyArea(display, buffer, window, gc,
213 FX + x * TILEX, FX + y * TILEY, TILEX, TILEY,
214 SX + x * TILEX, SY + y * TILEY);
219 for(x=0; x<MAX_BUF_XSIZE; x++)
220 for(y=0; y<MAX_BUF_YSIZE; y++)
229 long fading_delay = 300;
231 if (setup.fading && (redraw_mask & REDRAW_FIELD))
238 XFillRectangle(display,window,gc,
239 REAL_SX,REAL_SY,FULL_SXSIZE,FULL_SYSIZE);
242 for(i=0;i<2*FULL_SYSIZE;i++)
244 for(y=0;y<FULL_SYSIZE;y++)
246 XCopyArea(display,backbuffer,window,gc,
247 REAL_SX,REAL_SY+i, FULL_SXSIZE,1, REAL_SX,REAL_SY+i);
255 for(i=1;i<FULL_SYSIZE;i+=2)
256 XCopyArea(display,backbuffer,window,gc,
257 REAL_SX,REAL_SY+i, FULL_SXSIZE,1, REAL_SX,REAL_SY+i);
263 XSetClipOrigin(display,clip_gc[PIX_FADEMASK],0,0);
264 XCopyArea(display,backbuffer,window,clip_gc[PIX_FADEMASK],
265 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE, REAL_SX,REAL_SY);
269 XSetClipOrigin(display,clip_gc[PIX_FADEMASK],-1,-1);
270 XCopyArea(display,backbuffer,window,clip_gc[PIX_FADEMASK],
271 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE, REAL_SX,REAL_SY);
275 XSetClipOrigin(display,clip_gc[PIX_FADEMASK],0,-1);
276 XCopyArea(display,backbuffer,window,clip_gc[PIX_FADEMASK],
277 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE, REAL_SX,REAL_SY);
281 XSetClipOrigin(display,clip_gc[PIX_FADEMASK],-1,0);
282 XCopyArea(display,backbuffer,window,clip_gc[PIX_FADEMASK],
283 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE, REAL_SX,REAL_SY);
287 redraw_mask &= ~REDRAW_MAIN;
296 XFillRectangle(display, backbuffer, gc,
297 REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE);
299 if (setup.soft_scrolling && game_status == PLAYING)
301 XFillRectangle(display, fieldbuffer, gc, 0, 0, FXSIZE, FYSIZE);
302 SetDrawtoField(DRAW_BUFFERED);
305 SetDrawtoField(DRAW_BACKBUFFER);
307 if (setup.direct_draw && game_status == PLAYING)
309 XFillRectangle(display, window, gc,
310 REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE);
311 SetDrawtoField(DRAW_DIRECT);
314 redraw_mask |= REDRAW_FIELD;
317 int getFontWidth(int font_size, int font_type)
319 return (font_size == FS_BIG ? FONT1_XSIZE :
320 font_type == FC_SPECIAL1 ? FONT3_XSIZE :
321 font_type == FC_SPECIAL2 ? FONT4_XSIZE :
322 font_type == FC_SPECIAL3 ? FONT5_XSIZE :
326 int getFontHeight(int font_size, int font_type)
328 return (font_size == FS_BIG ? FONT1_YSIZE :
329 font_type == FC_SPECIAL1 ? FONT3_YSIZE :
330 font_type == FC_SPECIAL2 ? FONT4_YSIZE :
331 font_type == FC_SPECIAL3 ? FONT5_YSIZE :
335 void DrawTextFCentered(int y, int font_type, char *format, ...)
337 char buffer[FULL_SXSIZE / FONT5_XSIZE + 10];
338 int font_width = getFontWidth(FS_SMALL, font_type);
341 va_start(ap, format);
342 vsprintf(buffer, format, ap);
345 DrawText(SX + (SXSIZE - strlen(buffer) * font_width) / 2, SY + y,
346 buffer, FS_SMALL, font_type);
349 void DrawTextF(int x, int y, int font_type, char *format, ...)
351 char buffer[FULL_SXSIZE / FONT5_XSIZE + 10];
354 va_start(ap, format);
355 vsprintf(buffer, format, ap);
358 DrawText(SX + x, SY + y, buffer, FS_SMALL, font_type);
361 void DrawText(int x, int y, char *text, int font_size, int font_type)
363 DrawTextExt(drawto, gc, x, y, text, font_size, font_type);
366 redraw_mask |= REDRAW_FIELD;
368 redraw_mask |= REDRAW_DOOR_1;
371 void DrawTextExt(Drawable d, GC gc, int x, int y,
372 char *text, int font_size, int font_type)
374 int font_width, font_height, font_start;
376 boolean print_inverse = FALSE;
378 if (font_size != FS_SMALL && font_size != FS_BIG)
379 font_size = FS_SMALL;
380 if (font_type < FC_RED || font_type > FC_SPECIAL3)
383 font_width = getFontWidth(font_size, font_type);
384 font_height = getFontHeight(font_size, font_type);
386 font_pixmap = (font_size == FS_BIG ? PIX_BIGFONT : PIX_SMALLFONT);
387 font_start = (font_type * (font_size == FS_BIG ? FONT1_YSIZE : FONT2_YSIZE) *
388 FONT_LINES_PER_FONT);
390 if (font_type == FC_SPECIAL3)
391 font_start += (FONT4_YSIZE - FONT2_YSIZE) * FONT_LINES_PER_FONT;
397 if (c == '~' && font_size == FS_SMALL)
399 print_inverse = TRUE;
403 if (c >= 'a' && c <= 'z')
405 else if (c == 'ä' || c == 'Ä')
407 else if (c == 'ö' || c == 'Ö')
409 else if (c == 'ü' || c == 'Ü')
412 if (c >= 32 && c <= 95)
414 int src_x = ((c - 32) % FONT_CHARS_PER_LINE) * font_width;
415 int src_y = ((c - 32) / FONT_CHARS_PER_LINE) * font_height + font_start;
416 int dest_x = x, dest_y = y;
420 XCopyArea(display, pix[font_pixmap], d, gc,
421 FONT_CHARS_PER_LINE * font_width,
422 3 * font_height + font_start,
423 font_width, font_height, x, y);
425 XSetClipOrigin(display, clip_gc[font_pixmap],
426 dest_x - src_x, dest_y - src_y);
427 XCopyArea(display, pix[font_pixmap], d, clip_gc[font_pixmap],
428 0, 0, font_width, font_height, dest_x, dest_y);
431 XCopyArea(display, pix[font_pixmap], d, gc,
432 src_x, src_y, font_width, font_height, dest_x, dest_y);
439 void DrawAllPlayers()
443 for(i=0; i<MAX_PLAYERS; i++)
444 if (stored_player[i].active)
445 DrawPlayer(&stored_player[i]);
448 void DrawPlayerField(int x, int y)
450 if (!IS_PLAYER(x, y))
453 DrawPlayer(PLAYERINFO(x, y));
456 void DrawPlayer(struct PlayerInfo *player)
458 int jx = player->jx, jy = player->jy;
459 int last_jx = player->last_jx, last_jy = player->last_jy;
460 int next_jx = jx + (jx - last_jx), next_jy = jy + (jy - last_jy);
461 int sx = SCREENX(jx), sy = SCREENY(jy);
462 int sxx = 0, syy = 0;
463 int element = Feld[jx][jy], last_element = Feld[last_jx][last_jy];
465 boolean player_is_moving = (last_jx != jx || last_jy != jy ? TRUE : FALSE);
467 if (!player->active || !IN_SCR_FIELD(SCREENX(last_jx), SCREENY(last_jy)))
471 if (!IN_LEV_FIELD(jx,jy))
473 printf("DrawPlayerField(): x = %d, y = %d\n",jx,jy);
474 printf("DrawPlayerField(): sx = %d, sy = %d\n",sx,sy);
475 printf("DrawPlayerField(): This should never happen!\n");
480 if (element == EL_EXPLODING)
483 /* draw things in the field the player is leaving, if needed */
485 if (player_is_moving)
487 if (Store[last_jx][last_jy] && IS_DRAWABLE(last_element))
489 DrawLevelElement(last_jx, last_jy, Store[last_jx][last_jy]);
490 DrawLevelFieldThruMask(last_jx, last_jy);
492 else if (last_element == EL_DYNAMIT)
493 DrawDynamite(last_jx, last_jy);
495 DrawLevelField(last_jx, last_jy);
497 if (player->Pushing && IN_SCR_FIELD(SCREENX(next_jx), SCREENY(next_jy)))
501 if (Feld[next_jx][next_jy] == EL_SOKOBAN_FELD_VOLL)
502 DrawLevelElement(next_jx, next_jy, EL_SOKOBAN_FELD_LEER);
504 DrawLevelElement(next_jx, next_jy, EL_LEERRAUM);
507 DrawLevelField(next_jx, next_jy);
511 if (!IN_SCR_FIELD(sx, sy))
514 if (setup.direct_draw)
515 SetDrawtoField(DRAW_BUFFERED);
517 /* draw things behind the player, if needed */
520 DrawLevelElement(jx, jy, Store[jx][jy]);
521 else if (element != EL_DYNAMIT && element != EL_DYNABOMB)
522 DrawLevelField(jx, jy);
524 /* draw player himself */
526 if (game.emulation == EMU_SUPAPLEX)
528 static int last_dir = MV_LEFT;
529 int action = (player->programmed_action ? player->programmed_action :
531 boolean action_moving =
533 ((action & (MV_LEFT | MV_RIGHT | MV_UP | MV_DOWN)) &&
534 !(action & ~(MV_LEFT | MV_RIGHT | MV_UP | MV_DOWN))));
536 graphic = GFX_SP_MURPHY;
540 if (player->MovDir == MV_LEFT)
541 graphic = GFX_MURPHY_PUSH_LEFT;
542 else if (player->MovDir == MV_RIGHT)
543 graphic = GFX_MURPHY_PUSH_RIGHT;
544 else if (player->MovDir & (MV_UP | MV_DOWN) && last_dir == MV_LEFT)
545 graphic = GFX_MURPHY_PUSH_LEFT;
546 else if (player->MovDir & (MV_UP | MV_DOWN) && last_dir == MV_RIGHT)
547 graphic = GFX_MURPHY_PUSH_RIGHT;
549 else if (player->snapped)
551 if (player->MovDir == MV_LEFT)
552 graphic = GFX_MURPHY_SNAP_LEFT;
553 else if (player->MovDir == MV_RIGHT)
554 graphic = GFX_MURPHY_SNAP_RIGHT;
555 else if (player->MovDir == MV_UP)
556 graphic = GFX_MURPHY_SNAP_UP;
557 else if (player->MovDir == MV_DOWN)
558 graphic = GFX_MURPHY_SNAP_DOWN;
560 else if (action_moving)
562 if (player->MovDir == MV_LEFT)
563 graphic = GFX_MURPHY_GO_LEFT;
564 else if (player->MovDir == MV_RIGHT)
565 graphic = GFX_MURPHY_GO_RIGHT;
566 else if (player->MovDir & (MV_UP | MV_DOWN) && last_dir == MV_LEFT)
567 graphic = GFX_MURPHY_GO_LEFT;
568 else if (player->MovDir & (MV_UP | MV_DOWN) && last_dir == MV_RIGHT)
569 graphic = GFX_MURPHY_GO_RIGHT;
571 graphic += getGraphicAnimationPhase(3, 2, ANIM_OSCILLATE);
574 if (player->MovDir == MV_LEFT || player->MovDir == MV_RIGHT)
575 last_dir = player->MovDir;
579 if (player->MovDir == MV_LEFT)
581 (player->Pushing ? GFX_SPIELER1_PUSH_LEFT : GFX_SPIELER1_LEFT);
582 else if (player->MovDir == MV_RIGHT)
584 (player->Pushing ? GFX_SPIELER1_PUSH_RIGHT : GFX_SPIELER1_RIGHT);
585 else if (player->MovDir == MV_UP)
586 graphic = GFX_SPIELER1_UP;
587 else /* MV_DOWN || MV_NO_MOVING */
588 graphic = GFX_SPIELER1_DOWN;
590 graphic += player->index_nr * 3 * HEROES_PER_LINE;
591 graphic += player->Frame;
596 if (player->MovDir == MV_LEFT || player->MovDir == MV_RIGHT)
597 sxx = player->GfxPos;
599 syy = player->GfxPos;
602 if (!setup.soft_scrolling && ScreenMovPos)
605 DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, NO_CUTTING);
607 if (player->Pushing && player->GfxPos)
609 int px = SCREENX(next_jx), py = SCREENY(next_jy);
611 if (element == EL_SOKOBAN_FELD_LEER ||
612 Feld[next_jx][next_jy] == EL_SOKOBAN_FELD_VOLL)
613 DrawGraphicShiftedThruMask(px, py, sxx, syy, GFX_SOKOBAN_OBJEKT,
617 int element = Feld[next_jx][next_jy];
618 int graphic = el2gfx(element);
620 if ((element == EL_FELSBROCKEN || element == EL_SP_ZONK) && sxx)
622 int phase = (player->GfxPos / (TILEX / 4));
624 if (player->MovDir == MV_LEFT)
627 graphic += (phase + 4) % 4;
630 DrawGraphicShifted(px, py, sxx, syy, graphic, NO_CUTTING, NO_MASKING);
634 /* draw things in front of player (EL_DYNAMIT or EL_DYNABOMB) */
636 if (element == EL_DYNAMIT || element == EL_DYNABOMB)
638 graphic = el2gfx(element);
640 if (element == EL_DYNAMIT)
642 if ((phase = (96 - MovDelay[jx][jy]) / 12) > 6)
647 if ((phase = ((96 - MovDelay[jx][jy]) / 6) % 8) > 3)
651 if (game.emulation == EMU_SUPAPLEX)
652 DrawGraphic(sx, sy, GFX_SP_DISK_RED);
654 DrawGraphicThruMask(sx, sy, graphic + phase);
657 if (player_is_moving && last_element == EL_EXPLODING)
659 int phase = Frame[last_jx][last_jy];
663 DrawGraphicThruMask(SCREENX(last_jx), SCREENY(last_jy),
664 GFX_EXPLOSION + ((phase - 1) / delay - 1));
667 /* draw elements that stay over the player */
668 /* handle the field the player is leaving ... */
669 if (player_is_moving && IS_OVER_PLAYER(last_element))
670 DrawLevelField(last_jx, last_jy);
671 /* ... and the field the player is entering */
672 if (IS_OVER_PLAYER(element))
673 DrawLevelField(jx, jy);
675 if (setup.direct_draw)
677 int dest_x = SX + SCREENX(MIN(jx, last_jx)) * TILEX;
678 int dest_y = SY + SCREENY(MIN(jy, last_jy)) * TILEY;
679 int x_size = TILEX * (1 + ABS(jx - last_jx));
680 int y_size = TILEY * (1 + ABS(jy - last_jy));
682 XCopyArea(display, drawto_field, window, gc,
683 dest_x, dest_y, x_size, y_size, dest_x, dest_y);
684 SetDrawtoField(DRAW_DIRECT);
687 MarkTileDirty(sx,sy);
690 static int getGraphicAnimationPhase(int frames, int delay, int mode)
694 if (mode == ANIM_OSCILLATE)
696 int max_anim_frames = 2 * frames - 2;
697 phase = (FrameCounter % (delay * max_anim_frames)) / delay;
698 phase = (phase < frames ? phase : max_anim_frames - phase);
701 phase = (FrameCounter % (delay * frames)) / delay;
703 if (mode == ANIM_REVERSE)
709 void DrawGraphicAnimationExt(int x, int y, int graphic,
710 int frames, int delay, int mode, int mask_mode)
712 int phase = getGraphicAnimationPhase(frames, delay, mode);
714 if (!(FrameCounter % delay) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
716 if (mask_mode == USE_MASKING)
717 DrawGraphicThruMask(SCREENX(x), SCREENY(y), graphic + phase);
719 DrawGraphic(SCREENX(x), SCREENY(y), graphic + phase);
723 void DrawGraphicAnimation(int x, int y, int graphic,
724 int frames, int delay, int mode)
726 DrawGraphicAnimationExt(x, y, graphic, frames, delay, mode, NO_MASKING);
729 void DrawGraphicAnimationThruMask(int x, int y, int graphic,
730 int frames, int delay, int mode)
732 DrawGraphicAnimationExt(x, y, graphic, frames, delay, mode, USE_MASKING);
735 void getGraphicSource(int graphic, int *pixmap_nr, int *x, int *y)
737 if (graphic >= GFX_START_ROCKSSCREEN && graphic <= GFX_END_ROCKSSCREEN)
739 graphic -= GFX_START_ROCKSSCREEN;
740 *pixmap_nr = PIX_BACK;
741 *x = SX + (graphic % GFX_PER_LINE) * TILEX;
742 *y = SY + (graphic / GFX_PER_LINE) * TILEY;
744 else if (graphic >= GFX_START_ROCKSMORE && graphic <= GFX_END_ROCKSMORE)
746 graphic -= GFX_START_ROCKSMORE;
747 *pixmap_nr = PIX_MORE;
748 *x = (graphic % MORE_PER_LINE) * TILEX;
749 *y = (graphic / MORE_PER_LINE) * TILEY;
751 else if (graphic >= GFX_START_ROCKSHEROES && graphic <= GFX_END_ROCKSHEROES)
753 graphic -= GFX_START_ROCKSHEROES;
754 *pixmap_nr = PIX_HEROES;
755 *x = (graphic % HEROES_PER_LINE) * TILEX;
756 *y = (graphic / HEROES_PER_LINE) * TILEY;
758 else if (graphic >= GFX_START_ROCKSFONT && graphic <= GFX_END_ROCKSFONT)
760 graphic -= GFX_START_ROCKSFONT;
761 *pixmap_nr = PIX_BIGFONT;
762 *x = (graphic % FONT_CHARS_PER_LINE) * TILEX;
763 *y = ((graphic / FONT_CHARS_PER_LINE) * TILEY +
764 FC_SPECIAL1 * FONT_LINES_PER_FONT * TILEY);
768 *pixmap_nr = PIX_MORE;
774 void DrawGraphic(int x, int y, int graphic)
777 if (!IN_SCR_FIELD(x,y))
779 printf("DrawGraphic(): x = %d, y = %d, graphic = %d\n",x,y,graphic);
780 printf("DrawGraphic(): This should never happen!\n");
785 DrawGraphicExt(drawto_field, gc, FX + x*TILEX, FY + y*TILEY, graphic);
789 void DrawGraphicExt(Drawable d, GC gc, int x, int y, int graphic)
794 getGraphicSource(graphic, &pixmap_nr, &src_x, &src_y);
795 XCopyArea(display, pix[pixmap_nr], d, gc,
796 src_x, src_y, TILEX, TILEY, x, y);
799 void DrawGraphicThruMask(int x, int y, int graphic)
802 if (!IN_SCR_FIELD(x,y))
804 printf("DrawGraphicThruMask(): x = %d,y = %d, graphic = %d\n",x,y,graphic);
805 printf("DrawGraphicThruMask(): This should never happen!\n");
810 DrawGraphicThruMaskExt(drawto_field, FX + x*TILEX, FY + y*TILEY, graphic);
814 void DrawGraphicThruMaskExt(Drawable d, int dest_x, int dest_y, int graphic)
822 if (graphic == GFX_LEERRAUM)
825 getGraphicSource(graphic, &pixmap_nr, &src_x, &src_y);
826 src_pixmap = pix[pixmap_nr];
827 drawing_gc = clip_gc[pixmap_nr];
829 if (tile_clipmask[tile] != None)
831 XSetClipMask(display, tile_clip_gc, tile_clipmask[tile]);
832 XSetClipOrigin(display, tile_clip_gc, dest_x, dest_y);
833 XCopyArea(display, src_pixmap, d, tile_clip_gc,
834 src_x, src_y, TILEX, TILEY, dest_x, dest_y);
839 printf("DrawGraphicThruMask(): tile '%d' needs clipping!\n", tile);
842 XSetClipOrigin(display, drawing_gc, dest_x-src_x, dest_y-src_y);
843 XCopyArea(display, src_pixmap, d, drawing_gc,
844 src_x, src_y, TILEX, TILEY, dest_x, dest_y);
848 void DrawMiniGraphic(int x, int y, int graphic)
850 DrawMiniGraphicExt(drawto,gc, SX + x*MINI_TILEX, SY + y*MINI_TILEY, graphic);
851 MarkTileDirty(x/2, y/2);
854 void getMiniGraphicSource(int graphic, Pixmap *pixmap, int *x, int *y)
856 if (graphic >= GFX_START_ROCKSSCREEN && graphic <= GFX_END_ROCKSSCREEN)
858 graphic -= GFX_START_ROCKSSCREEN;
859 *pixmap = pix[PIX_BACK];
860 *x = MINI_GFX_STARTX + (graphic % MINI_GFX_PER_LINE) * MINI_TILEX;
861 *y = MINI_GFX_STARTY + (graphic / MINI_GFX_PER_LINE) * MINI_TILEY;
863 else if (graphic >= GFX_START_ROCKSMORE && graphic <= GFX_END_ROCKSMORE)
865 graphic -= GFX_START_ROCKSMORE;
866 graphic -= ((graphic / MORE_PER_LINE) * MORE_PER_LINE) / 2;
867 *pixmap = pix[PIX_MORE];
868 *x = MINI_MORE_STARTX + (graphic % MINI_MORE_PER_LINE) * MINI_TILEX;
869 *y = MINI_MORE_STARTY + (graphic / MINI_MORE_PER_LINE) * MINI_TILEY;
871 else if (graphic >= GFX_START_ROCKSFONT && graphic <= GFX_END_ROCKSFONT)
873 graphic -= GFX_START_ROCKSFONT;
874 *pixmap = pix[PIX_SMALLFONT];
875 *x = (graphic % FONT_CHARS_PER_LINE) * FONT4_XSIZE;
876 *y = ((graphic / FONT_CHARS_PER_LINE) * FONT4_YSIZE +
877 FC_SPECIAL2 * FONT2_YSIZE * FONT_LINES_PER_FONT);
881 *pixmap = pix[PIX_MORE];
882 *x = MINI_MORE_STARTX;
883 *y = MINI_MORE_STARTY;
887 void DrawMiniGraphicExt(Drawable d, GC gc, int x, int y, int graphic)
892 getMiniGraphicSource(graphic, &pixmap, &src_x, &src_y);
893 XCopyArea(display, pixmap, d, gc,
894 src_x, src_y, MINI_TILEX, MINI_TILEY, x, y);
897 void DrawGraphicShifted(int x,int y, int dx,int dy, int graphic,
898 int cut_mode, int mask_mode)
900 int width = TILEX, height = TILEY;
902 int src_x, src_y, dest_x, dest_y;
910 DrawGraphic(x, y, graphic);
914 if (dx || dy) /* Verschiebung der Grafik? */
916 if (x < BX1) /* Element kommt von links ins Bild */
923 else if (x > BX2) /* Element kommt von rechts ins Bild */
929 else if (x==BX1 && dx < 0) /* Element verläßt links das Bild */
935 else if (x==BX2 && dx > 0) /* Element verläßt rechts das Bild */
937 else if (dx) /* allg. Bewegung in x-Richtung */
938 MarkTileDirty(x + SIGN(dx), y);
940 if (y < BY1) /* Element kommt von oben ins Bild */
942 if (cut_mode==CUT_BELOW) /* Element oberhalb des Bildes */
950 else if (y > BY2) /* Element kommt von unten ins Bild */
956 else if (y==BY1 && dy < 0) /* Element verläßt oben das Bild */
962 else if (dy > 0 && cut_mode == CUT_ABOVE)
964 if (y == BY2) /* Element unterhalb des Bildes */
970 MarkTileDirty(x, y + 1);
971 } /* Element verläßt unten das Bild */
972 else if (dy > 0 && (y == BY2 || cut_mode == CUT_BELOW))
974 else if (dy) /* allg. Bewegung in y-Richtung */
975 MarkTileDirty(x, y + SIGN(dy));
978 getGraphicSource(graphic, &pixmap_nr, &src_x, &src_y);
979 src_pixmap = pix[pixmap_nr];
980 drawing_gc = clip_gc[pixmap_nr];
982 dest_x = FX + x * TILEX + dx;
983 dest_y = FY + y * TILEY + dy;
986 if (!IN_SCR_FIELD(x,y))
988 printf("DrawGraphicShifted(): x = %d, y = %d, graphic = %d\n",x,y,graphic);
989 printf("DrawGraphicShifted(): This should never happen!\n");
994 if (mask_mode == USE_MASKING)
996 if (tile_clipmask[tile] != None)
998 XSetClipMask(display, tile_clip_gc, tile_clipmask[tile]);
999 XSetClipOrigin(display, tile_clip_gc, dest_x, dest_y);
1000 XCopyArea(display, src_pixmap, drawto_field, tile_clip_gc,
1001 src_x, src_y, TILEX, TILEY, dest_x, dest_y);
1006 printf("DrawGraphicShifted(): tile '%d' needs clipping!\n", tile);
1009 XSetClipOrigin(display, drawing_gc, dest_x - src_x, dest_y - src_y);
1010 XCopyArea(display, src_pixmap, drawto_field, drawing_gc,
1011 src_x, src_y, width, height, dest_x, dest_y);
1015 XCopyArea(display, src_pixmap, drawto_field, gc,
1016 src_x, src_y, width, height, dest_x, dest_y);
1021 void DrawGraphicShiftedThruMask(int x,int y, int dx,int dy, int graphic,
1024 DrawGraphicShifted(x,y, dx,dy, graphic, cut_mode, USE_MASKING);
1027 void DrawScreenElementExt(int x, int y, int dx, int dy, int element,
1028 int cut_mode, int mask_mode)
1030 int ux = LEVELX(x), uy = LEVELY(y);
1031 int graphic = el2gfx(element);
1032 int phase8 = ABS(MovPos[ux][uy]) / (TILEX / 8);
1033 int phase4 = phase8 / 2;
1034 int phase2 = phase8 / 4;
1035 int dir = MovDir[ux][uy];
1037 if (element == EL_PACMAN || element == EL_KAEFER || element == EL_FLIEGER)
1039 graphic += 4 * !phase2;
1043 else if (dir == MV_LEFT)
1045 else if (dir == MV_DOWN)
1048 else if (element == EL_SP_SNIKSNAK)
1051 graphic = GFX_SP_SNIKSNAK_LEFT;
1052 else if (dir == MV_RIGHT)
1053 graphic = GFX_SP_SNIKSNAK_RIGHT;
1054 else if (dir == MV_UP)
1055 graphic = GFX_SP_SNIKSNAK_UP;
1057 graphic = GFX_SP_SNIKSNAK_DOWN;
1059 graphic += (phase8 < 4 ? phase8 : 7 - phase8);
1061 else if (element == EL_SP_ELECTRON)
1063 graphic = GFX2_SP_ELECTRON + getGraphicAnimationPhase(8, 2, ANIM_NORMAL);
1065 else if (element == EL_MAULWURF || element == EL_PINGUIN ||
1066 element == EL_SCHWEIN || element == EL_DRACHE)
1069 graphic = (element == EL_MAULWURF ? GFX_MAULWURF_LEFT :
1070 element == EL_PINGUIN ? GFX_PINGUIN_LEFT :
1071 element == EL_SCHWEIN ? GFX_SCHWEIN_LEFT : GFX_DRACHE_LEFT);
1072 else if (dir == MV_RIGHT)
1073 graphic = (element == EL_MAULWURF ? GFX_MAULWURF_RIGHT :
1074 element == EL_PINGUIN ? GFX_PINGUIN_RIGHT :
1075 element == EL_SCHWEIN ? GFX_SCHWEIN_RIGHT : GFX_DRACHE_RIGHT);
1076 else if (dir == MV_UP)
1077 graphic = (element == EL_MAULWURF ? GFX_MAULWURF_UP :
1078 element == EL_PINGUIN ? GFX_PINGUIN_UP :
1079 element == EL_SCHWEIN ? GFX_SCHWEIN_UP : GFX_DRACHE_UP);
1081 graphic = (element == EL_MAULWURF ? GFX_MAULWURF_DOWN :
1082 element == EL_PINGUIN ? GFX_PINGUIN_DOWN :
1083 element == EL_SCHWEIN ? GFX_SCHWEIN_DOWN : GFX_DRACHE_DOWN);
1087 else if (element == EL_SONDE)
1089 graphic = GFX_SONDE_START + getGraphicAnimationPhase(8, 2, ANIM_NORMAL);
1091 else if (element == EL_SALZSAEURE)
1093 graphic = GFX_GEBLUBBER + getGraphicAnimationPhase(4, 10, ANIM_NORMAL);
1095 else if (element == EL_BUTTERFLY || element == EL_FIREFLY)
1099 else if ((element == EL_FELSBROCKEN || element == EL_SP_ZONK ||
1100 IS_GEM(element)) && !cut_mode)
1102 if (element == EL_FELSBROCKEN || element == EL_SP_ZONK)
1105 graphic += (4 - phase4) % 4;
1106 else if (dir == MV_RIGHT)
1109 graphic += phase2 * 2;
1111 else if (element != EL_SP_INFOTRON)
1115 if (element == EL_SP_ZONK)
1118 graphic += (4 - phase4) % 4;
1119 else if (dir == MV_RIGHT)
1122 graphic += phase2 * 2;
1124 else if (element != EL_SP_INFOTRON)
1125 graphic += phase2 * (element == EL_FELSBROCKEN ? 2 : 1);
1129 else if (element == EL_SIEB_LEER || element == EL_SIEB2_LEER ||
1130 element == EL_SIEB_VOLL || element == EL_SIEB2_VOLL)
1132 graphic += 3 + getGraphicAnimationPhase(4, 4, ANIM_REVERSE);
1134 else if (IS_AMOEBOID(element))
1136 graphic = (element == EL_AMOEBE_TOT ? GFX_AMOEBE_TOT : GFX_AMOEBE_LEBT);
1137 graphic += (x + 2 * y + 4) % 4;
1139 else if (element == EL_MAUER_LEBT)
1141 boolean links_massiv = FALSE, rechts_massiv = FALSE;
1143 if (!IN_LEV_FIELD(ux-1, uy) || IS_MAUER(Feld[ux-1][uy]))
1144 links_massiv = TRUE;
1145 if (!IN_LEV_FIELD(ux+1, uy) || IS_MAUER(Feld[ux+1][uy]))
1146 rechts_massiv = TRUE;
1148 if (links_massiv && rechts_massiv)
1149 graphic = GFX_MAUERWERK;
1150 else if (links_massiv)
1151 graphic = GFX_MAUER_R;
1152 else if (rechts_massiv)
1153 graphic = GFX_MAUER_L;
1157 DrawGraphicShifted(x, y, dx, dy, graphic, cut_mode, mask_mode);
1158 else if (mask_mode == USE_MASKING)
1159 DrawGraphicThruMask(x, y, graphic);
1161 DrawGraphic(x, y, graphic);
1164 void DrawLevelElementExt(int x, int y, int dx, int dy, int element,
1165 int cut_mode, int mask_mode)
1167 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1168 DrawScreenElementExt(SCREENX(x), SCREENY(y), dx, dy, element,
1169 cut_mode, mask_mode);
1172 void DrawScreenElementShifted(int x, int y, int dx, int dy, int element,
1175 DrawScreenElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
1178 void DrawLevelElementShifted(int x, int y, int dx, int dy, int element,
1181 DrawLevelElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
1184 void DrawScreenElementThruMask(int x, int y, int element)
1186 DrawScreenElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
1189 void DrawLevelElementThruMask(int x, int y, int element)
1191 DrawLevelElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
1194 void DrawLevelFieldThruMask(int x, int y)
1196 DrawLevelElementExt(x, y, 0, 0, Feld[x][y], NO_CUTTING, USE_MASKING);
1199 void ErdreichAnbroeckeln(int x, int y)
1201 int i, width, height, cx,cy;
1202 int ux = LEVELX(x), uy = LEVELY(y);
1203 int element, graphic;
1205 static int xy[4][2] =
1213 if (!IN_LEV_FIELD(ux, uy))
1216 element = Feld[ux][uy];
1218 if (element == EL_ERDREICH)
1220 if (!IN_SCR_FIELD(x, y))
1223 graphic = GFX_ERDENRAND;
1229 uxx = ux + xy[i][0];
1230 uyy = uy + xy[i][1];
1231 if (!IN_LEV_FIELD(uxx, uyy))
1234 element = Feld[uxx][uyy];
1236 if (element == EL_ERDREICH)
1239 if (i == 1 || i == 2)
1243 cx = (i == 2 ? TILEX - snip : 0);
1251 cy = (i == 3 ? TILEY - snip : 0);
1254 XCopyArea(display, pix[PIX_BACK], drawto_field, gc,
1255 SX + (graphic % GFX_PER_LINE) * TILEX + cx,
1256 SY + (graphic / GFX_PER_LINE) * TILEY + cy,
1257 width, height, FX + x * TILEX + cx, FY + y * TILEY + cy);
1260 MarkTileDirty(x, y);
1264 graphic = GFX_ERDENRAND;
1268 int xx, yy, uxx, uyy;
1272 uxx = ux + xy[i][0];
1273 uyy = uy + xy[i][1];
1275 if (!IN_LEV_FIELD(uxx, uyy) || Feld[uxx][uyy] != EL_ERDREICH ||
1276 !IN_SCR_FIELD(xx, yy))
1279 if (i == 1 || i == 2)
1283 cx = (i == 1 ? TILEX - snip : 0);
1291 cy = (i==0 ? TILEY-snip : 0);
1294 XCopyArea(display, pix[PIX_BACK], drawto_field, gc,
1295 SX + (graphic % GFX_PER_LINE) * TILEX + cx,
1296 SY + (graphic / GFX_PER_LINE) * TILEY + cy,
1297 width, height, FX + xx * TILEX + cx, FY + yy * TILEY + cy);
1299 MarkTileDirty(xx, yy);
1304 void DrawScreenElement(int x, int y, int element)
1306 DrawScreenElementExt(x, y, 0, 0, element, NO_CUTTING, NO_MASKING);
1307 ErdreichAnbroeckeln(x, y);
1310 void DrawLevelElement(int x, int y, int element)
1312 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1313 DrawScreenElement(SCREENX(x), SCREENY(y), element);
1316 void DrawScreenField(int x, int y)
1318 int ux = LEVELX(x), uy = LEVELY(y);
1321 if (!IN_LEV_FIELD(ux, uy))
1323 if (ux < -1 || ux > lev_fieldx || uy < -1 || uy > lev_fieldy)
1324 element = EL_LEERRAUM;
1326 element = BorderElement;
1328 DrawScreenElement(x, y, element);
1332 element = Feld[ux][uy];
1334 if (IS_MOVING(ux, uy))
1336 int horiz_move = (MovDir[ux][uy] == MV_LEFT || MovDir[ux][uy] == MV_RIGHT);
1337 boolean cut_mode = NO_CUTTING;
1339 if (Store[ux][uy] == EL_MORAST_LEER ||
1340 Store[ux][uy] == EL_SIEB_LEER ||
1341 Store[ux][uy] == EL_SIEB2_LEER ||
1342 Store[ux][uy] == EL_AMOEBE_NASS)
1343 cut_mode = CUT_ABOVE;
1344 else if (Store[ux][uy] == EL_MORAST_VOLL ||
1345 Store[ux][uy] == EL_SIEB_VOLL ||
1346 Store[ux][uy] == EL_SIEB2_VOLL)
1347 cut_mode = CUT_BELOW;
1349 if (cut_mode == CUT_ABOVE)
1350 DrawScreenElementShifted(x, y, 0, 0, Store[ux][uy], NO_CUTTING);
1352 DrawScreenElement(x, y, EL_LEERRAUM);
1355 DrawScreenElementShifted(x, y, MovPos[ux][uy], 0, element, NO_CUTTING);
1357 DrawScreenElementShifted(x, y, 0, MovPos[ux][uy], element, cut_mode);
1359 if (Store[ux][uy] == EL_SALZSAEURE)
1360 DrawLevelElementThruMask(ux, uy + 1, EL_SALZSAEURE);
1362 else if (IS_BLOCKED(ux, uy))
1367 boolean cut_mode = NO_CUTTING;
1369 Blocked2Moving(ux, uy, &oldx, &oldy);
1372 horiz_move = (MovDir[oldx][oldy] == MV_LEFT ||
1373 MovDir[oldx][oldy] == MV_RIGHT);
1375 if (Store[oldx][oldy] == EL_MORAST_LEER ||
1376 Store[oldx][oldy] == EL_SIEB_LEER ||
1377 Store[oldx][oldy] == EL_SIEB2_LEER ||
1378 Store[oldx][oldy] == EL_AMOEBE_NASS)
1379 cut_mode = CUT_ABOVE;
1381 DrawScreenElement(x, y, EL_LEERRAUM);
1382 element = Feld[oldx][oldy];
1385 DrawScreenElementShifted(sx,sy, MovPos[oldx][oldy],0,element,NO_CUTTING);
1387 DrawScreenElementShifted(sx,sy, 0,MovPos[oldx][oldy],element,cut_mode);
1389 else if (IS_DRAWABLE(element))
1390 DrawScreenElement(x, y, element);
1392 DrawScreenElement(x, y, EL_LEERRAUM);
1395 void DrawLevelField(int x, int y)
1397 if (IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1398 DrawScreenField(SCREENX(x), SCREENY(y));
1399 else if (IS_MOVING(x, y))
1403 Moving2Blocked(x, y, &newx, &newy);
1404 if (IN_SCR_FIELD(SCREENX(newx), SCREENY(newy)))
1405 DrawScreenField(SCREENX(newx), SCREENY(newy));
1407 else if (IS_BLOCKED(x, y))
1411 Blocked2Moving(x, y, &oldx, &oldy);
1412 if (IN_SCR_FIELD(SCREENX(oldx), SCREENY(oldy)))
1413 DrawScreenField(SCREENX(oldx), SCREENY(oldy));
1417 void DrawMiniElement(int x, int y, int element)
1423 DrawMiniGraphic(x, y, -1);
1427 graphic = el2gfx(element);
1428 DrawMiniGraphic(x, y, graphic);
1431 void DrawMiniElementOrWall(int sx, int sy, int scroll_x, int scroll_y)
1433 int x = sx + scroll_x, y = sy + scroll_y;
1435 if (x < -1 || x > lev_fieldx || y < -1 || y > lev_fieldy)
1436 DrawMiniElement(sx, sy, EL_LEERRAUM);
1437 else if (x > -1 && x < lev_fieldx && y > -1 && y < lev_fieldy)
1438 DrawMiniElement(sx, sy, Feld[x][y]);
1441 int steel_type, steel_position;
1444 { GFX_VSTEEL_UPPER_LEFT, GFX_ISTEEL_UPPER_LEFT },
1445 { GFX_VSTEEL_UPPER_RIGHT, GFX_ISTEEL_UPPER_RIGHT },
1446 { GFX_VSTEEL_LOWER_LEFT, GFX_ISTEEL_LOWER_LEFT },
1447 { GFX_VSTEEL_LOWER_RIGHT, GFX_ISTEEL_LOWER_RIGHT },
1448 { GFX_VSTEEL_VERTICAL, GFX_ISTEEL_VERTICAL },
1449 { GFX_VSTEEL_HORIZONTAL, GFX_ISTEEL_HORIZONTAL }
1452 steel_type = (BorderElement == EL_BETON ? 0 : 1);
1453 steel_position = (x == -1 && y == -1 ? 0 :
1454 x == lev_fieldx && y == -1 ? 1 :
1455 x == -1 && y == lev_fieldy ? 2 :
1456 x == lev_fieldx && y == lev_fieldy ? 3 :
1457 x == -1 || x == lev_fieldx ? 4 :
1458 y == -1 || y == lev_fieldy ? 5 : -1);
1460 if (steel_position != -1)
1461 DrawMiniGraphic(sx, sy, border[steel_position][steel_type]);
1465 void DrawMicroElement(int xpos, int ypos, int element)
1469 if (element == EL_LEERRAUM)
1472 graphic = el2gfx(element);
1474 if (graphic >= GFX_START_ROCKSMORE && graphic <= GFX_END_ROCKSMORE)
1476 graphic -= GFX_START_ROCKSMORE;
1477 graphic -= ((graphic / MORE_PER_LINE) * MORE_PER_LINE) / 2;
1478 XCopyArea(display, pix[PIX_MORE], drawto, gc,
1479 MICRO_MORE_STARTX + (graphic % MICRO_MORE_PER_LINE) *MICRO_TILEX,
1480 MICRO_MORE_STARTY + (graphic / MICRO_MORE_PER_LINE) *MICRO_TILEY,
1481 MICRO_TILEX, MICRO_TILEY, xpos, ypos);
1484 XCopyArea(display, pix[PIX_BACK], drawto, gc,
1485 MICRO_GFX_STARTX + (graphic % MICRO_GFX_PER_LINE) * MICRO_TILEX,
1486 MICRO_GFX_STARTY + (graphic / MICRO_GFX_PER_LINE) * MICRO_TILEY,
1487 MICRO_TILEX, MICRO_TILEY, xpos, ypos);
1496 for(x=BX1; x<=BX2; x++)
1497 for(y=BY1; y<=BY2; y++)
1498 DrawScreenField(x, y);
1500 redraw_mask |= REDRAW_FIELD;
1503 void DrawMiniLevel(int size_x, int size_y, int scroll_x, int scroll_y)
1507 for(x=0; x<size_x; x++)
1508 for(y=0; y<size_y; y++)
1509 DrawMiniElementOrWall(x, y, scroll_x, scroll_y);
1511 redraw_mask |= REDRAW_FIELD;
1514 static void DrawMicroLevelExt(int xpos, int ypos, int from_x, int from_y)
1518 XFillRectangle(display, drawto, gc,
1519 xpos, ypos, MICROLEV_XSIZE, MICROLEV_YSIZE);
1521 if (lev_fieldx < STD_LEV_FIELDX)
1522 xpos += (STD_LEV_FIELDX - lev_fieldx) / 2 * MICRO_TILEX;
1523 if (lev_fieldy < STD_LEV_FIELDY)
1524 ypos += (STD_LEV_FIELDY - lev_fieldy) / 2 * MICRO_TILEY;
1526 xpos += MICRO_TILEX;
1527 ypos += MICRO_TILEY;
1529 for(x=-1; x<=STD_LEV_FIELDX; x++)
1531 for(y=-1; y<=STD_LEV_FIELDY; y++)
1533 int lx = from_x + x, ly = from_y + y;
1535 if (lx >= 0 && lx < lev_fieldx && ly >= 0 && ly < lev_fieldy)
1536 DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
1538 else if (lx >= -1 && lx < lev_fieldx+1 && ly >= -1 && ly < lev_fieldy+1)
1539 DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
1544 redraw_mask |= REDRAW_MICROLEVEL;
1547 static void DrawMicroLevelLabelExt(int mode)
1549 char label_text[100];
1551 XFillRectangle(display, drawto,gc,
1552 SX, MICROLABEL_YPOS, SXSIZE, FONT4_YSIZE);
1554 strcpy(label_text, (mode == 1 ? level.name :
1555 mode == 2 ? "created by" :
1556 mode == 3 ? level.author : ""));
1558 if (strlen(label_text) > 0)
1560 int size, lxpos, lypos;
1562 label_text[SXSIZE / FONT4_XSIZE] = '\0';
1564 size = strlen(label_text);
1565 lxpos = SX + (SXSIZE - size * FONT4_XSIZE) / 2;
1566 lypos = MICROLABEL_YPOS;
1568 DrawText(lxpos, lypos, label_text, FS_SMALL, FC_SPECIAL2);
1571 redraw_mask |= REDRAW_MICROLEVEL;
1574 void DrawMicroLevel(int xpos, int ypos, boolean restart)
1576 static unsigned long scroll_delay = 0;
1577 static unsigned long label_delay = 0;
1578 static int from_x, from_y, scroll_direction;
1579 static int label_state, label_counter;
1583 from_x = from_y = 0;
1584 scroll_direction = MV_RIGHT;
1588 DrawMicroLevelExt(xpos, ypos, from_x, from_y);
1589 DrawMicroLevelLabelExt(label_state);
1591 /* initialize delay counters */
1592 DelayReached(&scroll_delay, 0);
1593 DelayReached(&label_delay, 0);
1598 /* scroll micro level, if needed */
1599 if ((lev_fieldx > STD_LEV_FIELDX || lev_fieldy > STD_LEV_FIELDY) &&
1600 DelayReached(&scroll_delay, MICROLEVEL_SCROLL_DELAY))
1602 switch (scroll_direction)
1608 scroll_direction = MV_UP;
1612 if (from_x < lev_fieldx - STD_LEV_FIELDX)
1615 scroll_direction = MV_DOWN;
1622 scroll_direction = MV_RIGHT;
1626 if (from_y < lev_fieldy - STD_LEV_FIELDY)
1629 scroll_direction = MV_LEFT;
1636 DrawMicroLevelExt(xpos, ypos, from_x, from_y);
1639 /* redraw micro level label, if needed */
1640 if (strcmp(level.name, NAMELESS_LEVEL_NAME) != 0 &&
1641 strcmp(level.author, ANONYMOUS_NAME) != 0 &&
1642 strcmp(level.author, leveldir[leveldir_nr].name) != 0 &&
1643 DelayReached(&label_delay, MICROLEVEL_LABEL_DELAY))
1645 label_counter = (label_counter + 1) % 23;
1646 label_state = (label_counter >= 0 && label_counter <= 7 ? 1 :
1647 label_counter >= 9 && label_counter <= 12 ? 2 :
1648 label_counter >= 14 && label_counter <= 21 ? 3 : 0);
1649 DrawMicroLevelLabelExt(label_state);
1653 int REQ_in_range(int x, int y)
1655 if (y > DY+249 && y < DY+278)
1657 if (x > DX+1 && x < DX+48)
1659 else if (x > DX+51 && x < DX+98)
1665 boolean Request(char *text, unsigned int req_state)
1667 int mx, my, ty, result = -1;
1668 unsigned int old_door_state;
1671 /* pause network game while waiting for request to answer */
1672 if (options.network &&
1673 game_status == PLAYING &&
1674 req_state & REQUEST_WAIT_FOR)
1675 SendToServer_PausePlaying();
1678 old_door_state = GetDoorState();
1682 CloseDoor(DOOR_CLOSE_1);
1684 /* save old door content */
1685 XCopyArea(display, pix[PIX_DB_DOOR], pix[PIX_DB_DOOR], gc,
1686 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE,
1687 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1);
1689 /* clear door drawing field */
1690 XFillRectangle(display, drawto, gc, DX, DY, DXSIZE, DYSIZE);
1692 /* write text for request */
1693 for(ty=0; ty<13; ty++)
1701 for(tl=0,tx=0; tx<7; tl++,tx++)
1704 if (!tc || tc == 32)
1715 DrawTextExt(drawto, gc,
1716 DX + 51 - (tl * 14)/2, DY + 8 + ty * 16,
1717 txt, FS_SMALL, FC_YELLOW);
1718 text += tl + (tc == 32 ? 1 : 0);
1721 if (req_state & REQ_ASK)
1723 MapGadget(tool_gadget[TOOL_CTRL_ID_YES]);
1724 MapGadget(tool_gadget[TOOL_CTRL_ID_NO]);
1726 else if (req_state & REQ_CONFIRM)
1728 MapGadget(tool_gadget[TOOL_CTRL_ID_CONFIRM]);
1730 else if (req_state & REQ_PLAYER)
1732 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_1]);
1733 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_2]);
1734 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_3]);
1735 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_4]);
1738 /* copy request gadgets to door backbuffer */
1739 XCopyArea(display, drawto, pix[PIX_DB_DOOR], gc,
1740 DX, DY, DXSIZE, DYSIZE,
1741 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
1743 OpenDoor(DOOR_OPEN_1);
1749 if (!(req_state & REQUEST_WAIT_FOR))
1752 if (game_status != MAINMENU)
1755 button_status = MB_RELEASED;
1757 request_gadget_id = -1;
1761 if (XPending(display))
1765 XNextEvent(display, &event);
1773 if (event.type == MotionNotify)
1780 if (!XQueryPointer(display, window, &root, &child,
1781 &root_x, &root_y, &win_x, &win_y, &mask))
1787 motion_status = TRUE;
1788 mx = ((XMotionEvent *) &event)->x;
1789 my = ((XMotionEvent *) &event)->y;
1793 motion_status = FALSE;
1794 mx = ((XButtonEvent *) &event)->x;
1795 my = ((XButtonEvent *) &event)->y;
1796 if (event.type==ButtonPress)
1797 button_status = ((XButtonEvent *) &event)->button;
1799 button_status = MB_RELEASED;
1802 /* this sets 'request_gadget_id' */
1803 HandleGadgets(mx, my, button_status);
1805 switch(request_gadget_id)
1807 case TOOL_CTRL_ID_YES:
1810 case TOOL_CTRL_ID_NO:
1813 case TOOL_CTRL_ID_CONFIRM:
1814 result = TRUE | FALSE;
1817 case TOOL_CTRL_ID_PLAYER_1:
1820 case TOOL_CTRL_ID_PLAYER_2:
1823 case TOOL_CTRL_ID_PLAYER_3:
1826 case TOOL_CTRL_ID_PLAYER_4:
1838 switch(XLookupKeysym((XKeyEvent *)&event,
1839 ((XKeyEvent *)&event)->state))
1852 if (req_state & REQ_PLAYER)
1857 key_joystick_mapping = 0;
1861 HandleOtherEvents(&event);
1865 else if (AnyJoystickButton() == JOY_BUTTON_NEW_PRESSED)
1867 int joy = AnyJoystick();
1869 if (joy & JOY_BUTTON_1)
1871 else if (joy & JOY_BUTTON_2)
1877 /* don't eat all CPU time */
1881 if (game_status != MAINMENU)
1886 if (!(req_state & REQ_STAY_OPEN))
1888 CloseDoor(DOOR_CLOSE_1);
1890 if (!(req_state & REQ_STAY_CLOSED) && (old_door_state & DOOR_OPEN_1))
1892 XCopyArea(display,pix[PIX_DB_DOOR],pix[PIX_DB_DOOR],gc,
1893 DOOR_GFX_PAGEX2,DOOR_GFX_PAGEY1, DXSIZE,DYSIZE,
1894 DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY1);
1895 OpenDoor(DOOR_OPEN_1);
1902 /* continue network game after request */
1903 if (options.network &&
1904 game_status == PLAYING &&
1905 req_state & REQUEST_WAIT_FOR)
1906 SendToServer_ContinuePlaying();
1912 unsigned int OpenDoor(unsigned int door_state)
1914 unsigned int new_door_state;
1916 if (door_state & DOOR_COPY_BACK)
1918 XCopyArea(display, pix[PIX_DB_DOOR], pix[PIX_DB_DOOR], gc,
1919 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE + VYSIZE,
1920 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
1921 door_state &= ~DOOR_COPY_BACK;
1924 new_door_state = MoveDoor(door_state);
1926 return(new_door_state);
1929 unsigned int CloseDoor(unsigned int door_state)
1931 unsigned int new_door_state;
1933 XCopyArea(display, backbuffer, pix[PIX_DB_DOOR], gc,
1934 DX, DY, DXSIZE, DYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
1935 XCopyArea(display, backbuffer, pix[PIX_DB_DOOR], gc,
1936 VX, VY, VXSIZE, VYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2);
1938 new_door_state = MoveDoor(door_state);
1940 return(new_door_state);
1943 unsigned int GetDoorState()
1945 return(MoveDoor(DOOR_GET_STATE));
1948 unsigned int MoveDoor(unsigned int door_state)
1950 static int door1 = DOOR_OPEN_1;
1951 static int door2 = DOOR_CLOSE_2;
1952 static unsigned long door_delay = 0;
1953 int x, start, stepsize = 2;
1954 unsigned long door_delay_value = stepsize * 5;
1956 if (door_state == DOOR_GET_STATE)
1957 return(door1 | door2);
1959 if (door1 == DOOR_OPEN_1 && door_state & DOOR_OPEN_1)
1960 door_state &= ~DOOR_OPEN_1;
1961 else if (door1 == DOOR_CLOSE_1 && door_state & DOOR_CLOSE_1)
1962 door_state &= ~DOOR_CLOSE_1;
1963 if (door2 == DOOR_OPEN_2 && door_state & DOOR_OPEN_2)
1964 door_state &= ~DOOR_OPEN_2;
1965 else if (door2 == DOOR_CLOSE_2 && door_state & DOOR_CLOSE_2)
1966 door_state &= ~DOOR_CLOSE_2;
1968 if (setup.quick_doors)
1971 door_delay_value = 0;
1972 StopSound(SND_OEFFNEN);
1975 if (door_state & DOOR_ACTION)
1977 if (!(door_state & DOOR_NO_DELAY))
1978 PlaySoundStereo(SND_OEFFNEN, PSND_MAX_RIGHT);
1980 start = ((door_state & DOOR_NO_DELAY) ? DXSIZE : 0);
1982 for(x=start; x<=DXSIZE; x+=stepsize)
1984 WaitUntilDelayReached(&door_delay, door_delay_value);
1986 if (door_state & DOOR_ACTION_1)
1988 int i = (door_state & DOOR_OPEN_1 ? DXSIZE-x : x);
1989 int j = (DXSIZE - i) / 3;
1991 XCopyArea(display, pix[PIX_DB_DOOR], drawto, gc,
1992 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1 + i/2,
1993 DXSIZE,DYSIZE - i/2, DX, DY);
1995 XFillRectangle(display, drawto, gc, DX, DY + DYSIZE - i/2, DXSIZE,i/2);
1997 XSetClipOrigin(display, clip_gc[PIX_DOOR],
1998 DX - i, (DY + j) - DOOR_GFX_PAGEY1);
1999 XCopyArea(display, pix[PIX_DOOR], drawto,clip_gc[PIX_DOOR],
2000 DXSIZE, DOOR_GFX_PAGEY1, i, 77, DX + DXSIZE - i, DY + j);
2001 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2002 DXSIZE, DOOR_GFX_PAGEY1 + 140, i, 63, DX + DXSIZE - i,
2004 XSetClipOrigin(display, clip_gc[PIX_DOOR],
2005 DX - DXSIZE + i, DY - (DOOR_GFX_PAGEY1 + j));
2006 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2007 DXSIZE - i, DOOR_GFX_PAGEY1 + j, i, 77 - j, DX, DY);
2008 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2009 DXSIZE-i, DOOR_GFX_PAGEY1 + 140, i, 63, DX, DY + 140 - j);
2011 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2012 DXSIZE - i, DOOR_GFX_PAGEY1 + 77, i, 63,
2014 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2015 DXSIZE - i, DOOR_GFX_PAGEY1 + 203, i, 77,
2017 XSetClipOrigin(display, clip_gc[PIX_DOOR],
2018 DX - i, (DY + j) - DOOR_GFX_PAGEY1);
2019 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2020 DXSIZE, DOOR_GFX_PAGEY1 + 77, i, 63,
2021 DX + DXSIZE - i, DY + 77 + j);
2022 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2023 DXSIZE, DOOR_GFX_PAGEY1 + 203, i, 77 - j,
2024 DX + DXSIZE - i, DY + 203 + j);
2026 redraw_mask |= REDRAW_DOOR_1;
2029 if (door_state & DOOR_ACTION_2)
2031 int i = (door_state & DOOR_OPEN_2 ? VXSIZE - x : x);
2032 int j = (VXSIZE - i) / 3;
2034 XCopyArea(display, pix[PIX_DB_DOOR], drawto, gc,
2035 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2 + i/2,
2036 VXSIZE, VYSIZE - i/2, VX, VY);
2038 XFillRectangle(display, drawto, gc, VX, VY + VYSIZE-i/2, VXSIZE, i/2);
2040 XSetClipOrigin(display, clip_gc[PIX_DOOR],
2041 VX - i, (VY + j) - DOOR_GFX_PAGEY2);
2042 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2043 VXSIZE, DOOR_GFX_PAGEY2, i, VYSIZE / 2, VX + VXSIZE-i, VY+j);
2044 XSetClipOrigin(display, clip_gc[PIX_DOOR],
2045 VX - VXSIZE + i, VY - (DOOR_GFX_PAGEY2 + j));
2046 XCopyArea(display, pix[PIX_DOOR], drawto,clip_gc[PIX_DOOR],
2047 VXSIZE - i, DOOR_GFX_PAGEY2 + j, i, VYSIZE / 2 - j, VX, VY);
2049 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2050 VXSIZE - i, DOOR_GFX_PAGEY2 + VYSIZE / 2, i, VYSIZE / 2,
2051 VX, VY + VYSIZE / 2 - j);
2052 XSetClipOrigin(display, clip_gc[PIX_DOOR],
2053 VX - i, (VY + j) - DOOR_GFX_PAGEY2);
2054 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2055 VXSIZE, DOOR_GFX_PAGEY2 + VYSIZE / 2, i, VYSIZE / 2 - j,
2056 VX + VXSIZE - i, VY + VYSIZE / 2 + j);
2058 redraw_mask |= REDRAW_DOOR_2;
2063 if (game_status == MAINMENU)
2068 if (setup.quick_doors)
2069 StopSound(SND_OEFFNEN);
2071 if (door_state & DOOR_ACTION_1)
2072 door1 = door_state & DOOR_ACTION_1;
2073 if (door_state & DOOR_ACTION_2)
2074 door2 = door_state & DOOR_ACTION_2;
2076 return (door1 | door2);
2079 void DrawSpecialEditorDoor()
2081 /* draw bigger toolbox window */
2082 XCopyArea(display, pix[PIX_DOOR], drawto, gc,
2083 DOOR_GFX_PAGEX7, 0, 108, 56, EX - 4, EY - 12);
2085 redraw_mask |= REDRAW_ALL;
2088 void UndrawSpecialEditorDoor()
2090 /* draw normal tape recorder window */
2091 XCopyArea(display, pix[PIX_BACK], drawto, gc,
2092 562, 344, 108, 56, EX - 4, EY - 12);
2094 redraw_mask |= REDRAW_ALL;
2097 int ReadPixel(Drawable d, int x, int y)
2099 XImage *pixel_image;
2100 unsigned long pixel_value;
2102 pixel_image = XGetImage(display, d, x, y, 1, 1, AllPlanes, ZPixmap);
2103 pixel_value = XGetPixel(pixel_image, 0, 0);
2105 XDestroyImage(pixel_image);
2110 /* ---------- new tool button stuff ---------------------------------------- */
2112 /* graphic position values for tool buttons */
2113 #define TOOL_BUTTON_YES_XPOS 2
2114 #define TOOL_BUTTON_YES_YPOS 250
2115 #define TOOL_BUTTON_YES_GFX_YPOS 0
2116 #define TOOL_BUTTON_YES_XSIZE 46
2117 #define TOOL_BUTTON_YES_YSIZE 28
2118 #define TOOL_BUTTON_NO_XPOS 52
2119 #define TOOL_BUTTON_NO_YPOS TOOL_BUTTON_YES_YPOS
2120 #define TOOL_BUTTON_NO_GFX_YPOS TOOL_BUTTON_YES_GFX_YPOS
2121 #define TOOL_BUTTON_NO_XSIZE TOOL_BUTTON_YES_XSIZE
2122 #define TOOL_BUTTON_NO_YSIZE TOOL_BUTTON_YES_YSIZE
2123 #define TOOL_BUTTON_CONFIRM_XPOS TOOL_BUTTON_YES_XPOS
2124 #define TOOL_BUTTON_CONFIRM_YPOS TOOL_BUTTON_YES_YPOS
2125 #define TOOL_BUTTON_CONFIRM_GFX_YPOS 30
2126 #define TOOL_BUTTON_CONFIRM_XSIZE 96
2127 #define TOOL_BUTTON_CONFIRM_YSIZE TOOL_BUTTON_YES_YSIZE
2128 #define TOOL_BUTTON_PLAYER_XSIZE 30
2129 #define TOOL_BUTTON_PLAYER_YSIZE 30
2130 #define TOOL_BUTTON_PLAYER_GFX_XPOS 5
2131 #define TOOL_BUTTON_PLAYER_GFX_YPOS 185
2132 #define TOOL_BUTTON_PLAYER_XPOS (5 + TOOL_BUTTON_PLAYER_XSIZE / 2)
2133 #define TOOL_BUTTON_PLAYER_YPOS (215 - TOOL_BUTTON_PLAYER_YSIZE / 2)
2134 #define TOOL_BUTTON_PLAYER1_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2135 + 0 * TOOL_BUTTON_PLAYER_XSIZE)
2136 #define TOOL_BUTTON_PLAYER2_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2137 + 1 * TOOL_BUTTON_PLAYER_XSIZE)
2138 #define TOOL_BUTTON_PLAYER3_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2139 + 0 * TOOL_BUTTON_PLAYER_XSIZE)
2140 #define TOOL_BUTTON_PLAYER4_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2141 + 1 * TOOL_BUTTON_PLAYER_XSIZE)
2142 #define TOOL_BUTTON_PLAYER1_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2143 + 0 * TOOL_BUTTON_PLAYER_YSIZE)
2144 #define TOOL_BUTTON_PLAYER2_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2145 + 0 * TOOL_BUTTON_PLAYER_YSIZE)
2146 #define TOOL_BUTTON_PLAYER3_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2147 + 1 * TOOL_BUTTON_PLAYER_YSIZE)
2148 #define TOOL_BUTTON_PLAYER4_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2149 + 1 * TOOL_BUTTON_PLAYER_YSIZE)
2158 } toolbutton_info[NUM_TOOL_BUTTONS] =
2161 TOOL_BUTTON_YES_XPOS, TOOL_BUTTON_YES_GFX_YPOS,
2162 TOOL_BUTTON_YES_XPOS, TOOL_BUTTON_YES_YPOS,
2163 TOOL_BUTTON_YES_XSIZE, TOOL_BUTTON_YES_YSIZE,
2168 TOOL_BUTTON_NO_XPOS, TOOL_BUTTON_NO_GFX_YPOS,
2169 TOOL_BUTTON_NO_XPOS, TOOL_BUTTON_NO_YPOS,
2170 TOOL_BUTTON_NO_XSIZE, TOOL_BUTTON_NO_YSIZE,
2175 TOOL_BUTTON_CONFIRM_XPOS, TOOL_BUTTON_CONFIRM_GFX_YPOS,
2176 TOOL_BUTTON_CONFIRM_XPOS, TOOL_BUTTON_CONFIRM_YPOS,
2177 TOOL_BUTTON_CONFIRM_XSIZE, TOOL_BUTTON_CONFIRM_YSIZE,
2178 TOOL_CTRL_ID_CONFIRM,
2182 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2183 TOOL_BUTTON_PLAYER1_XPOS, TOOL_BUTTON_PLAYER1_YPOS,
2184 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2185 TOOL_CTRL_ID_PLAYER_1,
2189 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2190 TOOL_BUTTON_PLAYER2_XPOS, TOOL_BUTTON_PLAYER2_YPOS,
2191 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2192 TOOL_CTRL_ID_PLAYER_2,
2196 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2197 TOOL_BUTTON_PLAYER3_XPOS, TOOL_BUTTON_PLAYER3_YPOS,
2198 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2199 TOOL_CTRL_ID_PLAYER_3,
2203 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2204 TOOL_BUTTON_PLAYER4_XPOS, TOOL_BUTTON_PLAYER4_YPOS,
2205 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2206 TOOL_CTRL_ID_PLAYER_4,
2211 static void DoNotDisplayInfoText(void *ptr)
2216 void CreateToolButtons()
2220 for (i=0; i<NUM_TOOL_BUTTONS; i++)
2222 Pixmap gd_pixmap = pix[PIX_DOOR];
2223 Pixmap deco_pixmap = None;
2224 int deco_x = 0, deco_y = 0, deco_xpos = 0, deco_ypos = 0;
2225 struct GadgetInfo *gi;
2226 unsigned long event_mask;
2227 int gd_xoffset, gd_yoffset;
2228 int gd_x1, gd_x2, gd_y;
2231 event_mask = GD_EVENT_RELEASED;
2233 gd_xoffset = toolbutton_info[i].xpos;
2234 gd_yoffset = toolbutton_info[i].ypos;
2235 gd_x1 = DOOR_GFX_PAGEX4 + gd_xoffset;
2236 gd_x2 = DOOR_GFX_PAGEX3 + gd_xoffset;
2237 gd_y = DOOR_GFX_PAGEY1 + gd_yoffset;
2239 if (id >= TOOL_CTRL_ID_PLAYER_1 && id <= TOOL_CTRL_ID_PLAYER_4)
2241 getMiniGraphicSource(GFX_SPIELER1 + id - TOOL_CTRL_ID_PLAYER_1,
2242 &deco_pixmap, &deco_x, &deco_y);
2243 deco_xpos = (toolbutton_info[i].width - MINI_TILEX) / 2;
2244 deco_ypos = (toolbutton_info[i].height - MINI_TILEY) / 2;
2247 gi = CreateGadget(GDI_CUSTOM_ID, id,
2248 GDI_INFO_TEXT, toolbutton_info[i].infotext,
2249 GDI_X, DX + toolbutton_info[i].x,
2250 GDI_Y, DY + toolbutton_info[i].y,
2251 GDI_WIDTH, toolbutton_info[i].width,
2252 GDI_HEIGHT, toolbutton_info[i].height,
2253 GDI_TYPE, GD_TYPE_NORMAL_BUTTON,
2254 GDI_STATE, GD_BUTTON_UNPRESSED,
2255 GDI_DESIGN_UNPRESSED, gd_pixmap, gd_x1, gd_y,
2256 GDI_DESIGN_PRESSED, gd_pixmap, gd_x2, gd_y,
2257 GDI_DECORATION_DESIGN, deco_pixmap, deco_x, deco_y,
2258 GDI_DECORATION_POSITION, deco_xpos, deco_ypos,
2259 GDI_DECORATION_SIZE, MINI_TILEX, MINI_TILEY,
2260 GDI_DECORATION_SHIFTING, 1, 1,
2261 GDI_EVENT_MASK, event_mask,
2262 GDI_CALLBACK_ACTION, HandleToolButtons,
2263 GDI_CALLBACK_INFO, DoNotDisplayInfoText,
2267 Error(ERR_EXIT, "cannot create gadget");
2269 tool_gadget[id] = gi;
2273 static void UnmapToolButtons()
2277 for (i=0; i<NUM_TOOL_BUTTONS; i++)
2278 UnmapGadget(tool_gadget[i]);
2281 static void HandleToolButtons(struct GadgetInfo *gi)
2283 request_gadget_id = gi->custom_id;
2286 int el2gfx(int element)
2290 case EL_LEERRAUM: return -1;
2291 case EL_ERDREICH: return GFX_ERDREICH;
2292 case EL_MAUERWERK: return GFX_MAUERWERK;
2293 case EL_FELSBODEN: return GFX_FELSBODEN;
2294 case EL_FELSBROCKEN: return GFX_FELSBROCKEN;
2295 case EL_SCHLUESSEL: return GFX_SCHLUESSEL;
2296 case EL_EDELSTEIN: return GFX_EDELSTEIN;
2297 case EL_AUSGANG_ZU: return GFX_AUSGANG_ZU;
2298 case EL_AUSGANG_ACT: return GFX_AUSGANG_ACT;
2299 case EL_AUSGANG_AUF: return GFX_AUSGANG_AUF;
2300 case EL_SPIELFIGUR: return GFX_SPIELFIGUR;
2301 case EL_SPIELER1: return GFX_SPIELER1;
2302 case EL_SPIELER2: return GFX_SPIELER2;
2303 case EL_SPIELER3: return GFX_SPIELER3;
2304 case EL_SPIELER4: return GFX_SPIELER4;
2305 case EL_KAEFER: return GFX_KAEFER;
2306 case EL_KAEFER_R: return GFX_KAEFER_R;
2307 case EL_KAEFER_O: return GFX_KAEFER_O;
2308 case EL_KAEFER_L: return GFX_KAEFER_L;
2309 case EL_KAEFER_U: return GFX_KAEFER_U;
2310 case EL_FLIEGER: return GFX_FLIEGER;
2311 case EL_FLIEGER_R: return GFX_FLIEGER_R;
2312 case EL_FLIEGER_O: return GFX_FLIEGER_O;
2313 case EL_FLIEGER_L: return GFX_FLIEGER_L;
2314 case EL_FLIEGER_U: return GFX_FLIEGER_U;
2315 case EL_BUTTERFLY: return GFX_BUTTERFLY;
2316 case EL_BUTTERFLY_R: return GFX_BUTTERFLY_R;
2317 case EL_BUTTERFLY_O: return GFX_BUTTERFLY_O;
2318 case EL_BUTTERFLY_L: return GFX_BUTTERFLY_L;
2319 case EL_BUTTERFLY_U: return GFX_BUTTERFLY_U;
2320 case EL_FIREFLY: return GFX_FIREFLY;
2321 case EL_FIREFLY_R: return GFX_FIREFLY_R;
2322 case EL_FIREFLY_O: return GFX_FIREFLY_O;
2323 case EL_FIREFLY_L: return GFX_FIREFLY_L;
2324 case EL_FIREFLY_U: return GFX_FIREFLY_U;
2325 case EL_MAMPFER: return GFX_MAMPFER;
2326 case EL_ROBOT: return GFX_ROBOT;
2327 case EL_BETON: return GFX_BETON;
2328 case EL_DIAMANT: return GFX_DIAMANT;
2329 case EL_MORAST_LEER: return GFX_MORAST_LEER;
2330 case EL_MORAST_VOLL: return GFX_MORAST_VOLL;
2331 case EL_TROPFEN: return GFX_TROPFEN;
2332 case EL_BOMBE: return GFX_BOMBE;
2333 case EL_SIEB_INAKTIV: return GFX_SIEB_INAKTIV;
2334 case EL_SIEB_LEER: return GFX_SIEB_LEER;
2335 case EL_SIEB_VOLL: return GFX_SIEB_VOLL;
2336 case EL_SIEB_TOT: return GFX_SIEB_TOT;
2337 case EL_SALZSAEURE: return GFX_SALZSAEURE;
2338 case EL_AMOEBE_TOT: return GFX_AMOEBE_TOT;
2339 case EL_AMOEBE_NASS: return GFX_AMOEBE_NASS;
2340 case EL_AMOEBE_NORM: return GFX_AMOEBE_NORM;
2341 case EL_AMOEBE_VOLL: return GFX_AMOEBE_VOLL;
2342 case EL_AMOEBE_BD: return GFX_AMOEBE_BD;
2343 case EL_AMOEBA2DIAM: return GFX_AMOEBA2DIAM;
2344 case EL_KOKOSNUSS: return GFX_KOKOSNUSS;
2345 case EL_LIFE: return GFX_LIFE;
2346 case EL_LIFE_ASYNC: return GFX_LIFE_ASYNC;
2347 case EL_DYNAMIT: return GFX_DYNAMIT;
2348 case EL_BADEWANNE: return GFX_BADEWANNE;
2349 case EL_BADEWANNE1: return GFX_BADEWANNE1;
2350 case EL_BADEWANNE2: return GFX_BADEWANNE2;
2351 case EL_BADEWANNE3: return GFX_BADEWANNE3;
2352 case EL_BADEWANNE4: return GFX_BADEWANNE4;
2353 case EL_BADEWANNE5: return GFX_BADEWANNE5;
2354 case EL_ABLENK_AUS: return GFX_ABLENK_AUS;
2355 case EL_ABLENK_EIN: return GFX_ABLENK_EIN;
2356 case EL_SCHLUESSEL1: return GFX_SCHLUESSEL1;
2357 case EL_SCHLUESSEL2: return GFX_SCHLUESSEL2;
2358 case EL_SCHLUESSEL3: return GFX_SCHLUESSEL3;
2359 case EL_SCHLUESSEL4: return GFX_SCHLUESSEL4;
2360 case EL_PFORTE1: return GFX_PFORTE1;
2361 case EL_PFORTE2: return GFX_PFORTE2;
2362 case EL_PFORTE3: return GFX_PFORTE3;
2363 case EL_PFORTE4: return GFX_PFORTE4;
2364 case EL_PFORTE1X: return GFX_PFORTE1X;
2365 case EL_PFORTE2X: return GFX_PFORTE2X;
2366 case EL_PFORTE3X: return GFX_PFORTE3X;
2367 case EL_PFORTE4X: return GFX_PFORTE4X;
2368 case EL_DYNAMIT_AUS: return GFX_DYNAMIT_AUS;
2369 case EL_PACMAN: return GFX_PACMAN;
2370 case EL_PACMAN_R: return GFX_PACMAN_R;
2371 case EL_PACMAN_O: return GFX_PACMAN_O;
2372 case EL_PACMAN_L: return GFX_PACMAN_L;
2373 case EL_PACMAN_U: return GFX_PACMAN_U;
2374 case EL_UNSICHTBAR: return GFX_UNSICHTBAR;
2375 case EL_ERZ_EDEL: return GFX_ERZ_EDEL;
2376 case EL_ERZ_DIAM: return GFX_ERZ_DIAM;
2377 case EL_BIRNE_AUS: return GFX_BIRNE_AUS;
2378 case EL_BIRNE_EIN: return GFX_BIRNE_EIN;
2379 case EL_ZEIT_VOLL: return GFX_ZEIT_VOLL;
2380 case EL_ZEIT_LEER: return GFX_ZEIT_LEER;
2381 case EL_MAUER_LEBT: return GFX_MAUER_LEBT;
2382 case EL_MAUER_X: return GFX_MAUER_X;
2383 case EL_MAUER_Y: return GFX_MAUER_Y;
2384 case EL_MAUER_XY: return GFX_MAUER_XY;
2385 case EL_EDELSTEIN_BD: return GFX_EDELSTEIN_BD;
2386 case EL_EDELSTEIN_GELB: return GFX_EDELSTEIN_GELB;
2387 case EL_EDELSTEIN_ROT: return GFX_EDELSTEIN_ROT;
2388 case EL_EDELSTEIN_LILA: return GFX_EDELSTEIN_LILA;
2389 case EL_ERZ_EDEL_BD: return GFX_ERZ_EDEL_BD;
2390 case EL_ERZ_EDEL_GELB: return GFX_ERZ_EDEL_GELB;
2391 case EL_ERZ_EDEL_ROT: return GFX_ERZ_EDEL_ROT;
2392 case EL_ERZ_EDEL_LILA: return GFX_ERZ_EDEL_LILA;
2393 case EL_MAMPFER2: return GFX_MAMPFER2;
2394 case EL_SIEB2_INAKTIV: return GFX_SIEB2_INAKTIV;
2395 case EL_SIEB2_LEER: return GFX_SIEB2_LEER;
2396 case EL_SIEB2_VOLL: return GFX_SIEB2_VOLL;
2397 case EL_SIEB2_TOT: return GFX_SIEB2_TOT;
2398 case EL_DYNABOMB: return GFX_DYNABOMB;
2399 case EL_DYNABOMB_NR: return GFX_DYNABOMB_NR;
2400 case EL_DYNABOMB_SZ: return GFX_DYNABOMB_SZ;
2401 case EL_DYNABOMB_XL: return GFX_DYNABOMB_XL;
2402 case EL_SOKOBAN_OBJEKT: return GFX_SOKOBAN_OBJEKT;
2403 case EL_SOKOBAN_FELD_LEER: return GFX_SOKOBAN_FELD_LEER;
2404 case EL_SOKOBAN_FELD_VOLL: return GFX_SOKOBAN_FELD_VOLL;
2405 case EL_MAULWURF: return GFX_MAULWURF;
2406 case EL_PINGUIN: return GFX_PINGUIN;
2407 case EL_SCHWEIN: return GFX_SCHWEIN;
2408 case EL_DRACHE: return GFX_DRACHE;
2409 case EL_SONDE: return GFX_SONDE;
2410 case EL_PFEIL_L: return GFX_PFEIL_L;
2411 case EL_PFEIL_R: return GFX_PFEIL_R;
2412 case EL_PFEIL_O: return GFX_PFEIL_O;
2413 case EL_PFEIL_U: return GFX_PFEIL_U;
2414 case EL_SPEED_PILL: return GFX_SPEED_PILL;
2415 case EL_SP_TERMINAL_ACTIVE: return GFX_SP_TERMINAL;
2416 case EL_SP_BUG_ACTIVE: return GFX_SP_BUG_ACTIVE;
2417 case EL_SP_ZONK: return GFX_SP_ZONK;
2418 /* ^^^^^^^^^^ non-standard position in supaplex graphic set! */
2419 case EL_INVISIBLE_STEEL: return GFX_INVISIBLE_STEEL;
2420 case EL_BLACK_ORB: return GFX_BLACK_ORB;
2421 case EL_EM_GATE_1: return GFX_EM_GATE_1;
2422 case EL_EM_GATE_2: return GFX_EM_GATE_2;
2423 case EL_EM_GATE_3: return GFX_EM_GATE_3;
2424 case EL_EM_GATE_4: return GFX_EM_GATE_4;
2425 case EL_EM_GATE_1X: return GFX_EM_GATE_1X;
2426 case EL_EM_GATE_2X: return GFX_EM_GATE_2X;
2427 case EL_EM_GATE_3X: return GFX_EM_GATE_3X;
2428 case EL_EM_GATE_4X: return GFX_EM_GATE_4X;
2429 case EL_EM_KEY_1_FILE: return GFX_EM_KEY_1;
2430 case EL_EM_KEY_2_FILE: return GFX_EM_KEY_2;
2431 case EL_EM_KEY_3_FILE: return GFX_EM_KEY_3;
2432 case EL_EM_KEY_4_FILE: return GFX_EM_KEY_4;
2433 case EL_EM_KEY_1: return GFX_EM_KEY_1;
2434 case EL_EM_KEY_2: return GFX_EM_KEY_2;
2435 case EL_EM_KEY_3: return GFX_EM_KEY_3;
2436 case EL_EM_KEY_4: return GFX_EM_KEY_4;
2440 if (IS_CHAR(element))
2441 return GFX_CHAR_START + (element - EL_CHAR_START);
2442 else if (element >= EL_SP_START && element <= EL_SP_END)
2444 int nr_element = element - EL_SP_START;
2445 int gfx_per_line = 8;
2447 (nr_element / gfx_per_line) * MORE_PER_LINE +
2448 (nr_element % gfx_per_line);
2450 return GFX_START_ROCKSMORE + nr_graphic;