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 ***********************************************************/
22 /* positions in the level editor */
23 #define ED_WIN_MB_LEFT_XPOS 7
24 #define ED_WIN_MB_LEFT_YPOS 6
25 #define ED_WIN_LEVELNR_XPOS 77
26 #define ED_WIN_LEVELNR_YPOS 7
27 #define ED_WIN_MB_MIDDLE_XPOS 7
28 #define ED_WIN_MB_MIDDLE_YPOS 258
29 #define ED_WIN_MB_RIGHT_XPOS 77
30 #define ED_WIN_MB_RIGHT_YPOS 258
32 /* other constants for the editor */
33 #define ED_SCROLL_NO 0
34 #define ED_SCROLL_LEFT 1
35 #define ED_SCROLL_RIGHT 2
36 #define ED_SCROLL_UP 4
37 #define ED_SCROLL_DOWN 8
39 /* delay value to avoid too fast scrolling etc. */
40 #define CHOICE_DELAY_VALUE 100
42 /* how many steps can be cancelled */
43 #define NUM_UNDO_STEPS (10 + 1)
45 /* values for random placement */
46 #define RANDOM_USE_PERCENTAGE 0
47 #define RANDOM_USE_NUM_OBJECTS 1
49 /* values for the control window */
50 #define ED_CTRL_BUTTONS_GFX_YPOS 236
51 #define ED_CTRL1_BUTTONS_HORIZ 4
52 #define ED_CTRL1_BUTTONS_VERT 4
53 #define ED_CTRL1_BUTTON_XSIZE 22
54 #define ED_CTRL1_BUTTON_YSIZE 22
55 #define ED_CTRL1_BUTTONS_XPOS 6
56 #define ED_CTRL1_BUTTONS_YPOS 6
57 #define ED_CTRL2_BUTTONS_HORIZ 3
58 #define ED_CTRL2_BUTTONS_VERT 2
59 #define ED_CTRL2_BUTTON_XSIZE 30
60 #define ED_CTRL2_BUTTON_YSIZE 20
61 #define ED_CTRL2_BUTTONS_XPOS 5
62 #define ED_CTRL2_BUTTONS_YPOS 100
63 #define ED_NUM_CTRL1_BUTTONS (ED_CTRL1_BUTTONS_HORIZ * ED_CTRL1_BUTTONS_VERT)
64 #define ED_NUM_CTRL2_BUTTONS (ED_CTRL2_BUTTONS_HORIZ * ED_CTRL2_BUTTONS_VERT)
65 #define ED_NUM_CTRL_BUTTONS (ED_NUM_CTRL1_BUTTONS + ED_NUM_CTRL2_BUTTONS)
67 /* control button names */
68 #define ED_CTRL_ID_SINGLE_ITEMS 0
69 #define ED_CTRL_ID_CONNECTED_ITEMS 1
70 #define ED_CTRL_ID_LINE 2
71 #define ED_CTRL_ID_TEXT 3
72 #define ED_CTRL_ID_RECTANGLE 4
73 #define ED_CTRL_ID_FILLED_BOX 5
74 #define ED_CTRL_ID_WRAP_UP 6
75 #define ED_CTRL_ID_ITEM_PROPERTIES 7
76 #define ED_CTRL_ID_FLOOD_FILL 8
77 #define ED_CTRL_ID_WRAP_LEFT 9
78 #define ED_CTRL_ID_WRAP_RIGHT 11
79 #define ED_CTRL_ID_RANDOM_PLACEMENT 12
80 #define ED_CTRL_ID_BRUSH 13
81 #define ED_CTRL_ID_WRAP_DOWN 14
82 #define ED_CTRL_ID_UNDO 16
83 #define ED_CTRL_ID_INFO 17
84 #define ED_CTRL_ID_SAVE 18
85 #define ED_CTRL_ID_CLEAR 19
86 #define ED_CTRL_ID_TEST 20
87 #define ED_CTRL_ID_EXIT 21
89 /* forward declaration for internal use */
90 void HandleDrawingFunctions(int, int, int);
91 void HandlePressedControlButtons();
92 void HandleControlButtons(struct GadgetInfo *);
94 static struct GadgetInfo *control_button_gadget[ED_NUM_CTRL_BUTTONS];
95 static boolean control_button_gadgets_created = FALSE;
96 static boolean control_button_gadgets_mapped = FALSE;
98 static int drawing_function = ED_CTRL_ID_SINGLE_ITEMS;
100 static short OrigBackup[MAX_LEV_FIELDX][MAX_LEV_FIELDY];
101 static short UndoBuffer[NUM_UNDO_STEPS][MAX_LEV_FIELDX][MAX_LEV_FIELDY];
102 static int undo_buffer_position = 0;
103 static int undo_buffer_steps = 0;
105 static int random_placement_percentage = 10;
106 static int random_placement_num_objects = 10;
108 static int random_placement_method = RANDOM_USE_PERCENTAGE;
110 static int random_placement_method = RANDOM_USE_NUM_OBJECTS;
113 static int level_xpos,level_ypos;
114 static boolean edit_mode;
115 static boolean name_typing;
116 static int new_element1 = EL_MAUERWERK;
117 static int new_element2 = EL_LEERRAUM;
118 static int new_element3 = EL_ERDREICH;
121 int editor_element[] =
123 EL_CHAR_A + ('B' - 'A'),
124 EL_CHAR_A + ('O' - 'A'),
125 EL_CHAR_A + ('U' - 'A'),
126 EL_CHAR_A + ('L' - 'A'),
129 EL_CHAR_A + ('D' - 'A'),
130 EL_CHAR_A + ('E' - 'A'),
131 EL_CHAR_A + ('R' - 'A'),
133 EL_CHAR_A + ('D' - 'A'),
134 EL_CHAR_A + ('A' - 'A'),
135 EL_CHAR_A + ('S' - 'A'),
136 EL_CHAR_A + ('H' - 'A'),
163 EL_CHAR_A + ('E' - 'A'),
164 EL_CHAR_A + ('M' - 'A'),
165 EL_CHAR_A + ('E' - 'A'),
168 EL_CHAR_A + ('R' - 'A'),
169 EL_CHAR_A + ('A' - 'A'),
170 EL_CHAR_A + ('L' - 'A'),
171 EL_CHAR_A + ('D' - 'A'),
173 EL_CHAR_A + ('M' - 'A'),
174 EL_CHAR_A + ('I' - 'A'),
175 EL_CHAR_A + ('N' - 'A'),
176 EL_CHAR_A + ('E' - 'A'),
253 EL_CHAR_A + ('M' - 'A'),
254 EL_CHAR_A + ('O' - 'A'),
255 EL_CHAR_A + ('R' - 'A'),
256 EL_CHAR_A + ('E' - 'A'),
303 EL_CHAR_A + ('S' - 'A'),
304 EL_CHAR_A + ('O' - 'A'),
305 EL_CHAR_A + ('K' - 'A'),
306 EL_CHAR_A + ('O' - 'A'),
309 EL_CHAR_A + ('B' - 'A'),
310 EL_CHAR_A + ('A' - 'A'),
311 EL_CHAR_A + ('N' - 'A'),
314 EL_SOKOBAN_FELD_LEER,
315 EL_SOKOBAN_FELD_VOLL,
319 EL_CHAR_A + ('D' - 'A'),
320 EL_CHAR_A + ('Y' - 'A'),
321 EL_CHAR_A + ('N' - 'A'),
322 EL_CHAR_A + ('A' - 'A'),
324 EL_CHAR_A + ('B' - 'A'),
325 EL_CHAR_A + ('L' - 'A'),
326 EL_CHAR_A + ('A' - 'A'),
327 EL_CHAR_A + ('S' - 'A'),
330 EL_CHAR_A + ('T' - 'A'),
331 EL_CHAR_A + ('E' - 'A'),
332 EL_CHAR_A + ('R' - 'A'),
414 int elements_in_list = sizeof(editor_element)/sizeof(int);
416 void ScrollMiniLevel(int from_x, int from_y, int scroll)
419 int dx = (scroll==ED_SCROLL_LEFT ? -1 : scroll==ED_SCROLL_RIGHT ? 1 : 0);
420 int dy = (scroll==ED_SCROLL_UP ? -1 : scroll==ED_SCROLL_DOWN ? 1 : 0);
422 XCopyArea(display,drawto,drawto,gc,
423 SX+MINI_TILEX*(dx==-1),SY+MINI_TILEY*(dy==-1),
424 SXSIZE-MINI_TILEX*ABS(dx),SYSIZE-MINI_TILEY*ABS(dy),
425 SX+MINI_TILEX*(dx==+1),SY+MINI_TILEY*(dy==+1));
428 x = (dx==1 ? 0 : 2*SCR_FIELDX-1);
429 for(y=0;y<2*SCR_FIELDY;y++)
430 DrawMiniElementOrWall(x,y,from_x,from_y);
434 y = (dy==1 ? 0 : 2*SCR_FIELDY-1);
435 for(x=0;x<2*SCR_FIELDX;x++)
436 DrawMiniElementOrWall(x,y,from_x,from_y);
439 redraw_mask |= REDRAW_FIELD;
443 void CreateLevelEditorControlButtons()
447 if (control_button_gadgets_created)
450 for (i=0; i<ED_NUM_CTRL_BUTTONS; i++)
452 Pixmap gd_pixmap = pix[PIX_DOOR];
453 struct GadgetInfo *gi;
454 int gd_xoffset, gd_yoffset;
455 int gd_x1, gd_x2, gd_y;
457 unsigned long event_mask;
459 if (i < ED_NUM_CTRL1_BUTTONS)
461 int x = i % ED_CTRL1_BUTTONS_HORIZ;
462 int y = i / ED_CTRL1_BUTTONS_HORIZ;
464 gd_xoffset = ED_CTRL1_BUTTONS_XPOS + x * ED_CTRL1_BUTTON_XSIZE;
465 gd_yoffset = ED_CTRL1_BUTTONS_YPOS + y * ED_CTRL1_BUTTON_YSIZE;
466 width = ED_CTRL1_BUTTON_XSIZE;
467 height = ED_CTRL1_BUTTON_YSIZE;
471 int x = (i - ED_NUM_CTRL1_BUTTONS) % ED_CTRL2_BUTTONS_HORIZ;
472 int y = (i - ED_NUM_CTRL1_BUTTONS) / ED_CTRL2_BUTTONS_HORIZ;
474 gd_xoffset = ED_CTRL2_BUTTONS_XPOS + x * ED_CTRL2_BUTTON_XSIZE;
475 gd_yoffset = ED_CTRL2_BUTTONS_YPOS + y * ED_CTRL2_BUTTON_YSIZE;
476 width = ED_CTRL2_BUTTON_XSIZE;
477 height = ED_CTRL2_BUTTON_YSIZE;
480 gd_x1 = DOOR_GFX_PAGEX8 + gd_xoffset;
481 gd_x2 = DOOR_GFX_PAGEX7 + gd_xoffset;
482 gd_y = DOOR_GFX_PAGEY1 + ED_CTRL_BUTTONS_GFX_YPOS + gd_yoffset;
484 if (i == ED_CTRL_ID_WRAP_LEFT ||
485 i == ED_CTRL_ID_WRAP_RIGHT ||
486 i == ED_CTRL_ID_WRAP_UP ||
487 i == ED_CTRL_ID_WRAP_DOWN)
488 event_mask = GD_EVENT_PRESSED;
490 event_mask = GD_EVENT_RELEASED;
492 gi = CreateGadget(GDI_X, EX + gd_xoffset,
493 GDI_Y, EY + gd_yoffset,
496 GDI_TYPE, GD_TYPE_NORMAL_BUTTON,
497 GDI_STATE, GD_BUTTON_UNPRESSED,
498 GDI_DESIGN_UNPRESSED, gd_pixmap, gd_x1, gd_y,
499 GDI_DESIGN_PRESSED, gd_pixmap, gd_x2, gd_y,
500 GDI_EVENT_MASK, event_mask,
501 GDI_CALLBACK, HandleControlButtons,
505 Error(ERR_EXIT, "cannot create gadget");
507 control_button_gadget[i] = gi;
510 control_button_gadgets_created = TRUE;
513 void MapLevelEditorControlButtons()
517 if (!control_button_gadgets_created)
518 CreateLevelEditorControlButtons();
520 for (i=0; i<ED_NUM_CTRL_BUTTONS; i++)
521 MapGadget(control_button_gadget[i]);
523 control_button_gadgets_mapped = TRUE;
526 void UnmapLevelEditorControlButtons()
530 if (!control_button_gadgets_created || !control_button_gadgets_mapped)
533 for (i=0; i<ED_NUM_CTRL_BUTTONS; i++)
534 UnmapGadget(control_button_gadget[i]);
536 control_button_gadgets_mapped = FALSE;
541 int i, x, y, graphic;
549 CloseDoor(DOOR_CLOSE_ALL);
551 if (level_editor_test_game)
553 for(x=0; x<lev_fieldx; x++)
554 for(y=0; y<lev_fieldy; y++)
555 Feld[x][y] = Ur[x][y];
557 for(x=0; x<lev_fieldx; x++)
558 for(y=0; y<lev_fieldy; y++)
559 Ur[x][y] = OrigBackup[x][y];
561 level_editor_test_game = FALSE;
565 undo_buffer_position = 0;
566 undo_buffer_steps = 0;
567 for(x=0; x<lev_fieldx; x++)
568 for(y=0; y<lev_fieldy; y++)
569 UndoBuffer[0][x][y] = Ur[x][y];
572 DrawMiniLevel(level_xpos,level_ypos);
575 XCopyArea(display,pix[PIX_DOOR],pix[PIX_DB_DOOR],gc,
576 DOOR_GFX_PAGEX6,DOOR_GFX_PAGEY1,
578 DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY1);
579 XCopyArea(display,pix[PIX_DOOR],pix[PIX_DB_DOOR],gc,
580 DOOR_GFX_PAGEX6+ED_BUTTON_ELEM_XPOS,
581 DOOR_GFX_PAGEY1+ED_BUTTON_ELEM_YPOS,
582 4*ED_BUTTON_ELEM_XSIZE,5*ED_BUTTON_ELEM_YSIZE,
583 DOOR_GFX_PAGEX1+ED_BUTTON_ELEM_XPOS,
584 DOOR_GFX_PAGEY1+ED_BUTTON_EUP_Y2POS);
586 for(i=0;i<MAX_ELEM_X*MAX_ELEM_Y;i++)
588 if (i < elements_in_list)
589 graphic = el2gfx(editor_element[i]);
591 graphic = GFX_LEERRAUM;
593 DrawMiniGraphicExt(pix[PIX_DB_DOOR],gc,
594 DOOR_GFX_PAGEX1+ED_BUTTON_ELEM_XPOS+3 +
595 (i%MAX_ELEM_X)*ED_BUTTON_ELEM_XSIZE,
596 DOOR_GFX_PAGEY1+ED_BUTTON_ELEM_YPOS+3 +
597 (i/MAX_ELEM_X)*ED_BUTTON_ELEM_YSIZE,
601 DrawMiniGraphicExt(pix[PIX_DB_DOOR],gc,
602 DOOR_GFX_PAGEX1+ED_WIN_MB_LEFT_XPOS,
603 DOOR_GFX_PAGEY1+ED_WIN_MB_LEFT_YPOS,
604 el2gfx(new_element1));
605 DrawMiniGraphicExt(pix[PIX_DB_DOOR],gc,
606 DOOR_GFX_PAGEX1+ED_WIN_MB_MIDDLE_XPOS,
607 DOOR_GFX_PAGEY1+ED_WIN_MB_MIDDLE_YPOS,
608 el2gfx(new_element2));
609 DrawMiniGraphicExt(pix[PIX_DB_DOOR],gc,
610 DOOR_GFX_PAGEX1+ED_WIN_MB_RIGHT_XPOS,
611 DOOR_GFX_PAGEY1+ED_WIN_MB_RIGHT_YPOS,
612 el2gfx(new_element3));
613 DrawTextExt(pix[PIX_DB_DOOR],gc,
614 DOOR_GFX_PAGEX2+ED_WIN_LEVELNR_XPOS,
615 DOOR_GFX_PAGEY1+ED_WIN_LEVELNR_YPOS,
616 int2str(level_nr,2),FS_SMALL,FC_SPECIAL1);
617 XCopyArea(display,pix[PIX_DB_DOOR],pix[PIX_DB_DOOR],gc,
618 DOOR_GFX_PAGEX2+ED_WIN_LEVELNR_XPOS+3,
619 DOOR_GFX_PAGEY1+ED_WIN_LEVELNR_YPOS,
621 DOOR_GFX_PAGEX1+ED_WIN_LEVELNR_XPOS,
622 DOOR_GFX_PAGEY1+ED_WIN_LEVELNR_YPOS);
623 XCopyArea(display,pix[PIX_DB_DOOR],pix[PIX_DB_DOOR],gc,
624 DOOR_GFX_PAGEX2+ED_WIN_LEVELNR_XPOS+14,
625 DOOR_GFX_PAGEY1+ED_WIN_LEVELNR_YPOS,
627 DOOR_GFX_PAGEX1+ED_WIN_LEVELNR_XPOS+9,
628 DOOR_GFX_PAGEY1+ED_WIN_LEVELNR_YPOS);
630 XCopyArea(display,pix[PIX_DOOR],pix[PIX_DB_DOOR],gc,
631 DOOR_GFX_PAGEX6,DOOR_GFX_PAGEY2,
633 DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY2);
635 /* draw bigger door */
636 XCopyArea(display, pix[PIX_DOOR], drawto, gc,
641 /* draw new control window */
642 XCopyArea(display, pix[PIX_DOOR], drawto, gc,
643 DOOR_GFX_PAGEX8, 236,
647 redraw_mask |= REDRAW_ALL;
649 OpenDoor(DOOR_OPEN_1);
651 MapLevelEditorControlButtons();
654 OpenDoor(DOOR_OPEN_1 | DOOR_OPEN_2);
658 void DrawControlWindow()
664 /* Inhalt der Mampfer */
665 DrawText(ED_COUNT_GADGET_XPOS+1,SY+6,
666 "Contents of a smashed cruncher:",FS_SMALL,FC_YELLOW);
667 for(i=0;i<4;i++) for(y=0;y<4;y++) for(x=0;x<4;x++)
669 DrawMiniElement(1+5*i+x,2+y,EL_ERDREICH);
670 XFillRectangle(display,drawto,gc,
671 SX+(1+5*i)*MINI_TILEX+MINI_TILEX/2-1,
672 SY+(2)*MINI_TILEY+MINI_TILEY/2-1,
673 3*MINI_TILEX+2,3*MINI_TILEY+2);
675 XCopyArea(display,drawto,drawto,gc,
676 SX+1*MINI_TILEX,SY+2*MINI_TILEY,
677 4*5*MINI_TILEX,5*MINI_TILEY,
678 SX+1*MINI_TILEX-MINI_TILEX/2,SY+2*MINI_TILEY-MINI_TILEY/2);
681 for(y=0;y<3;y++) for(x=0;x<3;x++)
682 DrawMiniElement(1+5*i+x,2+y,level.mampfer_inhalt[i][x][y]);
684 DrawText(SX+MINI_TILEX+(5*i+1)*MINI_TILEX+1,
685 SY+2*MINI_TILEY+(4)*MINI_TILEY-4,
686 int2str(i+1,1),FS_SMALL,FC_YELLOW);
689 /* Inhalt der Amöbe */
690 for(y=0;y<2;y++) for(x=0;x<2;x++)
692 DrawMiniElement(29+x,26+y,EL_ERDREICH);
693 XFillRectangle(display,drawto,gc,
694 SX+29*MINI_TILEX+MINI_TILEX/2-1,
695 SY+26*MINI_TILEY+MINI_TILEY/2-1,
696 MINI_TILEX+2,MINI_TILEY+2);
698 XCopyArea(display,drawto,drawto,gc,
699 SX+29*MINI_TILEX,SY+26*MINI_TILEY,
700 3*MINI_TILEX,3*MINI_TILEY,
701 SX+29*MINI_TILEX-MINI_TILEX/2,SY+26*MINI_TILEY-MINI_TILEY/2);
702 DrawMiniElement(29,26,level.amoebe_inhalt);
704 for(i=0;i<11+3+2;i++)
706 XCopyArea(display,pix[PIX_DOOR],drawto,gc,
707 DOOR_GFX_PAGEX4+ED_BUTTON_MINUS_XPOS,
708 DOOR_GFX_PAGEY1+ED_BUTTON_MINUS_YPOS,
709 DXSIZE-4,ED_BUTTON_MINUS_YSIZE,
710 ED_COUNT_GADGET_XPOS,
711 ED_COUNT_GADGET_YPOS+i*ED_COUNT_GADGET_YSIZE);
714 DrawText(ED_COUNT_VALUE_XPOS,
715 ED_COUNT_VALUE_YPOS+i*ED_COUNT_GADGET_YSIZE,
716 int2str(level.score[i],3),FS_SMALL,FC_YELLOW);
718 DrawText(ED_COUNT_VALUE_XPOS,
719 ED_COUNT_VALUE_YPOS+11*ED_COUNT_GADGET_YSIZE,
720 int2str(level.tempo_amoebe,3),FS_SMALL,FC_YELLOW);
722 DrawText(ED_COUNT_VALUE_XPOS,
723 ED_COUNT_VALUE_YPOS+12*ED_COUNT_GADGET_YSIZE,
724 int2str(level.dauer_sieb,3),FS_SMALL,FC_YELLOW);
726 DrawText(ED_COUNT_VALUE_XPOS,
727 ED_COUNT_VALUE_YPOS+13*ED_COUNT_GADGET_YSIZE,
728 int2str(level.dauer_ablenk,3),FS_SMALL,FC_YELLOW);
730 DrawText(ED_COUNT_VALUE_XPOS,
731 ED_COUNT_VALUE_YPOS+14*ED_COUNT_GADGET_YSIZE,
732 int2str(level.edelsteine,3),FS_SMALL,FC_YELLOW);
734 DrawText(ED_COUNT_VALUE_XPOS,
735 ED_COUNT_VALUE_YPOS+15*ED_COUNT_GADGET_YSIZE,
736 int2str(level.time,3),FS_SMALL,FC_YELLOW);
739 DrawText(ED_COUNT_TEXT_XPOS,ED_COUNT_TEXT_YPOS+0*ED_COUNT_TEXT_YSIZE,
740 "Score for Emerald",FS_SMALL,FC_YELLOW);
741 DrawText(ED_COUNT_TEXT_XPOS,ED_COUNT_TEXT_YPOS+1*ED_COUNT_TEXT_YSIZE,
742 "Score for Diamond",FS_SMALL,FC_YELLOW);
743 DrawText(ED_COUNT_TEXT_XPOS,ED_COUNT_TEXT_YPOS+2*ED_COUNT_TEXT_YSIZE,
744 "Score for smashing a Bug",FS_SMALL,FC_YELLOW);
745 DrawText(ED_COUNT_TEXT_XPOS,ED_COUNT_TEXT_YPOS+3*ED_COUNT_TEXT_YSIZE,
746 "Score for smashing a Spaceship",FS_SMALL,FC_YELLOW);
747 DrawText(ED_COUNT_TEXT_XPOS,ED_COUNT_TEXT_YPOS+4*ED_COUNT_TEXT_YSIZE,
748 "Score for smashing a Cruncher",FS_SMALL,FC_YELLOW);
749 DrawText(ED_COUNT_TEXT_XPOS,ED_COUNT_TEXT_YPOS+5*ED_COUNT_TEXT_YSIZE,
750 "Score for smashing an Alien",FS_SMALL,FC_YELLOW);
751 DrawText(ED_COUNT_TEXT_XPOS,ED_COUNT_TEXT_YPOS+6*ED_COUNT_TEXT_YSIZE,
752 "Score for smashing a Pacman",FS_SMALL,FC_YELLOW);
753 DrawText(ED_COUNT_TEXT_XPOS,ED_COUNT_TEXT_YPOS+7*ED_COUNT_TEXT_YSIZE,
754 "Score for cracking a nut",FS_SMALL,FC_YELLOW);
755 DrawText(ED_COUNT_TEXT_XPOS,ED_COUNT_TEXT_YPOS+8*ED_COUNT_TEXT_YSIZE,
756 "Score for dynamite",FS_SMALL,FC_YELLOW);
757 DrawText(ED_COUNT_TEXT_XPOS,ED_COUNT_TEXT_YPOS+9*ED_COUNT_TEXT_YSIZE,
758 "Score for key",FS_SMALL,FC_YELLOW);
759 DrawText(ED_COUNT_TEXT_XPOS,ED_COUNT_TEXT_YPOS+10*ED_COUNT_TEXT_YSIZE,
760 "Score for each 10 seconds left",FS_SMALL,FC_YELLOW);
761 DrawText(ED_COUNT_TEXT_XPOS,ED_COUNT_TEXT_YPOS+11*ED_COUNT_TEXT_YSIZE,
762 "Speed of the amoeba / Content",FS_SMALL,FC_YELLOW);
763 DrawText(ED_COUNT_TEXT_XPOS,ED_COUNT_TEXT_YPOS+12*ED_COUNT_TEXT_YSIZE,
764 "Time for magic wall",FS_SMALL,FC_YELLOW);
765 DrawText(ED_COUNT_TEXT_XPOS,ED_COUNT_TEXT_YPOS+13*ED_COUNT_TEXT_YSIZE,
766 "Time for wheel",FS_SMALL,FC_YELLOW);
767 DrawText(ED_COUNT_TEXT_XPOS,ED_COUNT_TEXT_YPOS+14*ED_COUNT_TEXT_YSIZE,
768 "Emeralds needed in this level",FS_SMALL,FC_YELLOW);
769 DrawText(ED_COUNT_TEXT_XPOS,ED_COUNT_TEXT_YPOS+15*ED_COUNT_TEXT_YSIZE,
770 "Time available for this level",FS_SMALL,FC_YELLOW);
772 XCopyArea(display,pix[PIX_DOOR],drawto,gc,
773 DOOR_GFX_PAGEX4+ED_WIN_COUNT_XPOS,
774 DOOR_GFX_PAGEY1+ED_WIN_COUNT_YPOS,
775 ED_WIN_COUNT_XSIZE,ED_WIN_COUNT_YSIZE,
776 ED_COUNT_GADGET_XPOS,
777 ED_COUNT_GADGET_YPOS+16*ED_COUNT_GADGET_YSIZE);
779 XCopyArea(display,pix[PIX_DOOR],drawto,gc,
780 DOOR_GFX_PAGEX4+ED_WIN_COUNT_XPOS+3+2*FONT2_XSIZE,
781 DOOR_GFX_PAGEY1+ED_WIN_COUNT_YPOS,
782 ED_WIN_COUNT_XSIZE-3-2*FONT2_XSIZE,ED_WIN_COUNT_YSIZE,
783 ED_COUNT_GADGET_XPOS+3+i*FONT2_XSIZE,
784 ED_COUNT_GADGET_YPOS+16*ED_COUNT_GADGET_YSIZE);
785 DrawText(ED_COUNT_GADGET_XPOS+5,
786 ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE,
787 level.name,FS_SMALL,FC_YELLOW);
788 DrawText(ED_COUNT_GADGET_XPOS+(30+3)*FONT2_XSIZE-5,
789 ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE,
790 "Title",FS_SMALL,FC_YELLOW);
792 DrawText(ED_SIZE_GADGET_XPOS,ED_SIZE_GADGET_YPOS-18,
793 "Playfield size:",FS_SMALL,FC_YELLOW);
794 XCopyArea(display,pix[PIX_DOOR],drawto,gc,
795 DOOR_GFX_PAGEX4+ED_BUTTON_MINUS_XPOS,
796 DOOR_GFX_PAGEY1+ED_BUTTON_MINUS_YPOS,
797 DXSIZE-4,ED_BUTTON_MINUS_YSIZE,
799 ED_SIZE_GADGET_YPOS+0*ED_COUNT_GADGET_YSIZE);
800 XCopyArea(display,pix[PIX_DOOR],drawto,gc,
801 DOOR_GFX_PAGEX4+ED_BUTTON_MINUS_XPOS,
802 DOOR_GFX_PAGEY1+ED_BUTTON_MINUS_YPOS,
803 DXSIZE-4,ED_BUTTON_MINUS_YSIZE,
805 ED_SIZE_GADGET_YPOS+1*ED_COUNT_GADGET_YSIZE);
806 DrawText(ED_SIZE_TEXT_XPOS,ED_SIZE_TEXT_YPOS+0*ED_SIZE_TEXT_YSIZE,
807 "Width",FS_SMALL,FC_YELLOW);
808 DrawText(ED_SIZE_TEXT_XPOS,ED_SIZE_TEXT_YPOS+1*ED_SIZE_TEXT_YSIZE,
809 "Height",FS_SMALL,FC_YELLOW);
810 DrawText(ED_SIZE_VALUE_XPOS,ED_SIZE_VALUE_YPOS+0*ED_SIZE_GADGET_YSIZE,
811 int2str(level.fieldx,3),FS_SMALL,FC_YELLOW);
812 DrawText(ED_SIZE_VALUE_XPOS,ED_SIZE_VALUE_YPOS+1*ED_SIZE_GADGET_YSIZE,
813 int2str(level.fieldy,3),FS_SMALL,FC_YELLOW);
816 void AdjustLevelScrollPosition()
820 if (level_xpos > lev_fieldx - 2*SCR_FIELDX + 1)
821 level_xpos = lev_fieldx - 2*SCR_FIELDX + 1;
822 if (lev_fieldx < 2*SCR_FIELDX - 2)
827 if (level_ypos > lev_fieldy - 2*SCR_FIELDY + 1)
828 level_ypos = lev_fieldy - 2*SCR_FIELDY + 1;
829 if (lev_fieldy < 2*SCR_FIELDY - 2)
833 void LevelEd(int mx, int my, int button)
835 static int last_button = 0;
836 static int in_field_pressed = FALSE;
837 static boolean use_floodfill = FALSE;
841 int x = (mx-SX)/MINI_TILEX;
842 int y = (my-SY)/MINI_TILEY;
846 HandlePressedControlButtons();
847 HandleDrawingFunctions(mx, my, button);
849 if (use_floodfill) /********** FLOOD FILL **********/
857 if (mx>=SX && mx<SX+SXSIZE && my>=SY && my<SY+SYSIZE)
862 if (x>lev_fieldx || y>lev_fieldy ||
863 (x==0 && level_xpos<0) ||
864 (x==2*SCR_FIELDX-1 && level_xpos>lev_fieldx-2*SCR_FIELDX) ||
865 (y==0 && level_ypos<0) ||
866 (y==2*SCR_FIELDY-1 && level_ypos>lev_fieldy-2*SCR_FIELDY))
869 from_x = x+level_xpos;
870 from_y = y+level_ypos;
871 fill_element = (button==1 ? new_element1 :
872 button==2 ? new_element2 :
873 button==3 ? new_element3 : 0);
875 FloodFill(from_x,from_y,fill_element);
876 DrawMiniLevel(level_xpos,level_ypos);
879 use_floodfill = FALSE;
880 CloseDoor(DOOR_CLOSE_1);
881 OpenDoor(DOOR_OPEN_1 | DOOR_COPY_BACK);
890 else /********** EDIT/CTRL-FENSTER **********/
892 static unsigned long choice_delay = 0;
893 int choice = CheckElemButtons(mx,my,button);
894 int elem_pos = choice-ED_BUTTON_ELEM;
896 if (((choice == ED_BUTTON_EUP && element_shift>0) ||
897 (choice == ED_BUTTON_EDOWN &&
898 element_shift<elements_in_list-MAX_ELEM_X*MAX_ELEM_Y)) &&
899 DelayReached(&choice_delay, CHOICE_DELAY_VALUE))
903 step = (button==1 ? MAX_ELEM_X : button==2 ? 5*MAX_ELEM_X :
905 element_shift += (choice==ED_BUTTON_EUP ? -step : step);
908 if (element_shift>elements_in_list-MAX_ELEM_X*MAX_ELEM_Y)
909 element_shift = elements_in_list-MAX_ELEM_X*MAX_ELEM_Y;
910 if (element_shift % MAX_ELEM_X)
911 element_shift += MAX_ELEM_X-(element_shift % MAX_ELEM_X);
913 for(i=0;i<MAX_ELEM_X*MAX_ELEM_Y;i++)
914 DrawElemButton(i+2,ED_BUTTON_RELEASED);
916 else if (elem_pos>=0 && elem_pos<MAX_ELEM_X*MAX_ELEM_Y)
920 if (elem_pos+element_shift < elements_in_list)
921 new_element = editor_element[elem_pos+element_shift];
923 new_element = EL_LEERRAUM;
926 new_element1 = new_element;
927 else if (last_button==2)
928 new_element2 = new_element;
929 else if (last_button==3)
930 new_element3 = new_element;
932 DrawMiniGraphicExt(drawto,gc,
933 DX+ED_WIN_MB_LEFT_XPOS,
934 DY+ED_WIN_MB_LEFT_YPOS,
935 el2gfx(new_element1));
936 DrawMiniGraphicExt(drawto,gc,
937 DX+ED_WIN_MB_MIDDLE_XPOS,
938 DY+ED_WIN_MB_MIDDLE_YPOS,
939 el2gfx(new_element2));
940 DrawMiniGraphicExt(drawto,gc,
941 DX+ED_WIN_MB_RIGHT_XPOS,
942 DY+ED_WIN_MB_RIGHT_YPOS,
943 el2gfx(new_element3));
944 redraw_mask |= REDRAW_DOOR_1;
947 if (edit_mode) /********** EDIT-FENSTER **********/
954 switch(CheckEditButtons(mx,my,button))
957 CloseDoor(DOOR_CLOSE_2);
959 XCopyArea(display,pix[PIX_DOOR],pix[PIX_DB_DOOR],gc,
960 DOOR_GFX_PAGEX4,DOOR_GFX_PAGEY1+80,
962 DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY2);
963 OpenDoor(DOOR_OPEN_2);
967 Request("Caution ! Flood fill mode ! Choose area !",REQ_OPEN);
968 use_floodfill = TRUE;
974 if (!DelayReached(&choice_delay, CHOICE_DELAY_VALUE))
976 if (lev_fieldx<2*SCR_FIELDX-2)
979 level_xpos -= (button==1 ? 1 : button==2 ? 5 : lev_fieldx);
983 ScrollMiniLevel(level_xpos,level_ypos,ED_SCROLL_RIGHT);
985 DrawMiniLevel(level_xpos,level_ypos);
988 case ED_BUTTON_RIGHT:
989 if (level_xpos<=lev_fieldx-2*SCR_FIELDX)
991 if (!DelayReached(&choice_delay, CHOICE_DELAY_VALUE))
993 if (lev_fieldx<2*SCR_FIELDX-2)
996 level_xpos += (button==1 ? 1 : button==2 ? 5 : lev_fieldx);
997 if (level_xpos>lev_fieldx-2*SCR_FIELDX+1)
998 level_xpos = lev_fieldx-2*SCR_FIELDX+1;
1000 ScrollMiniLevel(level_xpos,level_ypos,ED_SCROLL_LEFT);
1002 DrawMiniLevel(level_xpos,level_ypos);
1008 if (!DelayReached(&choice_delay, CHOICE_DELAY_VALUE))
1010 if (lev_fieldy<2*SCR_FIELDY-2)
1013 level_ypos -= (button==1 ? 1 : button==2 ? 5 : lev_fieldy);
1017 ScrollMiniLevel(level_xpos,level_ypos,ED_SCROLL_DOWN);
1019 DrawMiniLevel(level_xpos,level_ypos);
1022 case ED_BUTTON_DOWN:
1023 if (level_ypos<=lev_fieldy-2*SCR_FIELDY)
1025 if (!DelayReached(&choice_delay, CHOICE_DELAY_VALUE))
1027 if (lev_fieldy<2*SCR_FIELDY-2)
1030 level_ypos += (button==1 ? 1 : button==2 ? 5 : lev_fieldy);
1031 if (level_ypos>lev_fieldy-2*SCR_FIELDY+1)
1032 level_ypos = lev_fieldy-2*SCR_FIELDY+1;
1034 ScrollMiniLevel(level_xpos,level_ypos,ED_SCROLL_UP);
1036 DrawMiniLevel(level_xpos,level_ypos);
1049 if (mx>=SX && mx<SX+SXSIZE && my>=SY && my<SY+SYSIZE)
1053 if (button && !motion_status)
1054 in_field_pressed = TRUE;
1056 if (!button || !in_field_pressed || button<1 || button>3 ||
1057 (y==0 && level_ypos<0) ||
1058 (y==2*SCR_FIELDY-1 && level_ypos>lev_fieldy-2*SCR_FIELDY) ||
1059 (x==0 && level_xpos<0) ||
1060 (x==2*SCR_FIELDX-1 && level_xpos>lev_fieldx-2*SCR_FIELDX) ||
1061 x>lev_fieldx || y>lev_fieldy)
1064 new_element = (button==1 ? new_element1 :
1065 button==2 ? new_element2 :
1066 button==3 ? new_element3 : 0);
1068 if (new_element != Feld[x+level_xpos][y+level_ypos])
1070 if (new_element==EL_SPIELFIGUR) /* Jeder nur EINE Figur bitte... */
1074 for(x=0;x<lev_fieldx;x++) for(y=0;y<lev_fieldy;y++)
1076 if (Feld[x][y]==EL_SPIELFIGUR || Feld[x][y]==EL_SPIELER1)
1078 Feld[x][y] = EL_LEERRAUM;
1079 if (x-level_xpos>=0 && x-level_xpos<2*SCR_FIELDX &&
1080 y-level_ypos>=0 && y-level_ypos<2*SCR_FIELDY)
1081 DrawMiniElement(x-level_xpos,y-level_ypos,EL_LEERRAUM);
1086 Feld[x+level_xpos][y+level_ypos] = new_element;
1087 DrawMiniElement(x,y,new_element);
1090 else if (!motion_status) /* Mauszeiger nicht im Level-Feld */
1091 in_field_pressed = FALSE;
1098 else /********** KONTROLL-FENSTER **********/
1100 int choice = CheckCountButtons(mx,my,button);
1101 int step = (button==1 ? 1 : button==2 ? 5 : button==3 ? 10 : 0);
1103 if (choice >= 0 && choice < 36 &&
1104 DelayReached(&choice_delay, CHOICE_DELAY_VALUE))
1113 level.score[choice] += step;
1114 if (level.score[choice]<0)
1115 level.score[choice] = 0;
1116 else if (level.score[choice]>255)
1117 level.score[choice] = 255;
1119 else if (choice==11)
1121 level.tempo_amoebe += step;
1122 if (level.tempo_amoebe<0)
1123 level.tempo_amoebe = 0;
1124 else if (level.tempo_amoebe>255)
1125 level.tempo_amoebe = 255;
1127 else if (choice==12)
1129 level.dauer_sieb += step;
1130 if (level.dauer_sieb<0)
1131 level.dauer_sieb = 0;
1132 else if (level.dauer_sieb>255)
1133 level.dauer_sieb = 255;
1135 else if (choice==13)
1137 level.dauer_ablenk += step;
1138 if (level.dauer_ablenk<0)
1139 level.dauer_ablenk = 0;
1140 else if (level.dauer_ablenk>255)
1141 level.dauer_ablenk = 255;
1143 else if (choice==14)
1145 level.edelsteine += step;
1146 if (level.edelsteine<0)
1147 level.edelsteine = 0;
1148 else if (level.edelsteine>999)
1149 level.edelsteine = 999;
1151 else if (choice==15)
1156 else if (level.time>999)
1159 else if (choice==16)
1162 if (lev_fieldx<MIN_LEV_FIELDX)
1163 lev_fieldx = MIN_LEV_FIELDX;
1164 else if (lev_fieldx>MAX_LEV_FIELDX)
1165 lev_fieldx = MAX_LEV_FIELDX;
1166 level.fieldx = lev_fieldx;
1168 else if (choice==17)
1171 if (lev_fieldy<MIN_LEV_FIELDY)
1172 lev_fieldy = MIN_LEV_FIELDY;
1173 else if (lev_fieldy>MAX_LEV_FIELDY)
1174 lev_fieldy = MAX_LEV_FIELDY;
1175 level.fieldy = lev_fieldy;
1179 DrawText(ED_COUNT_VALUE_XPOS,
1180 ED_COUNT_VALUE_YPOS+choice*ED_COUNT_GADGET_YSIZE,
1181 int2str(level.score[choice],3),FS_SMALL,FC_YELLOW);
1182 else if (choice==11)
1183 DrawText(ED_COUNT_VALUE_XPOS,
1184 ED_COUNT_VALUE_YPOS+11*ED_COUNT_GADGET_YSIZE,
1185 int2str(level.tempo_amoebe,3),FS_SMALL,FC_YELLOW);
1186 else if (choice==12)
1187 DrawText(ED_COUNT_VALUE_XPOS,
1188 ED_COUNT_VALUE_YPOS+12*ED_COUNT_GADGET_YSIZE,
1189 int2str(level.dauer_sieb,3),FS_SMALL,FC_YELLOW);
1190 else if (choice==13)
1191 DrawText(ED_COUNT_VALUE_XPOS,
1192 ED_COUNT_VALUE_YPOS+13*ED_COUNT_GADGET_YSIZE,
1193 int2str(level.dauer_ablenk,3),FS_SMALL,FC_YELLOW);
1194 else if (choice==14)
1195 DrawText(ED_COUNT_VALUE_XPOS,
1196 ED_COUNT_VALUE_YPOS+14*ED_COUNT_GADGET_YSIZE,
1197 int2str(level.edelsteine,3),FS_SMALL,FC_YELLOW);
1198 else if (choice==15)
1199 DrawText(ED_COUNT_VALUE_XPOS,
1200 ED_COUNT_VALUE_YPOS+15*ED_COUNT_GADGET_YSIZE,
1201 int2str(level.time,3),FS_SMALL,FC_YELLOW);
1202 else if (choice==16)
1203 DrawText(ED_SIZE_VALUE_XPOS,
1204 ED_SIZE_VALUE_YPOS+0*ED_SIZE_GADGET_YSIZE,
1205 int2str(level.fieldx,3),FS_SMALL,FC_YELLOW);
1206 else if (choice==17)
1207 DrawText(ED_SIZE_VALUE_XPOS,
1208 ED_SIZE_VALUE_YPOS+1*ED_SIZE_GADGET_YSIZE,
1209 int2str(level.fieldy,3),FS_SMALL,FC_YELLOW);
1211 redraw_mask &= ~REDRAW_FIELD;
1213 XCopyArea(display,drawto,window,gc,
1214 ED_COUNT_VALUE_XPOS,
1215 ED_COUNT_VALUE_YPOS+choice*ED_COUNT_GADGET_YSIZE,
1216 3*FONT2_XSIZE,FONT2_YSIZE,
1217 ED_COUNT_VALUE_XPOS,
1218 ED_COUNT_VALUE_YPOS+choice*ED_COUNT_GADGET_YSIZE);
1220 XCopyArea(display,drawto,window,gc,
1222 ED_SIZE_VALUE_YPOS+(choice-16)*ED_SIZE_GADGET_YSIZE,
1223 3*FONT2_XSIZE,FONT2_YSIZE,
1225 ED_SIZE_VALUE_YPOS+(choice-16)*ED_SIZE_GADGET_YSIZE);
1233 switch(CheckCtrlButtons(mx,my,button))
1235 case ED_BUTTON_EDIT:
1236 CloseDoor(DOOR_CLOSE_2);
1237 AdjustLevelScrollPosition();
1238 DrawMiniLevel(level_xpos,level_ypos);
1239 XCopyArea(display,pix[PIX_DOOR],pix[PIX_DB_DOOR],gc,
1240 DOOR_GFX_PAGEX6,DOOR_GFX_PAGEY2,
1242 DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY2);
1243 OpenDoor(DOOR_OPEN_2);
1246 case ED_BUTTON_CLEAR:
1247 if (Request("Are you sure to clear this level ?",REQ_ASK))
1249 for(x=0;x<MAX_LEV_FIELDX;x++)
1250 for(y=0;y<MAX_LEV_FIELDY;y++)
1251 Feld[x][y] = EL_ERDREICH;
1252 DrawMiniLevel(level_xpos,level_ypos);
1255 case ED_BUTTON_UNDO:
1256 if (leveldir[leveldir_nr].readonly ||
1257 Request("Exit without saving ?",REQ_ASK | REQ_STAY_OPEN))
1259 CloseDoor(DOOR_CLOSE_ALL);
1260 game_status=MAINMENU;
1265 CloseDoor(DOOR_CLOSE_1);
1266 OpenDoor(DOOR_OPEN_1 | DOOR_COPY_BACK);
1269 case ED_BUTTON_EXIT:
1271 int figur_vorhanden = FALSE;
1273 if (leveldir[leveldir_nr].readonly)
1275 Request("This level is read only !",REQ_CONFIRM);
1279 for(y=0;y<lev_fieldy;y++)
1280 for(x=0;x<lev_fieldx;x++)
1281 if (Feld[x][y]==EL_SPIELFIGUR || Feld[x][y]==EL_SPIELER1)
1282 figur_vorhanden = TRUE;
1284 if (!figur_vorhanden)
1285 Request("No Level without Gregor Mc Duffin please !",
1289 if (Request("Save this level and kill the old ?",
1290 REQ_ASK | REQ_STAY_OPEN))
1292 for(x=0;x<lev_fieldx;x++)
1293 for(y=0;y<lev_fieldy;y++)
1294 Ur[x][y]=Feld[x][y];
1295 SaveLevel(level_nr);
1297 CloseDoor(DOOR_CLOSE_ALL);
1298 game_status=MAINMENU;
1311 if (mx>=ED_COUNT_GADGET_XPOS &&
1312 mx<ED_COUNT_GADGET_XPOS+31*FONT2_XSIZE+10 &&
1313 my>=ED_COUNT_GADGET_YPOS+16*ED_COUNT_GADGET_YSIZE &&
1314 my<ED_COUNT_GADGET_YPOS+16*ED_COUNT_GADGET_YSIZE+ED_WIN_COUNT_YSIZE)
1319 DrawText(ED_COUNT_GADGET_XPOS+5,
1320 ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE,
1321 level.name,FS_SMALL,FC_GREEN);
1322 DrawText(ED_COUNT_GADGET_XPOS+5+strlen(level.name)*FONT2_XSIZE,
1323 ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE,
1324 "<",FS_SMALL,FC_RED);
1331 name_typing = FALSE;
1332 DrawText(ED_COUNT_GADGET_XPOS+5,
1333 ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE,
1334 level.name,FS_SMALL,FC_YELLOW);
1335 DrawText(ED_COUNT_GADGET_XPOS+5+strlen(level.name)*FONT2_XSIZE,
1336 ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE,
1337 " ",FS_SMALL,FC_RED);
1341 if (mx>=SX+29*MINI_TILEX && mx<SX+30*MINI_TILEX &&
1342 my>=SY+26*MINI_TILEY && my<SY+27*MINI_TILEY)
1346 if (!button || button<1 || button>3)
1349 new_element = (button==1 ? new_element1 :
1350 button==2 ? new_element2 :
1351 button==3 ? new_element3 : 0);
1353 if (new_element != level.amoebe_inhalt)
1355 level.amoebe_inhalt = new_element;
1356 DrawMiniElement(29,26,new_element);
1360 if (mx>=SX+1*MINI_TILEX && mx<SX+(1+4*5)*MINI_TILEX &&
1361 my>=SY+2*MINI_TILEY && my<SY+(2+3)*MINI_TILEY)
1363 int x = (mx-SX-1*MINI_TILEX)/MINI_TILEX;
1364 int y = (my-SY-2*MINI_TILEY)/MINI_TILEY;
1369 if (i>=0 && i<43 && x>=0 && x<3 && y>=0 && y<3)
1371 if (button && !motion_status)
1372 in_field_pressed = TRUE;
1374 if (!button || !in_field_pressed || button<1 || button>3)
1377 new_element = (button==1 ? new_element1 :
1378 button==2 ? new_element2 :
1379 button==3 ? new_element3 : 0);
1381 if (new_element != level.mampfer_inhalt[i][x][y])
1383 level.mampfer_inhalt[i][x][y] = new_element;
1384 DrawMiniElement(1+5*i+x,2+y,new_element);
1387 else if (!motion_status)/* Mauszeiger nicht im Cruncher-Feld */
1388 in_field_pressed = FALSE;
1390 else if (!motion_status) /* Mauszeiger nicht im Cruncher-Feld */
1391 in_field_pressed = FALSE;
1395 last_button = button;
1400 void LevelNameTyping(KeySym key)
1402 unsigned char ascii = 0;
1403 int len = strlen(level.name);
1408 if (key>=XK_A && key<=XK_Z)
1409 ascii = 'A'+(char)(key-XK_A);
1410 else if (key>=XK_a && key<=XK_z)
1411 ascii = 'a'+(char)(key-XK_a);
1412 else if (key>=XK_0 && key<=XK_9)
1413 ascii = '0'+(char)(key-XK_0);
1415 else if (key>=XK_space && key<=XK_at)
1416 ascii = ' '+(char)(key-XK_space);
1417 else if (key==XK_Adiaeresis)
1419 else if (key==XK_Odiaeresis)
1421 else if (key==XK_Udiaeresis)
1423 else if (key==XK_adiaeresis)
1425 else if (key==XK_odiaeresis)
1427 else if (key==XK_udiaeresis)
1429 else if (key==XK_underscore)
1433 if (ascii && len<MAX_LEVNAMLEN-2)
1435 level.name[len] = ascii;
1436 level.name[len+1] = 0;
1439 DrawTextExt(drawto,gc,
1440 ED_COUNT_GADGET_XPOS+5,
1441 ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE,
1442 level.name,FS_SMALL,FC_GREEN);
1443 DrawTextExt(window,gc,
1444 ED_COUNT_GADGET_XPOS+5,
1445 ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE,
1446 level.name,FS_SMALL,FC_GREEN);
1447 DrawTextExt(drawto,gc,
1448 ED_COUNT_GADGET_XPOS+5+len*FONT2_XSIZE,
1449 ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE,
1450 "<",FS_SMALL,FC_RED);
1451 DrawTextExt(window,gc,
1452 ED_COUNT_GADGET_XPOS+5+len*FONT2_XSIZE,
1453 ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE,
1454 "<",FS_SMALL,FC_RED);
1456 else if ((key==XK_Delete || key==XK_BackSpace) && len>0)
1458 level.name[len-1] = 0;
1461 DrawTextExt(drawto,gc,
1462 ED_COUNT_GADGET_XPOS+5+len*FONT2_XSIZE,
1463 ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE,
1464 "< ",FS_SMALL,FC_GREEN);
1465 DrawTextExt(window,gc,
1466 ED_COUNT_GADGET_XPOS+5+len*FONT2_XSIZE,
1467 ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE,
1468 "< ",FS_SMALL,FC_GREEN);
1470 else if (key==XK_Return)
1472 DrawTextExt(drawto,gc,
1473 ED_COUNT_GADGET_XPOS+5,
1474 ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE,
1475 level.name,FS_SMALL,FC_YELLOW);
1476 DrawTextExt(window,gc,
1477 ED_COUNT_GADGET_XPOS+5,
1478 ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE,
1479 level.name,FS_SMALL,FC_YELLOW);
1480 DrawTextExt(drawto,gc,
1481 ED_COUNT_GADGET_XPOS+5+len*FONT2_XSIZE,
1482 ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE,
1483 " ",FS_SMALL,FC_YELLOW);
1484 DrawTextExt(window,gc,
1485 ED_COUNT_GADGET_XPOS+5+len*FONT2_XSIZE,
1486 ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE,
1487 " ",FS_SMALL,FC_YELLOW);
1489 name_typing = FALSE;
1493 static void swap_numbers(int *i1, int *i2)
1501 static void swap_number_pairs(int *x1, int *y1, int *x2, int *y2)
1513 static void DrawLineElement(int sx, int sy, int element, boolean change_level)
1515 int lx = sx + level_xpos;
1516 int ly = sy + level_ypos;
1518 DrawMiniElement(sx, sy, (element < 0 ? Feld[lx][ly] : element));
1521 Feld[lx][ly] = element;
1524 void DrawLine(int from_x, int from_y, int to_x, int to_y, int element,
1525 boolean change_level)
1527 if (from_y == to_y) /* horizontal line */
1533 swap_numbers(&from_x, &to_x);
1535 for (x=from_x; x<=to_x; x++)
1536 DrawLineElement(x, y, element, change_level);
1538 else if (from_x == to_x) /* vertical line */
1544 swap_numbers(&from_y, &to_y);
1546 for (y=from_y; y<=to_y; y++)
1547 DrawLineElement(x, y, element, change_level);
1549 else /* diagonal line */
1551 int len_x = ABS(to_x - from_x);
1552 int len_y = ABS(to_y - from_y);
1555 if (len_y < len_x) /* a < 1 */
1557 float a = (float)len_y / (float)len_x;
1560 swap_number_pairs(&from_x, &from_y, &to_x, &to_y);
1562 for (x=0; x<=len_x; x++)
1564 int y = (int)(a * x + 0.5) * (to_y < from_y ? -1 : +1);
1566 DrawLineElement(from_x + x, from_y + y, element, change_level);
1571 float a = (float)len_x / (float)len_y;
1574 swap_number_pairs(&from_x, &from_y, &to_x, &to_y);
1576 for (y=0; y<=len_y; y++)
1578 int x = (int)(a * y + 0.5) * (to_x < from_x ? -1 : +1);
1580 DrawLineElement(from_x + x, from_y + y, element, change_level);
1586 void DrawRectangle(int from_x, int from_y, int to_x, int to_y, int element,
1587 boolean change_level)
1589 DrawLine(from_x, from_y, from_x, to_y, element, change_level);
1590 DrawLine(from_x, to_y, to_x, to_y, element, change_level);
1591 DrawLine(to_x, to_y, to_x, from_y, element, change_level);
1592 DrawLine(to_x, from_y, from_x, from_y, element, change_level);
1595 void DrawFilledBox(int from_x, int from_y, int to_x, int to_y, int element,
1596 boolean change_level)
1601 swap_number_pairs(&from_x, &from_y, &to_x, &to_y);
1603 for (y=from_y; y<=to_y; y++)
1604 DrawLine(from_x, y, to_x, y, element, change_level);
1607 void FloodFill(int from_x, int from_y, int fill_element)
1611 static int check[4][2] = { {-1,0}, {0,-1}, {1,0}, {0,1} };
1612 static int safety = 0;
1614 /* check if starting field still has the desired content */
1615 if (Feld[from_x][from_y] == fill_element)
1620 if (safety > lev_fieldx*lev_fieldy)
1621 Error(ERR_EXIT, "Something went wrong in 'FloodFill()'. Please debug.");
1623 old_element = Feld[from_x][from_y];
1624 Feld[from_x][from_y] = fill_element;
1628 x = from_x + check[i][0];
1629 y = from_y + check[i][1];
1631 if (IN_LEV_FIELD(x,y) && Feld[x][y] == old_element)
1632 FloodFill(x, y, fill_element);
1638 void CopyLevelToUndoBuffer()
1642 undo_buffer_position = (undo_buffer_position + 1) % NUM_UNDO_STEPS;
1644 if (undo_buffer_steps < NUM_UNDO_STEPS - 1)
1645 undo_buffer_steps++;
1647 for(x=0; x<lev_fieldx; x++)
1648 for(y=0; y<lev_fieldy; y++)
1649 UndoBuffer[undo_buffer_position][x][y] = Feld[x][y];
1654 printf("state saved to undo buffer %d\n", undo_buffer_position);
1658 void RandomPlacement(int button)
1663 new_element = (button == 1 ? new_element1 :
1664 button == 2 ? new_element2 :
1665 button == 3 ? new_element3 : 0);
1667 CopyLevelToUndoBuffer();
1669 if (random_placement_method == RANDOM_USE_PERCENTAGE)
1671 for(x=0; x<lev_fieldx; x++)
1672 for(y=0; y<lev_fieldy; y++)
1673 if (RND(100) < random_placement_percentage)
1674 Feld[x][y] = new_element;
1678 int elements_left = random_placement_num_objects;
1680 while (elements_left > 0)
1682 x = RND(lev_fieldx);
1683 y = RND(lev_fieldy);
1685 if (Feld[x][y] != new_element)
1687 Feld[x][y] = new_element;
1693 DrawMiniLevel(level_xpos, level_ypos);
1696 void HandleDrawingFunctions(int mx, int my, int button)
1698 static int last_button = 0;
1699 static int last_element = 0;
1700 boolean button_press_event;
1701 boolean button_release_event;
1702 boolean copy_to_undo_buffer = FALSE;
1704 int sx = (mx - SX) / MINI_TILEX;
1705 int sy = (my - SY) / MINI_TILEY;
1706 int lx = sx + level_xpos;
1707 int ly = sy + level_ypos;
1713 button_press_event = (last_button == 0 && button != 0);
1714 button_release_event = (last_button != 0 && button == 0);
1715 last_button = button;
1717 if (mx < SX || mx >= SX + SXSIZE || my < SY || my >= SY + SYSIZE)
1720 if ((!button && !button_release_event) ||
1721 sx > lev_fieldx || sy > lev_fieldy ||
1722 (sx == 0 && level_xpos<0) ||
1723 (sx == 2*SCR_FIELDX - 1 && level_xpos > lev_fieldx - 2*SCR_FIELDX) ||
1724 (sy == 0 && level_ypos < 0) ||
1725 (sy == 2*SCR_FIELDY - 1 && level_ypos > lev_fieldy - 2*SCR_FIELDY))
1728 new_element = (button == 1 ? new_element1 :
1729 button == 2 ? new_element2 :
1730 button == 3 ? new_element3 : 0);
1732 switch (drawing_function)
1734 case ED_CTRL_ID_SINGLE_ITEMS:
1735 if (button_release_event)
1736 copy_to_undo_buffer = TRUE;
1741 if (new_element != Feld[lx][ly])
1743 if (new_element == EL_SPIELFIGUR)
1745 /* remove player at old position */
1746 for(y=0; y<lev_fieldy; y++)
1748 for(x=0; x<lev_fieldx; x++)
1750 if (Feld[x][y] == EL_SPIELFIGUR || Feld[x][y] == EL_SPIELER1)
1752 Feld[x][y] = EL_LEERRAUM;
1753 if (x - level_xpos >= 0 && x - level_xpos < 2*SCR_FIELDX &&
1754 y - level_ypos >= 0 && y - level_ypos < 2*SCR_FIELDY)
1755 DrawMiniElement(x - level_xpos, y - level_ypos, EL_LEERRAUM);
1761 Feld[lx][ly] = new_element;
1762 DrawMiniElement(sx, sy, new_element);
1766 case ED_CTRL_ID_CONNECTED_ITEMS:
1768 static int last_sx = -1;
1769 static int last_sy = -1;
1771 if (button_release_event)
1772 copy_to_undo_buffer = TRUE;
1776 if (!button_press_event)
1777 DrawLine(last_sx, last_sy, sx, sy, new_element, TRUE);
1785 case ED_CTRL_ID_LINE:
1786 case ED_CTRL_ID_RECTANGLE:
1787 case ED_CTRL_ID_FILLED_BOX:
1789 static int last_sx = -1;
1790 static int last_sy = -1;
1791 static int start_sx = -1;
1792 static int start_sy = -1;
1793 void (*draw_func)(int, int, int, int, int, boolean);
1795 if (drawing_function == ED_CTRL_ID_LINE)
1796 draw_func = DrawLine;
1797 else if (drawing_function == ED_CTRL_ID_RECTANGLE)
1798 draw_func = DrawRectangle;
1800 draw_func = DrawFilledBox;
1802 if (button_press_event)
1804 last_sx = start_sx = sx;
1805 last_sy = start_sy = sy;
1807 else if (button_release_event)
1809 draw_func(start_sx, start_sy, sx, sy, last_element, TRUE);
1810 copy_to_undo_buffer = TRUE;
1812 else if (last_sx != sx || last_sy != sy)
1814 draw_func(start_sx, start_sy, last_sx, last_sy, -1, FALSE);
1815 draw_func(start_sx, start_sy, sx, sy, new_element, FALSE);
1822 case ED_CTRL_ID_FLOOD_FILL:
1823 if (button_press_event && Feld[lx][ly] != new_element)
1825 FloodFill(lx, ly, new_element);
1826 DrawMiniLevel(level_xpos, level_ypos);
1827 copy_to_undo_buffer = TRUE;
1835 last_element = new_element;
1837 if (copy_to_undo_buffer)
1838 CopyLevelToUndoBuffer();
1839 copy_to_undo_buffer = FALSE;
1842 void HandlePressedControlButtons()
1844 static unsigned long button_delay = 0;
1847 /* buttons with action when held pressed */
1851 ED_CTRL_ID_WRAP_LEFT,
1852 ED_CTRL_ID_WRAP_RIGHT,
1853 ED_CTRL_ID_WRAP_DOWN,
1857 if (!DelayReached(&button_delay, CHOICE_DELAY_VALUE))
1860 while (gadget_id[i] != -1)
1862 int id = gadget_id[i++];
1863 int state = control_button_gadget[id]->state;
1864 int button = control_button_gadget[id]->event.button;
1865 int step = (button == 1 ? 1 : button == 2 ? 5 : 10);
1867 if (state != GD_BUTTON_PRESSED)
1872 case ED_CTRL_ID_WRAP_LEFT:
1873 if (level_xpos >= 0)
1875 if (lev_fieldx < 2*SCR_FIELDX - 2)
1879 if (level_xpos <- 1)
1882 ScrollMiniLevel(level_xpos, level_ypos, ED_SCROLL_RIGHT);
1884 DrawMiniLevel(level_xpos, level_ypos);
1888 case ED_CTRL_ID_WRAP_RIGHT:
1889 if (level_xpos <= lev_fieldx - 2*SCR_FIELDX)
1891 if (lev_fieldx < 2*SCR_FIELDX - 2)
1895 if (level_xpos > lev_fieldx - 2*SCR_FIELDX + 1)
1896 level_xpos = lev_fieldx - 2*SCR_FIELDX + 1;
1898 ScrollMiniLevel(level_xpos, level_ypos, ED_SCROLL_LEFT);
1900 DrawMiniLevel(level_xpos, level_ypos);
1904 case ED_CTRL_ID_WRAP_UP:
1905 if (level_ypos >= 0)
1907 if (lev_fieldy < 2*SCR_FIELDY - 2)
1911 if (level_ypos < -1)
1914 ScrollMiniLevel(level_xpos, level_ypos, ED_SCROLL_DOWN);
1916 DrawMiniLevel(level_xpos, level_ypos);
1920 case ED_CTRL_ID_WRAP_DOWN:
1921 if (level_ypos <= lev_fieldy - 2*SCR_FIELDY)
1923 if (lev_fieldy < 2*SCR_FIELDY - 2)
1927 if (level_ypos > lev_fieldy - 2*SCR_FIELDY + 1)
1928 level_ypos = lev_fieldy - 2*SCR_FIELDY + 1;
1930 ScrollMiniLevel(level_xpos, level_ypos, ED_SCROLL_UP);
1932 DrawMiniLevel(level_xpos, level_ypos);
1942 void HandleControlButtons(struct GadgetInfo *gi)
1944 int event_type = gi->event.type;
1945 int button = gi->event.button;
1946 int player_present = FALSE;
1947 int level_changed = FALSE;
1951 /* get the button id */
1952 for (i=0; i<ED_NUM_CTRL_BUTTONS; i++)
1953 if (gi->id == control_button_gadget[i]->id)
1956 if (id < ED_NUM_CTRL1_BUTTONS && !edit_mode)
1958 AdjustLevelScrollPosition();
1959 DrawMiniLevel(level_xpos, level_ypos);
1965 case ED_CTRL_ID_SINGLE_ITEMS:
1966 case ED_CTRL_ID_CONNECTED_ITEMS:
1967 case ED_CTRL_ID_LINE:
1968 case ED_CTRL_ID_TEXT:
1969 case ED_CTRL_ID_RECTANGLE:
1970 case ED_CTRL_ID_FILLED_BOX:
1971 case ED_CTRL_ID_FLOOD_FILL:
1972 case ED_CTRL_ID_BRUSH:
1973 drawing_function = id;
1976 case ED_CTRL_ID_RANDOM_PLACEMENT:
1977 RandomPlacement(button);
1980 case ED_CTRL_ID_UNDO:
1981 if (undo_buffer_steps == 0)
1983 Request("Undo buffer empty !", REQ_CONFIRM);
1987 undo_buffer_position =
1988 (undo_buffer_position - 1 + NUM_UNDO_STEPS) % NUM_UNDO_STEPS;
1989 undo_buffer_steps--;
1991 for(x=0; x<lev_fieldx; x++)
1992 for(y=0; y<lev_fieldy; y++)
1993 Feld[x][y] = UndoBuffer[undo_buffer_position][x][y];
1994 DrawMiniLevel(level_xpos,level_ypos);
1997 case ED_CTRL_ID_INFO:
2000 DrawControlWindow();
2005 AdjustLevelScrollPosition();
2006 DrawMiniLevel(level_xpos, level_ypos);
2011 case ED_CTRL_ID_CLEAR:
2012 CopyLevelToUndoBuffer();
2014 for(x=0; x<MAX_LEV_FIELDX; x++)
2015 for(y=0; y<MAX_LEV_FIELDY; y++)
2016 Feld[x][y] = new_element3;
2018 DrawMiniLevel(level_xpos, level_ypos);
2021 case ED_CTRL_ID_SAVE:
2022 if (leveldir[leveldir_nr].readonly)
2024 Request("This level is read only !", REQ_CONFIRM);
2028 for(y=0; y<lev_fieldy; y++)
2029 for(x=0; x<lev_fieldx; x++)
2030 if (Feld[x][y] != Ur[x][y])
2031 level_changed = TRUE;
2035 Request("Level has not changed !", REQ_CONFIRM);
2039 for(y=0; y<lev_fieldy; y++)
2040 for(x=0; x<lev_fieldx; x++)
2041 if (Feld[x][y] == EL_SPIELFIGUR || Feld[x][y] == EL_SPIELER1)
2042 player_present = TRUE;
2044 if (!player_present)
2045 Request("No Level without Gregor Mc Duffin please !", REQ_CONFIRM);
2048 if (Request("Save this level and kill the old ?", REQ_ASK))
2050 for(x=0; x<lev_fieldx; x++)
2051 for(y=0; y<lev_fieldy; y++)
2052 Ur[x][y] = Feld[x][y];
2053 SaveLevel(level_nr);
2058 case ED_CTRL_ID_TEST:
2059 for(y=0; y<lev_fieldy; y++)
2060 for(x=0; x<lev_fieldx; x++)
2061 if (Feld[x][y] == EL_SPIELFIGUR || Feld[x][y] == EL_SPIELER1)
2062 player_present = TRUE;
2064 if (!player_present)
2065 Request("No Level without Gregor Mc Duffin please !", REQ_CONFIRM);
2068 for(x=0; x<lev_fieldx; x++)
2069 for(y=0; y<lev_fieldy; y++)
2070 OrigBackup[x][y] = Ur[x][y];
2072 for(x=0; x<lev_fieldx; x++)
2073 for(y=0; y<lev_fieldy; y++)
2074 Ur[x][y] = Feld[x][y];
2076 level_editor_test_game = TRUE;
2077 game_status = PLAYING;
2082 case ED_CTRL_ID_EXIT:
2083 for(y=0; y<lev_fieldy; y++)
2084 for(x=0; x<lev_fieldx; x++)
2085 if (Feld[x][y] != Ur[x][y])
2086 level_changed = TRUE;
2088 if (!level_changed ||
2089 Request("Level has changed! Exit without saving ?",
2090 REQ_ASK | REQ_STAY_OPEN))
2092 CloseDoor(DOOR_CLOSE_1);
2095 CloseDoor(DOOR_CLOSE_ALL);
2098 /* draw smaller door */
2099 XCopyArea(display, pix[PIX_DOOR], drawto, gc,
2100 DOOR_GFX_PAGEX7, 64,
2103 redraw_mask |= REDRAW_ALL;
2105 game_status = MAINMENU;
2110 CloseDoor(DOOR_CLOSE_1);
2111 XCopyArea(display, pix[PIX_DB_DOOR], pix[PIX_DB_DOOR], gc,
2112 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1, DXSIZE,DYSIZE,
2113 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
2114 OpenDoor(DOOR_OPEN_1);
2119 if (event_type == GD_EVENT_PRESSED)
2120 printf("HandleControlButtons: GD_EVENT_PRESSED\n");
2121 else if (event_type == GD_EVENT_RELEASED)
2122 printf("HandleControlButtons: GD_EVENT_RELEASED\n");
2124 printf("HandleControlButtons: ?\n");