install: add install sources and resources
[doom2d-restoration.git] / GAME / LEVELS / EDIT.CPP
blob8c33bc31e1c137c58985407a3772b3495e836de6
1 #include "glob.h"
2 #include <stdio.h>
3 #include <string.h>
4 #include <stdlib.h>
5 #include <direct.h>
6 #include <malloc.h>
7 #include "vga.h"
8 #include "view.h"
9 #include "error.h"
10 #include "gui.h"
11 #include "edit.h"
12 #include "files.h"
13 #include "memory.h"
14 #include "misc.h"
16 #define SW_PL_PRESS             1
17 #define SW_MN_PRESS             2
18 #define SW_PL_NEAR              4
19 #define SW_MN_NEAR              8
20 #define SW_KEY_R                16
21 #define SW_KEY_G                32
22 #define SW_KEY_B                64
24 enum{EBACK,EWALL,EFRONT,ETHING,ESWITCH};
26 extern "C" dword dpmi_memavl(void);
28 extern "C" {
29 extern int gamma;
30 extern char f_path[];
31 extern vgaimg *walp[256];
33 char musname[8]="";
34 int curth=-1;
37 char mapdir[_MAX_DIR]="",*mapmask[]={"*.WAD",NULL},mapfile[13]="";
39 int etype=ETHING,wallimg[3]={-1,-1,-1},wtype=1,pthing=TH_PLR1;
40 int thtnum,*tht_tlist;
41 char **thtn_list;
42 long par;
44 char *walls[256];
46 char *wt_name[]={"пусто","стена","закр.дверь","откр.дверь","ступень","вода",
47   "кислота1","кислота2","блок. мон.","лифт \x18","лифт \x19",NULL};
49 static view vw;
50 static mapwin mw1(213,93);
51 static sprview *wlsv[3];
52 static textstr th_cn(115,127,0,5,"",&smallfont,12),
53                 sw_cn(45,125,0,5,"",&smallfont,12);
54 static chkbox thf_r(115,135,10,9,E_THF_R,0),
55               thf_dm(115,145,10,9,E_THF_DM,0),
56               swf_pp(25,155,10,9,E_SWF_PP,0),
57               swf_mp(25,165,10,9,E_SWF_MP,0),
58               swf_pn(25,175,10,9,E_SWF_PN,0),
59               swf_mn(25,185,10,9,E_SWF_MN,0),
60               swf_kr(100,155,10,9,E_SWF_KR,0),
61               swf_kg(100,165,10,9,E_SWF_KG,0),
62               swf_kb(100,175,10,9,E_SWF_KB,0);
63 static strlist2 wl1(25,125,60,70,walls,E_WALLIMG,8),
64                 wl2(25,125,60,70,walls,E_WALLIMG,8),
65                 wl3(25,125,60,70,walls,E_WALLIMG,8);
67 static void about(void) {
68   static char s[2000];
70   sprintf(s,"Редактор уровней для DOOM'а 2D  V1.30\n\n"
71     "Свободно DPMI-памяти: %uK\n\n",dpmi_memavl()>>10);
72   TH_info(s+strlen(s));
73   SW_info(s+strlen(s));
74   sprintf(s+strlen(s),"Музыка: %.8s",musname);
75   message(MB_OK,"%s",s);
78 void rebuild_wl(void) {
79   char s[9];
81   s[8]=0;
82   for(int i=0;walls[i];++i) free(walls[i]);
83   for(i=0;i<255 && wal[i].n[0];++i) {
84         strncpy(s,wal[i].n,8);
85         walls[i]=strdup(s);
86   }walls[i]=NULL;
87   wl1.newlist(walls);wallimg[0]=-1;
88   wl2.newlist(walls);wallimg[1]=-1;
89   wl3.newlist(walls);wallimg[2]=-1;
92 static void redraw_th(void) {
93   th_cn.newtext(115,127,0,5,(curth==-1)?"":TH_getname(TH_gett(curth)),
94         &smallfont,12);
95   int i=TH_getf(curth);
96   thf_r.st=i&THF_DIR;thf_r.redraw();
97   thf_dm.st=i&THF_DM;thf_dm.redraw();
100 static void redraw_sw(void) {
101   sw_cn.newtext(45,125,0,5,SW_getname(),&smallfont,12);
102   byte f=SW_getf();
103   swf_pp.st=f&SW_PL_PRESS;swf_pp.redraw();
104   swf_mp.st=f&SW_MN_PRESS;swf_mp.redraw();
105   swf_pn.st=f&SW_PL_NEAR;swf_pn.redraw();
106   swf_mn.st=f&SW_MN_NEAR;swf_mn.redraw();
107   swf_kr.st=f&SW_KEY_R;swf_kr.redraw();
108   swf_kg.st=f&SW_KEY_G;swf_kg.redraw();
109   swf_kb.st=f&SW_KEY_B;swf_kb.redraw();
112 static void options(void) {
113   mdialog m(110,70,100,60);
114   hslider h1(150,90,50,10,4,gamma,E_GAMMA);
115   textstr t1(115,92,0,5,"Яркость",&smallfont,15);
116   button b1(130,110,60,15,"О'кей",C_OK,0,13);
118   desktop<<=m<<=(h1+=t1+=b1);
119   desktop.redraw();
120   for(msg=0;!msg;) GUI();
121   m.remove();desktop.redraw();
124 static void near add_wall(void) {
125   static char buf[9]="";
126   mdialog m(60,45,200,110);
127   inputbox ib(195,50,60,10,buf,9);
128   char **p=F_make_wall_list();
129   strlist2 lst(195,65,60,70,p,C_YES,8);
130   sprview sv1(64,68,128,64,NULL);
131   button b1(194,140,30,10,"О'кей",C_OK,0,13),
132          b2(226,140,30,10,"Не надо",C_CANCEL,0,27);
134   desktop<<=m<<=(b1+=b2+=ib+=lst+=sv1);
135   desktop.redraw();
136   int lc=-1;
137   for(msg=0;!msg || msg==C_YES;) {
138     GUI();
139     if(msg==C_YES) {
140       ib.cur=strlen(strcpy(buf,p[par]));ib.redraw();
141     }
142     if(lc!=ib.cur || msg==C_YES) {
143       M_unlock(sv1.img);
144       sv1.img=(vgaimg*)M_lock(F_findres(buf));sv1.redraw();
145       lc=ib.cur;
146     }
147     if(msg==C_YES) msg=0;
148   }
149   m.remove();desktop.redraw();
150   Z_freelist(p);
151   if(msg==C_CANCEL || buf[0]==0) return;
152   W_addwall(buf);rebuild_wl();
155 static void set_music(void) {
156   static char buf[9]="";
157   mdialog m(125,45,70,110);
158   inputbox ib(130,50,60,10,buf,9);
159   char **p=F_make_dmm_list();
160   strlist2 lst(130,65,60,70,p,C_YES,8);
161   button b1(129,140,30,10,"О'кей",C_OK,0,13),
162                  b2(161,140,30,10,"Не надо",C_CANCEL,0,27);
164   memcpy(buf,musname,8);buf[8]=0;
165   desktop<<=m<<=(b1+=b2+=ib+=lst);
166   desktop.redraw();
167   for(msg=0;!msg || msg==C_YES;) {
168     GUI();if(msg==C_YES) {
169       msg=0;ib.cur=strlen(strcpy(buf,p[par]));ib.redraw();
170     }
171   }
172   m.remove();desktop.redraw();
173   Z_freelist(p);
174   if(msg==C_CANCEL) return;
175   memset(musname,0,8);
176   strncpy(musname,buf,8);
179 static char *choose_map(char *fn,char *title) {
180   static char buf[9]="MAP01";
181   mdialog m(125,35,70,120);
182   inputbox ib(130,50,60,10,buf,9);
183   char **p=F_make_map_list(fn);
184   strlist2 lst(130,65,60,70,p,C_YES,8);
185   button b1(129,140,30,10,"О'кей",C_OK,0,13),
186          b2(161,140,30,10,"Не надо",C_CANCEL,0,27);
187   textstr t1(160,40,1,5,title,&smallfont,15);
189   buf[8]=0;
190   desktop<<=m<<=(b1+=b2+=ib+=lst+=t1);
191   desktop.redraw();
192   for(msg=0;!msg || msg==C_YES;) {
193     GUI();if(msg==C_YES) {
194       msg=0;ib.cur=strlen(strcpy(buf,p[par]));ib.redraw();
195     }
196   }
197   m.remove();desktop.redraw();
198   Z_freelist(p);
199   if(msg==C_CANCEL) return NULL;
200   return buf;
203 int choose_file(char *dir,char **mask,char *file,char *title) {
204   static char str[14],cdir[_MAX_DIR];
205   mdialog m(10,10,300,180);
206   char **p=F_make_file_list(dir,mask);
207   strlist2 lst(115,50,90,120,p,C_YES,10);
208   inputbox ib(115,35,90,10,file,13);
209   button b1(115,175,40,10,"О'кей",C_OK,0,13),
210                  b2(165,175,40,10,"Не надо",C_CANCEL,0,27);
211   textstr t1(160,15,1,5,title,&smallfont,15),
212           tdir(160,25,1,5,dir,&smallfont,12);
214   getcwd(cdir,_MAX_DIR);
215   chdir(dir);
216   desktop<<=m<<=(b1+=b2+=ib+=lst+=t1+=tdir);
217   desktop.redraw();
218   for(msg=0;msg!=C_OK && msg!=C_CANCEL;) {
219         GUI();
220         if(msg==C_YES) {
221           msg=0;
222           if(p[par][0]=='<') {
223                 strcpy(str,p[par]+1);str[strlen(str)-1]=0;
224                 chdir(str);getcwd(dir,_MAX_DIR);
225                 Z_freelist(p);
226                 lst.newlist(p=F_make_file_list(dir,mask));
227                 *file=0;ib.cur=0;ib.redraw();
228                 tdir.newtext(160,25,1,5,dir,&smallfont,12);
229           }else{
230                 ib.cur=strlen(strcpy(file,p[par]));ib.redraw();
231           }
232         }
233   }
234   m.remove();desktop.redraw();
235   Z_freelist(p);
236   chdir(cdir);
237   if(msg==C_CANCEL || file[0]==0) return 0;
238   if(f_path[strlen(strcpy(f_path,dir))-1]!='\\') strcat(f_path,"\\");
239   strcat(f_path,file);
240   return 1;
243 // desktop
245 struct desk:gui_obj{
246   desk();
247   virtual void draw(void);
248   virtual int key(int);
249   virtual void command(int,long);
252 desk::desk():gui_obj(0,0,320,200) {}
254 void desk::draw(void) {
255   V_clr(200,120,0,200,gray[5]);
256   gui_obj::draw();
259 int desk::key(int k) {
260   if(k==0x4400) {
261         send_command(this,E_QUIT,0);
262         return 1;
263   }
264   return gui_obj::key(k);
267 void desk::command(int c,long p) {
268   int i;
269   char *s;
270   static menu_t sysmnu[]={
271         "Опции",E_OPTIONS,"Справка",E_ABOUT,"Очистка",E_NEWMAP,
272         "Небо",E_SETSKY,
273         "Выход",E_QUIT,
274         NULL,0
275   };
276   static byte swf[7]={SW_PL_PRESS,SW_MN_PRESS,SW_PL_NEAR,SW_MN_NEAR,
277     SW_KEY_R,SW_KEY_G,SW_KEY_B};
279   switch(c) {
280         case E_DBACK: w_drawb=p;vw.redraw();break;
281         case E_DTYPE: w_drawt=p;vw.redraw();break;
282         case E_DFRONT: w_drawf=p;vw.redraw();break;
283         case E_DTHING: w_drawth=p;vw.redraw();break;
284         case E_DSWITCH: w_drawsw=p;vw.redraw();break;
285         case E_SYSTEM: desktop<<=*new menubox(305,2,sysmnu);desktop.redraw();break;
286         case E_QUIT:
287           if(message(MB_YN,"   Уже уходите?")==C_YES) ERR_quit();
288           break;
289         case E_OPTIONS: options();break;
290         case E_GAMMA: setgamma(p);break;
291         case E_ETYPE: send_command(&vw,E_DBACK+p,1);etype=p;break;
292         case E_WALLIMG: if(etype<3) {
293             wallimg[etype]=p+1;
294             wlsv[etype]->img=(p>=-1)?walp[p+1]:NULL;wlsv[etype]->redraw();
295             if(p<=-2) {wl2.lst->cline=-1;wl2.redraw();}
296           }break;
297         case E_WTYPE: wtype=p+1;break;
298         case E_THTYPE: pthing=tht_tlist[p];break;
299         case E_ADDWALL: add_wall();break;
300         case E_NEXTSW: SW_nexttype();redraw_sw();desktop.redraw();break;
301         case E_PREVSW: SW_prevtype();redraw_sw();desktop.redraw();break;
302         case E_DELSW: SW_delete(cursw);redraw_sw();desktop.redraw();break;
303         case E_THF_R: if(curth==-1) break;
304           TH_setf(curth,(TH_getf(curth)&(0xFFFF-THF_DIR))|(p?THF_DIR:0));
305           vw.redraw();break;
306         case E_THF_DM: if(curth==-1) break;
307           TH_setf(curth,(TH_getf(curth)&(0xFFFF-THF_DM))|(p?THF_DM:0));
308           break;
309         case E_SWF_PP: case E_SWF_MP: case E_SWF_PN: case E_SWF_MN:
310         case E_SWF_KR: case E_SWF_KG: case E_SWF_KB:
311           if(cursw==-1) break;
312           i=swf[c-E_SWF_PP];
313           SW_setf((SW_getf()&(0xFF-i))|(p?i:0));
314           break;
315         case E_MUSIC:
316           set_music();
317           break;
318         case E_NEWMAP:
319           if(message(MB_YN,"Стереть весь уровень?")!=C_YES) break;
320           if(message(MB_YN,"Вы уверены?")!=C_YES) break;
321           W_init();rebuild_wl();curth=-1;redraw_th();redraw_sw();
322           for(i=0;i<3;++i) wlsv[i]->img=NULL;
323           desktop.redraw();
324           break;
325         case E_LOADMAP:
326           if(!choose_file(mapdir,mapmask,mapfile,"ЗАГРУЗКА КАРТЫ")) break;
327           if(!(s=choose_map(f_path,"ЗАГРУЗКА КАРТЫ"))) break;
328           W_init();F_loadmap(f_path,s);rebuild_wl();curth=-1;redraw_th();
329           for(i=0;i<3;++i) wlsv[i]->img=NULL;
330           desktop.redraw();
331           break;
332         case E_SAVEMAP:
333           if(!choose_file(mapdir,mapmask,mapfile,"ЗАПИСЬ КАРТЫ")) break;
334 //        if(access(f_path,0)==0)
335 //              if(message(MB_YN,"Стереть старый %s ?",f_path)!=C_YES) break;
336           if(!(s=choose_map(f_path,"ЗАПИСЬ КАРТЫ"))) break;
337           if(!F_savemap(f_path,s))
338             message(MB_OK,"ВНИМАНИЕ!!!\n\nПроизошла ошибка при записи %s в файл\n"
339               "%s",s,f_path);
340           break;
341         case E_ABOUT:
342           about();
343           break;
344         case E_SETSKY:
345           if(++skytype>2) skytype=1;
346           W_setsky();
347           desktop.redraw();
348           break;
349         case E_HELP:
350           switch(p) {
351             case H_MAIN:
352               message(MB_OK,"Клавиши:\n\n"
353                 "F1      - помощь\n"
354                 "F2      - запись уровня\n"
355                 "F3      - загрузка уровня\n"
356                 "F10     - выход из редактора\n"
357                 "стрелки - прокрутка вида\n"
358               );break;
359             case H_BACK: case H_FRONT:
360               message(MB_OK,"Выберите текстуру из списка.\n"
361                 "(Добавьте, если список пустой.)\n\n"
362                 "На виде уровня нажмите левую кнопку мыши и, не\n"
363                 "отпуская ее, растяните прямоугольник, который\n"
364                 "надо заполнить текстурой.\n\n"
365                 "Аналогично, нажимая правую кнопку мыши, можно\n"
366                 "стереть %s.\n",(p==H_BACK)?"фон":"передний план"
367               );break;
368             case H_WALL:
369               message(MB_OK,
370                 "Выберите тип стены.\n"
371                 "Выберите текстуру, которую хотите поставить\n"
372                 "вместе с типом стены.\n"
373                 "Если вы хотите изменить только тип, нажмите\n"
374                 "кнопку над списком текстур.\n\n"
375                 "На виде уровня нажмите левую кнопку мыши и, не\n"
376                 "отпуская ее, растяните прямоугольник, который\n"
377                 "надо заполнить.\n\n"
378                 "Аналогично, нажимая правую кнопку мыши, можно\n"
379                 "стереть стены.\n\n"
380                 "Блок. мон. - блокировка монстров.\n"
381               );break;
382             case H_THING:
383               message(MB_OK,
384                 "Чтобы поставить новый предмет, выберите его из списка\n"
385                 "и на виде уровня нажмите правую кнопку мыши.\n\n"
386                 "Чтобы убрать предмет, щёлкните по нему правой кнопкой.\n\n"
387                 "Чтобы передвинуть предмет, нажмите на нём левую кнопку,\n"
388                 "и не отпуская её, перетащите предмет.\n"
389               );break;
390             case H_SWITCH:
391               message(MB_OK,
392                 "Чтобы поставить новую кнопку, в нужном месте на виде\n"
393                 "уровня нажмите левую кнопку мыши, и не отпуская её,\n"
394                 "нажмите правую.\n\n"
395                 "Чтобы поставить точку воздействия, нажмите правую\n"
396                 "кнопку мыши.\n"
397               );break;
398             case H_SWTYPE:
399               if(!(s=SW_gethelp())) break;
400               message(MB_OK,"%s\n",s);
401               break;
402           }break;
403         default:
404           msg=c;par=p;break;
405 //        def_command(c,p);
406   }
409 static desk dsk;
410 gui_obj& desktop=dsk;
412 // view
414 view::view():gui_obj(0,0,250,110) {
415   *this<<=*(hs=new hscroll(0,100,200,10,FLDW*CELW-200,FLDW*CELW/2,E_VIEWX,8))
416         +=*(vs=new vscroll(200,0,10,100,FLDH*CELH-98,FLDH*CELH/2,E_VIEWY,8));
417   for(int i=0;i<5;++i)
418         *this<<=*(cb[i]=new chkbox(215,i*15+10,10,9,E_DBACK+i,1));
419   cb[1]->st=0;
422 view::~view() {delete hs;delete vs;}
424 void view::draw(void) {
425   static vgaimg *s[5]=
426         {&back_icon,&wall_icon,&front_icon,&thing_icon,&switch_icon};
428   W_draw();gui_obj::draw();
429   for(int i=0;i<5;++i)
430         V_spr(240,i*15+14,s[i]);
433 void view::command(int c,long p) {
434   switch(c) {
435         case E_VIEWX: w_x=p+100;W_adjust();redraw();break;
436         case E_VIEWY: w_y=p+49;W_adjust();redraw();break;
437         case E_DBACK: case E_DTYPE: case E_DFRONT:
438         case E_DTHING: case E_DSWITCH:
439           cb[c-E_DBACK]->st=p;
440           redraw();
441         default: gui_obj::command(c,p);
442   }
445 int view::mouse(int x,int y,int b) {
446   int i,lx,ly,sx,sy;
447   byte *p;
449   if(x>=200 || y>=99 || y==0) return gui_obj::mouse(x,y,b);
450   switch(etype) {
451         case EBACK: case EWALL: case EFRONT:
452           if(b!=1 && b!=2) break;
453           edt=b;edx1=edx2=(x+w_x-100)/8;edy1=edy2=(y+w_y-50)/8;
454           redraw();
455           while(I_mget(&x,&y)&b) {
456                 if(x>=200) x=199;
457                 if(y==0) y=1;
458                 if(y>=99) y=98;
459                 x=(x+w_x-100)/8;y=(y+w_y-50)/8;
460                 if(x!=edx2 || y!=edy2) {edx2=x;edy2=y;redraw();}
461                 GUI_wait();
462           }
463           if(edx2<edx1) {i=edx1;edx1=edx2;edx2=i;}
464           if(edy2<edy1) {i=edy1;edy1=edy2;edy2=i;}
465           switch(etype) {
466                 case EWALL: if(wtype==2 || (wtype>=5 && wtype<=7)) {p=(byte*)fldf;break;}
467                 case EBACK: p=(byte*)fldb;break;
468                 case EFRONT: p=(byte*)fldf;break;
469           }
470           if(b==1) {i=wallimg[etype];b=wtype;}
471             else{b=0;i=(wallimg[etype]>=0)?0:-1;}
472           sx=sy=1;
473           if(i>0) if(((unsigned)walp[i]) > 16)
474             {sx=(walp[i]->w+7)/8;sy=(walp[i]->h+7)/8;}
475           for(edx2=edx2-edx1+1,ly=0;edy1<=edy2;++edy1,++ly) {
476             if(i>0) {
477               if(ly%sy==0)
478                 for(lx=0;lx<edx2;lx+=sx)
479                   p[edy1*FLDW+edx1+lx]=i;
480             }else if(i==0) memset(p+edy1*FLDW+edx1,0,edx2);
481             if(etype==EWALL) memset(&fld[edy1][edx1],b,edx2);
482           }
483           edt=0;redraw();mw1.redraw();
484           break;
485         case ETHING:
486           if((i=TH_isthing(w_x-100+x,w_y-50+y))!=-1) {
487                 curth=i;
488                 if(b&1) {
489                   lx=TH_getx(curth);ly=TH_gety(curth);
490                   sx=x;sy=y;
491                   while((b=I_mget(&x,&y))&1) {
492                         if(b&2) break;
493                         TH_move(curth,lx+x-sx,ly+y-sy);
494                         vw.redraw();
495                         GUI_wait();
496                   }
497                   if((b&2) || x>=200 || y==0 || y>=99) TH_move(curth,lx,ly);
498                   else TH_move(curth,lx+x-sx,ly+y-sy);
499                 }else {TH_delete(curth);curth=-1;}
500           }else if(b&2) curth=TH_add(w_x-100+x,w_y-50+y,pthing);
501           redraw_th();
502           desktop.redraw();
503           while(I_mget(&x,&y)) GUI_wait();
504           break;
505         case ESWITCH:
506           if((i=SW_ishere((w_x-100+x)>>3,(w_y-50+y)>>3))!=-1) {
507             if((b&3)==1) {cursw=i;redraw_sw();desktop.redraw();}
508           }else if((b&3)==3) {
509             SW_add((w_x-100+x)>>3,(w_y-50+y)>>3);
510             redraw_sw();desktop.redraw();
511             while((I_mget(&x,&y)&3)==3) GUI_wait();
512           }
513           if((b&3)==2) {
514             SW_setlink((w_x-100+x)>>3,(w_y-50+y)>>3);
515             desktop.redraw();
516             while(I_mget(&x,&y)&2) GUI_wait();
517           }
518           break;
519   }
520   return 1;
523 // map window
525 mapwin::mapwin(int x,int y):frame(x,y,104,104) {
526   clrh=2;clrn=0;clrl=8;
529 void mapwin::draw(void) {
530   frame::draw();
531   Z_drawmap(left+2,top+2);
532   SW_draw_mini(left+2,top+2);
535 int mapwin::mouse(int x,int y,int b) {
536   x-=2;y-=2;
537   if(x>=100 || y>=100 || x<0 || y<0) return 1;
538   while(I_mget(&x,&y)) {
539     x-=left+2;y-=top+2;
540     if(x<0) x=0;
541     if(y<0) y=0;
542     if(x>=100) x=99;
543     if(y>=100) y=99;
544     vw.hs->sld->cur=x*8-100;vw.hs->sld->adjust();
545     vw.vs->sld->cur=y*8-49;vw.vs->sld->adjust();
546     GUI_wait();
547   }
548   return 1;
551 // sprite viewer
553 sprview::sprview(int x,int y,int w,int h,vgaimg *v,char c):gui_obj(x,y,w,h) {
554   color=c;img=v;
557 void sprview::draw(void) {
558   short w,h;
560   w=scrw;h=scrh;
561   if(scrx>=left+width) return;
562   if(scry>=top+height) return;
563   if(scrx+w>left+width) scrw=left+width-scrx;
564   if(scry+h>top+height) scrh=top+height-scry;
565   V_clr(left,width,top,height,gray[color]);
566   if(img) if(img->w<=320 && img->h<=200) V_spr(left+img->sx,top+img->sy,img);
567   scrw=w;scrh=h;
570 extern "C" void edit(void) {
571   static textstr t1(115,115,1,5,"ФОН",&smallfont,15),
572                  t2(115,115,1,5,"СТЕНЫ, ДВЕРИ И Т.П.",&smallfont,15),
573                  t3(115,115,1,5,"ПЕРЕДНИЙ ПЛАН",&smallfont,15),
574                  t4(115,115,1,5,"ВЕЩИ, МОНСТРЫ И Т.П.",&smallfont,15),
575                  t5(115,115,1,5,"КНОПКИ",&smallfont,15),
576                  tht1(130,137,0,5,"вправо",&smallfont,15),
577                  tht2(130,147,0,5,"только в DM",&smallfont,15),
578                  swt1(40,157,0,5,"игрок наж.",&smallfont,15),
579                  swt2(40,167,0,5,"монстр наж.",&smallfont,15),
580                  swt3(40,177,0,5,"игрок близко",&smallfont,15),
581                  swt4(40,187,0,5,"монстр близко",&smallfont,15),
582                  swt5(115,157,0,5,"красный ключ",&smallfont,15),
583                  swt6(115,167,0,5,"зеленый ключ",&smallfont,15),
584                  swt7(115,177,0,5,"синий ключ",&smallfont,15);
585   static sprbutton hb1(199,113,6,7,&help_icon,E_HELP,H_BACK,0x3B00),
586                 hb2(199,113,6,7,&help_icon,E_HELP,H_WALL,0x3B00),
587                 hb3(199,113,6,7,&help_icon,E_HELP,H_FRONT,0x3B00),
588                 hb4(199,113,6,7,&help_icon,E_HELP,H_THING,0x3B00),
589                 hb5(199,113,6,7,&help_icon,E_HELP,H_SWITCH,0x3B00),
590                 hb6(120,123,6,7,&help_icon,E_HELP,H_SWTYPE,0x3B00);
591   static button baw1(145,125,60,10,"Добавить",E_ADDWALL,0,-1),
592                 baw2(155,125,50,10,"Добавить",E_ADDWALL,0,-1),
593                 baw3(145,125,60,10,"Добавить",E_ADDWALL,0,-1),
594                 bsw1(25,123,9,9,"\x1B",E_PREVSW,0,-1),
595                 bsw2(34,123,9,9,"\x1A",E_NEXTSW,0,-1),
596                 bsw3(25,140,40,9,"Убрать",E_DELSW,0,-1),
597                 bnw1(25,114,9,9,"",E_WALLIMG,-2,-1);
598   static strlist2 thl1(25,125,85,70,thtn_list,E_THTYPE,8);
599   static cont_t cnt1[]={
600         &t1,&back_icon,
601         &t2,&build_icon,
602         &t3,&front_icon,
603         &t4,&thing_icon,
604         &t5,&switch_icon,
605         NULL,NULL
606   };
607   static strlist2 wtl1(90,125,60,70,wt_name+1,E_WTYPE,4);
608   static sprbutton b1(305,2,13,10,&system_icon,E_SYSTEM,0,-1),
609                    b2(270,10,16,15,&load_icon,E_LOADMAP,0,0x3D00),
610                    b3(270,40,16,15,&save_icon,E_SAVEMAP,0,0x3C00),
611                    b5(308,15,6,7,&help_icon,E_HELP,H_MAIN,0x3B00);
612   static vcontbox vc1(0,110,210,90,20,cnt1,ETHING,E_ETYPE);
613   static button b4(265,70,36,15,"Музыка",E_MUSIC,0,-1);
615   logo("GUI_start: настройка графического интерфейса\n");
616   int i,t;
617   for(thtnum=1,t=TH_PLR2;t!=TH_PLR1;++thtnum,t=TH_nextt(t));
618   if(!(thtn_list=(char**)malloc((thtnum+1)*4)))
619         ERR_failinit("  Не хватает памяти");
620   if(!(tht_tlist=(int*)malloc(thtnum*4)))
621         ERR_failinit("  Не хватает памяти");
622   for(t=TH_PLR1,i=0;i<thtnum;++i,t=TH_nextt(t)) {
623         thtn_list[i]=TH_getname(tht_tlist[i]=t);
624   }thtn_list[i]=NULL;
625   thl1.newlist(thtn_list);thl1.lst->cline=0;
626   getcwd(mapdir,_MAX_DIR);
627   w_x=FLDW*CELW/2+100;w_y=FLDH*CELH/2+49;
628   rebuild_wl();
629   GUI_start();setgamma(gamma);
630   desktop<<=vw+=vc1+=mw1+=b1+=b2+=b3+=b4+=b5;
631   wtl1.lst->cline=0;
632   t1+=wl1+=baw1+=*(wlsv[0]=new sprview(145,140,60,55,NULL))+=hb1;
633   t2+=wl2+=wtl1+=baw2+=bnw1+=*(wlsv[1]=new sprview(155,140,50,55,NULL))+=hb2;
634   t3+=wl3+=baw3+=*(wlsv[2]=new sprview(145,140,60,55,NULL))+=hb3;
635   t4+=thl1+=th_cn+=thf_r+=thf_dm+=tht1+=tht2+=hb4;
636   t5+=bsw1+=bsw2+=bsw3+=sw_cn+=swt1+=swt2+=swt3+=swt4+=swt5+=swt6+=swt7
637     +=swf_pp+=swf_mp+=swf_pn+=swf_mn+=swf_kr+=swf_kg+=swf_kb+=hb5+=hb6;
638   for(;;) GUI();