1 /*
2  *  Abuse - dark 2D side-scrolling platform game
3  *  Copyright (c) 1995 Crack dot Com
4  *  Copyright (c) 2005-2011 Sam Hocevar <sam@hocevar.net>
5  *
6  *  This software was released into the Public Domain. As with most public
7  *  domain software, no warranty is made or implied by Crack dot Com, by
8  *  Jonathan Clark, or by Sam Hocevar.
9  */
10 
11 #if defined HAVE_CONFIG_H
12 #   include "config.h"
13 #endif
14 
15 #include <ctype.h>
16 #include <string.h>
17 
18 #include "common.h"
19 
20 #include "dev.h"
21 #include "input.h"
22 #include "objects.h"
23 #include "id.h"
24 #include "lisp.h"
25 #include "light.h"
26 #include "devsel.h"
27 #include "dprint.h"
28 #include "property.h"
29 #include "pmenu.h"
30 #include "filesel.h"
31 #include "tools.h"
32 #include "game.h"
33 #include "pcxread.h"
34 #include "lisp_gc.h"
35 #include "demo.h"
36 #include "profile.h"
37 #include "sbar.h"
38 #include "compiled.h"
39 #include "chat.h"
40 
41 #define make_above_tile(x) ((x)|0x4000)
42 char backw_on=0,forew_on=0,show_menu_on=0,ledit_on=0,pmenu_on=0,omenu_on=0,commandw_on=0,tbw_on=0,
43      searchw_on=0,small_render_on=0,interpolate_draw=0,disable_autolight=0,fps_on=0,profile_on=0,
44      show_names=0,fg_reversed=0,
45      raise_all;
46 
symbol_str(char const * name)47 char const *symbol_str(char const *name)
48 {
49   LSymbol *sym = LSymbol::FindOrCreate(name);
50   if (sym->GetValue() && item_type(sym->GetValue())==L_STRING)
51     return lstring_value(sym->GetValue());
52 
53 
54   // maybe english.lsp was not loaded yet, let's try to do that
55   int sp=current_space;
56   current_space=PERM_SPACE;
57 
58 
59   char prog[50];
60   char const *cs=prog;
61   strcpy(prog,"(setq section 'game_section)\n");
62   LObject::Compile(cs)->Eval();
63   strcpy(prog,"(load \"lisp/english.lsp\")\n");
64   cs=prog;
65   if (!LObject::Compile(cs)->Eval())
66   {
67     printf("unable to open file '%s'\n",lsf);
68     exit(0);
69   }
70   current_space=sp;
71 
72 
73   // check again to see if the symbol is there
74   sym = LSymbol::FindOrCreate(name);
75   if (sym->GetValue() && item_type(sym->GetValue())==L_STRING)
76     return lstring_value(sym->GetValue());
77 
78 
79   // check to see if there is a missing symbol definition
80   sym = LSymbol::FindOrCreate("missing_sym");
81   if (sym->GetValue() && item_type(sym->GetValue())==L_STRING)
82     return lstring_value(sym->GetValue());
83 
84   // last resort, return english string
85   return "Missing language symbol!";
86 }
87 
88 
89 static game_object *copy_object=NULL;
90 
91 pmenu *dev_menu=NULL;
92 Jwindow *mess_win=NULL,*warn_win=NULL;
93 
94 game_object *edit_object;
95 dev_controll *dev_cont=NULL;
96 image *small_render=NULL;
97 
98 int scale_mult,scale_div,dlastx,dlasty;
99 int last_created_type=-1;
100 char level_file[100]="levels/level00.spe";
101 
102 
103 class cached_image : public visual_object
104 {
105   int id;
106   public :
cached_image(int Id)107   cached_image(int Id) { id=Id; }
draw(image * screen,int x,int y,Filter * f)108   virtual void draw(image *screen, int x, int y, Filter *f)
109   {
110     if (f)
111       f->PutImage(screen, cache.img(id), vec2i(x, y));
112     else
113       cache.img(id)->put_image(screen,x,y);
114   }
width()115   virtual int width() { return cache.img(id)->Size().x; }
height()116   virtual int height() { return cache.img(id)->Size().y; }
117 } ;
118 
119 
120 #define DEV_MODES 3
121 cached_image *dev_mode_pict[DEV_MODES];
122 
123 int dev_del,dev_move, dev_char_left,dev_char_right,dev_back,dev_front,dev_ok,dev_copy,dev_brain,
124     dev_lights,dev_objects,dev_ai,dev_mode_icon[DEV_MODES],
125     dev_forward,dev_backward;
126 
127 char const *dev_mode_icon_names[DEV_MODES] =
128 {
129     "pixel_mode", "pick_mode", /* "fill_mode",
130     "line_mode","rect_mode","bar_mode", */ "area_select"
131 };
132 
133 int dev_mode_ids[DEV_MODES]={ ID_DMODE_DRAW,ID_DMODE_PICK, ID_DMODE_AREA};
134 
135 int edit_mode=ID_DMODE_DRAW;
136 
137 
138 dev_term *dev_console=NULL;
139 int ldef_width=0,ldef_height=0,ldef_r1=1,ldef_r2=100;
140 
141 void make_screen_size(int w, int h);
142 
143 class amb_cont : public scroller
144 {
145   public :
amb_cont(int X,int Y,ifield * Next)146   amb_cont(int X, int Y, ifield *Next) : scroller(X,Y,ID_NULL,100,wm->font()->height()+2,0,64,Next)
147   { if (player_list) sx=player_list->ambient; }
scroll_event(int newx,image * screen)148   virtual void scroll_event(int newx, image *screen)
149   {
150     screen->bar(x,y,x+l-1,y+h-1,wm->dark_color());
151     char st[100];
152     sprintf(st,"%d",newx);
153     wm->font()->put_string(screen,x+30,y+1,st,wm->bright_color());
154     if (player_list)
155       player_list->ambient=newx;
156     the_game->need_refresh();
157   }
158 } ;
159 
160 
confirm_quit()161 int confirm_quit()
162 {
163     Jwindow *quitw;
164     image *ok_image, *cancel_image;
165 
166     ok_image = cache.img(cache.reg("art/frame.spe", "dev_ok",
167                                  SPEC_IMAGE, 1))->copy();
168     cancel_image = cache.img(cache.reg("art/frame.spe", "cancel",
169                                      SPEC_IMAGE, 1))->copy();
170 
171     quitw = wm->new_window(xres / 2 + 40, yres / 2, 80, -1,
172               new button(10, wm->font()->height() + 4, ID_QUIT_OK, ok_image,
173               new button(38, wm->font()->height() + 4, ID_CANCEL, cancel_image,
174               new info_field(2, 2, ID_NULL, symbol_str("sure?"), NULL))),
175               symbol_str("quit_title"));
176 
177     wm->grab_focus(quitw);
178     int fin = 0, quit = 0;
179 
180     while(!fin)
181     {
182         wm->flush_screen();
183 
184         event ev;
185         wm->get_event(ev);
186         if(ev.type == EV_MESSAGE && ev.message.id == ID_QUIT_OK)
187             fin = quit = 1;
188         else if(ev.type == EV_MESSAGE && ev.message.id == ID_CANCEL)
189             fin = 1;
190         else if(ev.type == EV_KEY
191                  && toupper(ev.key) == toupper(*symbol_str("YES")))
192             fin = quit = 1;
193         else if(ev.type == EV_KEY
194                  && toupper(ev.key) == toupper(*symbol_str("NO")))
195             fin = 1;
196         if((ev.type == EV_KEY && ev.key == JK_ESC)
197            || ev.type == EV_CLOSE_WINDOW)
198             fin = 1;
199     }
200 
201     delete ok_image;
202     delete cancel_image;
203 
204     the_game->reset_keymap();
205 
206     wm->close_window(quitw);
207     wm->flush_screen();
208     return quit;
209 }
210 
show_object_number(game_object * who)211 static void show_object_number (game_object *who)
212 {
213   int total=0,number=0;
214   game_object *c;
215   for (c=current_level->first_object(); c; c=c->next)
216   {
217     if (c->otype==who->otype)
218       total++;
219     if (c==who) number=total;
220   }
221   char msg[100];
222   sprintf(msg,"%s : %d of %d",object_names[who->otype],number,total);
223 }
224 
search_backward()225 void dev_controll::search_backward()
226 { ;
227 }
228 
229 
single_render()230 static void single_render()
231 {
232   // enlarge clip area
233   the_game->first_view->cx2=the_game->first_view->cx1+
234                             (the_game->first_view->cx2-the_game->first_view->cx1+1)*2;
235   the_game->first_view->cy2=the_game->first_view->cy1+
236                             (the_game->first_view->cy2-the_game->first_view->cy1+1)*2;
237   delete small_render;
238   small_render=NULL;
239   small_render_on=0;
240 }
241 
double_render()242 static void double_render()
243 {
244   small_render_on=1;
245   // reduce clip area
246   the_game->first_view->cx2=the_game->first_view->cx1+
247                             (the_game->first_view->cx2-the_game->first_view->cx1+1)/2;
248   the_game->first_view->cy2=the_game->first_view->cy1+
249                             (the_game->first_view->cy2-the_game->first_view->cy1+1)/2;
250 
251   small_render=new image(vec2i(the_game->first_view->cx2-the_game->first_view->cx1+1, the_game->first_view->cy2-the_game->first_view->cy1+1),NULL,2);
252 }
253 
254 
search_forward()255 void dev_controll::search_forward()
256 {
257   if (search_window) // if no window then we can't get the object name
258   {
259     char *name=search_window->read(ID_SEARCH_TEXT);
260     int type=-1;    // see if this type exsists
261     int i;
262     for (i=0; i<total_objects; i++)
263       if (!strcmp(object_names[i],name))
264         type=i;
265     if (type==-1)
266     {
267       char msg[60];
268       sprintf(msg,"Object type '%s' does not exsists!\n",name);
269       the_game->show_help(msg);
270       the_game->need_refresh();
271     } else
272     {
273       game_object *first,*find=NULL;
274       if (!search_object || search_object->otype!=type)
275         first=current_level->first_object();
276       else
277         first=search_object->next;
278       for (; !find && first; first=first->next)
279         if (first->otype==type)
280       find=first;
281       int loop=0;
282       if (!find)
283       {
284     for (first=current_level->first_object(); first && !find; first=first->next)
285     {
286       if (first->otype==type)
287         find=first;
288     }
289     loop=1;
290       }
291       if (find)
292       {
293         search_object=find;
294     show_object_number(search_object);
295       }
296       else
297       {
298     the_game->show_help("No object matching name exsist in level\n");
299 
300       }
301     }
302   }
303 }
304 
305 
snap_x(int32_t x)306 int32_t dev_controll::snap_x(int32_t x)
307 {
308   if (wm->key_pressed(JK_CTRL_L) || wm->key_pressed(JK_CTRL_R))
309     return x-(x%the_game->ftile_width());
310   else if (wm->key_pressed(JK_ALT_L) || wm->key_pressed(JK_ALT_R))
311     return x-(x%the_game->ftile_width())+the_game->ftile_width()/2;
312   else return x;
313 }
314 
snap_y(int32_t y)315 int32_t dev_controll::snap_y(int32_t y)
316 {
317   if (wm->key_pressed(JK_CTRL_L) || wm->key_pressed(JK_CTRL_R))
318     return y-(y%the_game->ftile_height())-1;
319   else if (wm->key_pressed(JK_ALT_L) || wm->key_pressed(JK_ALT_R))
320     return y-(y%the_game->ftile_height())+the_game->ftile_height()/2-1;
321   else return y;
322 }
323 
make_ambient()324 void dev_controll::make_ambient()
325 {
326     if(ambw)
327         return;
328 
329     ambw = wm->new_window(prop->getd("ambient x", -1),
330                           prop->getd("ambient y", -1), -1, -1,
331                           new amb_cont(0, 0, NULL), "ambient");
332 }
333 
execute(char * st)334 void dev_term::execute(char *st)
335 {
336   if (!strcmp(st,"?"))
337   {
338     put_string("unchop x y, size x y,\n"
339            "load, esave, name\n");
340   } else
341   {
342     event ev;
343     dv->do_command(st,ev);
344   }
345 }
346 
load_dev_icons()347 static void load_dev_icons()
348 {
349   char const *artf="art/dev.spe";
350   dev_del=cache.reg(artf,"dev_del",SPEC_IMAGE,0);
351   dev_move=cache.reg(artf,"dev_move",SPEC_IMAGE,0);
352   dev_char_left=cache.reg(artf,"dev_char_left",SPEC_IMAGE,0);
353   dev_char_right=cache.reg(artf,"dev_char_right",SPEC_IMAGE,0);
354   dev_back=cache.reg(artf,"dev_back",SPEC_IMAGE,0);
355   dev_front=cache.reg(artf,"dev_front",SPEC_IMAGE,0);
356   dev_ok=cache.reg(artf,"dev_ok",SPEC_IMAGE,0);
357   dev_copy=cache.reg(artf,"dev_copy",SPEC_IMAGE,0);
358   dev_brain=cache.reg(artf,"brain",SPEC_IMAGE,0);
359   dev_lights=cache.reg(artf,"lights",SPEC_IMAGE,0);
360   dev_objects=cache.reg(artf,"objects",SPEC_IMAGE,0);
361   dev_ai=cache.reg(artf,"ai",SPEC_IMAGE,0);
362   dev_forward=cache.reg(artf,"forward",SPEC_IMAGE,0);
363   dev_backward=cache.reg(artf,"backward",SPEC_IMAGE,0);
364 
365   for (int i=0; i<DEV_MODES; i++)
366     dev_mode_icon[i]=cache.reg(artf,dev_mode_icon_names[i],SPEC_IMAGE,0);
367 
368 }
369 
scale_put(image * im,image * screen,int x,int y,short new_width,short new_height)370 void scale_put(image *im, image *screen, int x, int y, short new_width, short new_height)
371 {
372   unsigned char *sl1,*sl2;
373   int32_t xstep=(im->Size().x<<16)/new_width,
374        ystep=(im->Size().y<<16)/new_height,iy,ix,sx,ix_start,iy_start;
375   screen->AddDirty(x, y, x + new_width, y + new_height);
376 
377   int cx1, cy1, cx2, cy2;
378   screen->GetClip(cx1, cy1, cx2, cy2);
379   if (cx1>cx2 || cy1>cy2 || x>cx2-1 || y>cy2-1 || x+new_width<=cx1 || y+new_height<=cy1) return ;
380   if (x<cx1)
381   {
382     ix_start=(cx1-x)*xstep;
383     new_width-=(cx1-x);
384     x=cx1;
385   } else ix_start=0;
386   if (x+new_width>cx2)
387     new_width-=x+new_width-cx2;
388   if (y<cy1)
389   {
390     iy_start=(cy1-y)*ystep;
391     new_height-=(cy1-y);
392     y=cy1;
393   } else iy_start=0;
394   if (y+new_height>cy2)
395     new_height-=y+new_height-cy2;
396 
397   screen->Lock();
398   im->Lock();
399   for (iy=iy_start; new_height>0; new_height--,y++,iy+=ystep)
400   {
401     sl1=im->scan_line(iy>>16);
402     sl2=screen->scan_line(y)+x;
403     for (ix=ix_start,sx=0; sx<new_width; sx++,ix+=xstep,sl2++)
404       *sl2=sl1[ix>>16];
405   }
406   im->Unlock();
407   screen->Unlock();
408 }
409 
410 
scale_put_trans(image * im,image * screen,int x,int y,short new_width,short new_height)411 void scale_put_trans(image *im, image *screen, int x, int y, short new_width, short new_height)
412 {
413   unsigned char *sl1,*sl2;
414   int32_t xstep=(im->Size().x<<16)/new_width,
415        ystep=(im->Size().y<<16)/new_height,iy,ix,sx,ix_start,iy_start;
416   screen->AddDirty(x, y, x + new_width, y + new_height);
417 
418   int cx1, cy1, cx2, cy2;
419   screen->GetClip(cx1, cy1, cx2, cy2);
420   if (cx1>cx2 || cy1>cy2 || x>cx2-1 || y>cy2-1 || x+new_width<=cx1 || y+new_height<=cy1) return ;
421   if (x<cx1)
422   {
423     ix_start=(cx1-x)*xstep;
424     new_width-=(cx1-x);
425     x=cx1;
426   } else ix_start=0;
427   if (x+new_width>cx2)
428     new_width-=x+new_width-cx2;
429   if (y<cy1)
430   {
431     iy_start=(cy1-y)*ystep;
432     new_height-=(cy1-y);
433     y=cy1;
434   } else iy_start=0;
435   if (y+new_height>cy2)
436     new_height-=y+new_height-cy2;
437 
438   uint8_t d;
439   screen->Lock();
440   for (iy=iy_start; new_height>0; new_height--,y++,iy+=ystep)
441   {
442     sl1=im->scan_line(iy>>16);
443     sl2=screen->scan_line(y)+x;
444     for (ix=ix_start,sx=0; sx<new_width; sx++,ix+=xstep,sl2++)
445     {
446       d=sl1[ix>>16];
447       if (d)
448         *sl2=d;
449     }
450   }
451   screen->Unlock();
452 }
453 
need_plus_minus()454 int dev_controll::need_plus_minus()
455 {
456   if (state==DEV_MOVE_LIGHT) return 1; else return 0;
457 }
458 
need_arrows()459 int dev_controll::need_arrows()
460 {
461   if (state==DEV_MOVE_LIGHT) return 1; else return 0;
462 }
463 
repeat_key_mode()464 int dev_controll::repeat_key_mode()
465 {
466   if (state==DEV_MOVE_LIGHT) return 1; else return 0;
467 }
468 
469 int last_link_x=0,last_link_y=0;
470 
dev_draw(view * v)471 void dev_controll::dev_draw(view *v)
472 {
473   int32_t x1,y1,x2,y2;
474   if (dev&EDIT_MODE)
475   {
476     int32_t vx=v->xoff(),vy=v->yoff();
477 
478     if (dev&DRAW_LINKS)
479     {
480       for (light_source *f=first_light_source; f; f=f->next)
481       {
482     if (f->x-vx>=0 && f->x-vx<=(v->cx2-v->cx1+1) && f->y-vy>=0 && f->y-vy<=(v->cy2-v->cy1+1))
483     {
484       image *im=cache.img(light_buttons[f->type]);
485       im->put_image(screen,f->x-vx+v->cx1-im->Size().x/2,f->y-vy+v->cy1-im->Size().y/2,1);
486       screen->rectangle(f->x1-vx+v->cx1,f->y1-vy+v->cy1,f->x2-vx+v->cx1,f->y2-vy+v->cy1,
487                 wm->medium_color());
488     }
489       }
490     }
491 
492     if (link_object)
493     {
494       int32_t rx1,ry1;
495       the_game->game_to_mouse(link_object->x,link_object->y,v,rx1,ry1);
496       screen->line(rx1,ry1,dlastx,dlasty,yellow);
497     }
498 
499     if (selected_light)
500     {
501       image *i=cache.img(light_buttons[0]);
502       int l=i->Size().x/2,h=i->Size().y/2;
503       int32_t rx1,ry1;
504       the_game->game_to_mouse(selected_light->x,selected_light->y,v,rx1,ry1);
505       screen->rectangle(rx1-l,ry1-h,rx1+l,ry1+h,wm->bright_color());
506     }
507 
508     game_object *o;
509     if (show_names)
510       for (o=current_level->first_object(); o; o=o->next)
511       {
512     the_game->game_to_mouse(o->x,o->y,current_view,x1,y1);
513     char *nm=object_names[o->otype];
514     console_font->put_string(screen,x1-strlen(nm)*console_font->width()/2,y1+2,nm);
515       }
516 
517     if (dev&DRAW_LINKS)
518     {
519       // draw connections between objects
520       for (o=current_level->first_object(); o; o=o->next)
521       {
522     the_game->game_to_mouse(o->x,o->y,current_view,x1,y1);
523 
524     int i=0;
525     for (; i<o->total_objects(); i++)
526     {
527       game_object *other=o->get_object(i);
528       the_game->game_to_mouse(other->x,other->y,current_view,x2,y2);
529       screen->line(x1,y1,x2,y2,wm->bright_color());
530     }
531 
532     for (i=0; i<o->total_lights(); i++)
533     {
534       light_source *l=o->get_light(i);
535       the_game->game_to_mouse(l->x,l->y,current_view,x2,y2);
536       screen->line(x1,y1,x2,y2,light_connection_color);
537     }
538 
539       }
540     }
541 
542     if (selected_object)
543     {
544       selected_object->picture_space(x1,y1,x2,y2);
545       int32_t rx1,ry1,rx2,ry2;
546       the_game->game_to_mouse(x1,y1,v,rx1,ry1);
547       the_game->game_to_mouse(x2,y2,v,rx2,ry2);
548       screen->rectangle(rx1,ry1,rx2,ry2,wm->bright_color());
549 
550       the_game->game_to_mouse(selected_object->x,selected_object->y,current_view,x1,y1);
551       for (int i=0; i<selected_object->total_objects(); i++)
552       {
553     game_object *other=selected_object->get_object(i);
554     the_game->game_to_mouse(other->x,other->y,current_view,x2,y2);
555     screen->line(x1,y1,x2,y2,light_connection_color);
556       }
557     }
558 
559 
560   }
561 }
562 
find_light(int32_t x,int32_t y)563 static light_source *find_light(int32_t x, int32_t y)
564 {
565   image *i=cache.img(light_buttons[0]);
566   int l=i->Size().x/2,h=i->Size().y/2;
567   for (light_source *f=first_light_source; f; f=f->next)
568   {
569     if (x>=f->x-l && x<=f->x+l && y>=f->y-h && y<=f->y+h)
570       return f;
571   }
572   return NULL;
573 }
574 
575 
toggle_toolbar()576 void dev_controll::toggle_toolbar()
577 {
578   if (tbw)
579   {
580     tbw_on=0;
581     prop->setd("toolbar x",tbw->x);
582     prop->setd("toolbar y",tbw->y);
583     wm->close_window(tbw);
584     tbw=NULL;
585   } else
586   {
587     tbw_on=1;
588     int setx=0;
589     for (int i=0; i<DEV_MODES; i++)
590     {
591       if (edit_mode==dev_mode_ids[i])
592         setx=i;
593       dev_mode_pict[i]=new cached_image(dev_mode_icon[i]);
594     }
595 
596     tool_picker *tp=new tool_picker(0, 0,
597                          ID_NULL,
598                          5,(visual_object **)dev_mode_pict,dev_mode_ids,DEV_MODES,
599                         pal,pal,NULL);
600     tbw=wm->new_window(prop->getd("toolbar x",-1),
601                prop->getd("toolbar y",-1),-1,-1,tp);
602     tp->set_x(setx,tbw->screen);
603   }
604 }
605 
toggle_show_menu()606 void dev_controll::toggle_show_menu()
607 {
608     if(show_menu)
609     {
610         show_menu_on = 0;
611         prop->setd("layer x", show_menu->x);
612         prop->setd("layer y", show_menu->y);
613         wm->close_window(show_menu);
614         show_menu = NULL;
615         return;
616     }
617 
618     show_menu_on = 1;
619 
620     button *lnb, *lb, *cb, *bb, *bdb, *fb;
621 
622     lnb = new button(0, 100, SHOW_LINKS, symbol_str("l_links"), NULL);
623     if(dev & DRAW_LINKS)
624         lnb->push();
625     lb = new button(0, 80, SHOW_LIGHT, symbol_str("l_light"), lnb);
626     if(dev & DRAW_LIGHTS)
627         lb->push();
628     cb = new button(0, 60, SHOW_CHARACTERS, symbol_str("l_char"), lb);
629     if(dev & DRAW_PEOPLE_LAYER)
630         cb->push();
631     bb = new button(0, 40, SHOW_BACKGROUND, symbol_str("l_back"), cb);
632     if(dev & DRAW_BG_LAYER)
633         bb->push();
634     bdb = new button(0, 20, SHOW_FOREGROUND_BOUND, symbol_str("l_bound"), bb);
635     if(dev & DRAW_FG_BOUND_LAYER)
636         bdb->push();
637     fb = new button(0, 0, SHOW_FOREGROUND, symbol_str("l_fore"), bdb);
638     if(dev & DRAW_FG_LAYER)
639         fb->push();
640 
641     show_menu = wm->new_window(prop->getd("layer x", -1),
642                                prop->getd("layer y", -1), -1, -1,
643                                fb, symbol_str(symbol_str("SHOW?")));
644 }
645 
646 char **listable_objs=NULL;
647 int total_listable;
648 
toggle_omenu()649 void dev_controll::toggle_omenu()
650 {
651     if(omenu)
652     {
653         omenu_on = 0;
654         prop->setd("objects x", omenu->x);
655         prop->setd("objects y", omenu->y);
656         wm->close_window(omenu);
657         omenu = NULL;
658         free(listable_objs);
659         listable_objs = NULL;
660         return;
661     }
662 
663     omenu_on = 1;
664     total_listable = 0;
665 
666     int i, c;
667 
668     for(i = 0; i < total_objects; i++)
669         if(!figures[i]->get_cflag(CFLAG_UNLISTABLE))
670             total_listable++;
671     listable_objs = (char **)malloc(sizeof(char *) * total_listable);
672 
673     for(i = 0, c = 0; i < total_objects; i++)
674         if(!figures[i]->get_cflag(CFLAG_UNLISTABLE))
675         {
676             listable_objs[c] = object_names[i];
677             c++;
678         }
679 
680     omenu = wm->new_window(prop->getd("objects x", 0),
681                            prop->getd("objects y", 0), -1, -1,
682                            new pick_list(0, 0, DEV_CREATE,
683                                          yres / wm->font()->height() / 2,
684                                          listable_objs, total_listable, 0,
685                                          NULL, cache.img(window_texture)));
686 }
687 
get_omenu_item(int x)688 static int get_omenu_item(int x)
689 {
690   for (int i=0; i<total_objects; i++)
691     if (listable_objs[x]==object_names[i])
692       return i;
693   return 0;
694 }
695 
toggle_pmenu()696 void dev_controll::toggle_pmenu()
697 {
698     if(pmenu)
699     {
700         pmenu_on = 0;
701         prop->setd("pal x", pmenu->x);
702         prop->setd("pal y", pmenu->y);
703         wm->close_window(pmenu);
704         pmenu = NULL;
705         free(pwin_list);
706         return;
707     }
708 
709     if(!total_pals)
710     {
711         the_game->show_help(symbol_str("no_pals"));
712         return;
713     }
714 
715     pmenu_on = 1;
716 
717     pwin_list = (char **)malloc(total_pals * sizeof(char *));
718     for(int i = 0; i < total_pals; i++)
719         pwin_list[i] = pal_wins[i]->name;
720 
721     pmenu = wm->new_window(prop->getd("pal x",0),
722                            prop->getd("pal y",-1), -1,-1,
723                            new pick_list(0, 0, DEV_PALETTE,
724                                          yres / wm->font()->height() / 2,
725                                          pwin_list, total_pals, 0, NULL,
726                                          cache.img(window_texture)));
727 }
728 
729 
toggle_fgw()730 void dev_controll::toggle_fgw()
731 {
732     if(forew)
733     {
734         forew_on = 1;
735         prop->setd("fore x", forew->x);
736         prop->setd("fore y", forew->y);
737         wm->close_window(forew);
738         forew = NULL;
739         return;
740     }
741 
742     /* FIXME: shouldn't this be 1? */
743     forew_on = 0;
744     int maxh = (yres - 25) / (the_game->ftile_height() / fg_scale);
745 
746     /* FIXME: previous code had 1 instead of 0, investigate */
747     tile_picker *f_tp = new tile_picker(0, 0, DEV_FG_PICKER, SPEC_FORETILE,
748                                         fg_scale, maxh, fg_w, NULL);
749     f_tp->reverse();
750 
751     forew = wm->new_window(prop->getd("fore x", -30), prop->getd("fore y", 0),
752                            -1, -1, f_tp,symbol_str("l_fg"));
753 }
754 
toggle_music_window()755 void dev_controll::toggle_music_window()
756 {
757 /*  if (!music_window)
758   {
759     music_window=wm->new_window(-1,30,0,0,
760              new pick_list(0,0,DEV_MUSIC_PICKLIST,10,song_list,total_songs,0,NULL));
761     wm->fnt->put_string(music_window->screen,0,1,"songs");
762   } else
763   {
764     wm->close_window(music_window);
765     music_window=NULL;
766   }*/
767 }
768 
toggle_bgw()769 void dev_controll::toggle_bgw()
770 {
771     if(backw)
772     {
773         backw_on = 1;
774         prop->setd("back x", backw->x);
775         prop->setd("back y", backw->y);
776         wm->close_window(backw);
777         backw = NULL;
778         return;
779     }
780 
781     /* FIXME: shouldn't this be 1? */
782     backw_on = 0;
783     int maxh = (yres - 25) / (the_game->btile_height() / bg_scale);
784 
785     /* FIXME: previous code had 1 instead of 0, investigate */
786     tile_picker *f_tp = new tile_picker(0, 0, DEV_BG_PICKER, SPEC_BACKTILE,
787                                         bg_scale, maxh, bg_w, NULL);
788     forew = wm->new_window(prop->getd("back x", -30), prop->getd("back y", 0),
789                            -1, -1, f_tp,symbol_str("l_bg"));
790 }
791 
toggle_search_window()792 void dev_controll::toggle_search_window()
793 {
794     if(search_window)
795     {
796         searchw_on = 1;
797         prop->setd("searchw x", search_window->x);
798         prop->setd("searchw y", search_window->y);
799         prop->set("search name", search_window->read(ID_SEARCH_TEXT));
800         wm->close_window(search_window);
801         search_window = NULL;
802         search_object = NULL;
803         return;
804     }
805 
806     int bw = cache.img(dev_forward)->Size().x;
807     /* FIXME: previous code had 1,1 instead of 0,0 -- investigate */
808     search_window = wm->new_window(prop->getd("searchw x", -30),
809                                    prop->getd("searchw y", 0), -1, -1,
810         new text_field(0, 0, ID_SEARCH_TEXT, "object name>",
811                        "***************************",
812                        prop->get("search name", ""),
813         new button(bw, wm->font()->height() + 5, ID_SEARCH_BACKWARD,
814                    cache.img(dev_backward),
815         new button(bw * 3, wm->font()->height() + 5, ID_SEARCH_FOREWARD,
816                    cache.img(dev_forward), NULL))), "SEARCH");
817 
818     /* FIXME: shouldn't this be 1? */
819     searchw_on = 0;
820 }
821 
822 int open_owin=0,open_fwin=0,open_bwin=0,start_edit=0,start_nodelay=0,start_doubled=0,start_mem=0;
823 
824 
825 int get_option(char const *name);
826 
827 
dev_init(int argc,char ** argv)828 void dev_init(int argc, char **argv)
829 {
830   scale_mult=1;
831   scale_div=1;
832   dev=0;
833   int i;
834   prop=new property_manager;
835   prop->load("defaults.prp");
836 
837   for (i=1; i<argc; i++)
838   {
839     if (!strcmp(argv[i],"-edit"))
840     {
841       dev|=EDIT_MODE;
842       start_edit=1;
843       start_running=1;
844       disable_autolight=1;
845       if (get_option("-2"))
846       {
847         printf("%s\n",symbol_str("no2"));
848         exit(0);
849       }
850     }
851     else if (!strcmp(argv[i],"-fwin"))
852       open_fwin=1;
853     else if (!strcmp(argv[i],"-show_mem"))
854       start_mem=1;
855     else if (!strcmp(argv[i],"-bwin"))
856       open_bwin=1;
857     else if (!strcmp(argv[i],"-owin"))
858       open_owin=1;
859     else if (!strcmp(argv[i],"-nodelay"))
860       start_nodelay=1;
861 // AK : NOTE: Commented this out as it causes a conflict
862 /*    else if (!strcmp(argv[i],"-scale"))
863     {
864       i++;
865       scale_mult=atoi(argv[i++]);
866       scale_div=atoi(argv[i]);
867     }*/
868     else if (!strcmp(argv[i],"-f"))
869     {
870       i++;
871       strncpy(level_file, argv[i], sizeof(level_file) - 1);
872       level_file[sizeof(level_file) - 1] = '\0';
873     } else if (!strcmp(argv[i],"-2"))
874       start_doubled=1;
875     else if (!strcmp(argv[i],"-demo"))
876       demo_start=1;
877 
878   }
879 
880   if (get_option("-no_autolight"))
881     disable_autolight=0;
882 
883   if ((get_option("-size") || get_option("-vmode")) && !start_edit)
884   {
885     printf("%s\n",symbol_str("no_hirez"));
886     exit(0);
887   }
888 
889   fg_reversed=prop->getd("fg_reversed",0);
890   mouse_scrolling=prop->getd("mouse_scrolling",0);
891   palettes_locked=prop->getd("palettes_locked",0);
892   view_shift_disabled=prop->getd("view_shift_disabled",0);
893   fps_on=prop->getd("fps_on",0);
894   show_names=prop->getd("show_names",0);
895   raise_all=prop->getd("raise_all",0);
896 }
897 
898 static pmenu *make_menu(int x, int y);
899 
900 
dev_controll()901 dev_controll::dev_controll()
902 {
903   area_win=NULL;
904   current_area=NULL;
905   fg_w=bg_w=1;
906   commandw=NULL;
907   bg_scale=fg_scale=1;
908   pal_wins=NULL;
909   total_pals=0;
910   state=DEV_SELECT;
911   aiw=NULL;
912   edit_light=NULL;
913   selected_light=NULL;
914 
915   tbw=NULL;
916   modew=NULL;
917   link_object=NULL;
918   selected_object=NULL;
919   edit_object=NULL;
920   ai_object=NULL;
921   search_object = NULL;
922   oedit=NULL;
923   forew=NULL;
924   backw=NULL;
925   omenu=NULL;
926   ledit=NULL;
927   pmenu=NULL;
928   lightw=NULL;
929   search_window=NULL;
930   show_menu=NULL;
931   music_window=NULL;
932   ambw=NULL;
933   load_dev_icons();
934 
935   if (open_owin) toggle_omenu();
936   if (open_fwin) toggle_fgw();
937   if (open_bwin) toggle_bgw();
938   if (start_nodelay) the_game->toggle_delay();
939   yellow=pal->find_closest(255,255,0);
940   if (start_edit)
941   {
942     the_game->load_level(level_file);
943     the_game->draw();
944   }
945 
946   dev_console=new dev_term(50,18,this);
947   if (start_edit)
948     dev_menu=make_menu(0,yres-wm->font()->height()-5);
949 
950   if (get_option("-nolight"))
951     dev=dev^DRAW_LIGHTS;
952 }
953 
954 
set_state(int new_state)955 void dev_controll::set_state(int new_state)
956 {
957   if (start_doubled && new_state==RUN_STATE && !small_render)
958     double_render();
959 }
960 
load_stuff()961 void dev_controll::load_stuff()
962 {
963   if (dev & EDIT_MODE)
964   {
965     char prog[100];
966     char const *cs;
967     strcpy(prog,"(compile-file \"edit.lsp\")");
968     cs=prog;
969     LObject *p = LObject::Compile(cs);
970     l_user_stack.push(p);
971     p->Eval();
972     l_user_stack.pop(1);
973     for (int i=0; i<total_pals; i++)
974       pal_wins[i]->close_window();
975   }
976 
977 }
978 
do_command(char const * command,event & ev)979 void dev_controll::do_command(char const *command, event &ev)
980 {
981   char fword[50];
982   char const *st;
983   int l,h,x,y,i;
984   if (command[0]=='(')            // is this a lisp command?
985   {
986     LObject::Compile(command)->Eval();
987     return ;
988   }
989 
990   sscanf(command,"%s",fword);
991   for (st=command; *st && *st!=' '; st++);
992   if (*st) st++;
993   if (!strcmp(fword,"active"))
994   {
995     if (current_level && current_level->first_active_object())
996     {
997       game_object *o=current_level->first_active_object();
998       while (o)
999       {
1000     dprintf("%s %d %d %d %d\n",object_names[o->otype],o->x,o->y,
1001         figures[o->otype]->rangex,
1002         figures[o->otype]->rangey
1003         );
1004     o=o->next_active;
1005       }
1006     }
1007   }
1008 
1009   if (!strcmp(fword,"clear_weapons"))
1010   {
1011     view *f=NULL;
1012     for (f=player_list; f; f=f->next)
1013     {
1014       int i;
1015       for (i=0; i<total_weapons; i++)
1016     f->weapons[i]=-1;
1017 
1018       if (total_weapons)
1019         f->weapons[0]=0;
1020     }
1021   }
1022 
1023   if (!strcmp(fword,"reload"))
1024   {
1025     if (current_level && player_list && player_list->focus)
1026     {
1027       edit_object=selected_object=NULL;
1028       int32_t cx=player_list->focus->x,cy=player_list->focus->y;
1029 
1030       // save the old weapon array
1031       int32_t *w=(int32_t *)malloc(total_weapons*sizeof(int32_t));
1032       memcpy(w,player_list->weapons,total_weapons*sizeof(int32_t));
1033 
1034       char tmp[100];
1035       strcpy(tmp,current_level->name());
1036       the_game->load_level(tmp);
1037       current_level->unactivate_all();
1038 
1039       if (screen)  // don't draw if graphics haven't been setup yet.
1040         the_game->draw();
1041       player_list->reset_player();
1042       player_list->focus->x=cx;
1043       player_list->focus->y=cy;
1044 
1045       memcpy(player_list->weapons,w,total_weapons*sizeof(int32_t));
1046       free(w);
1047 
1048       the_game->need_refresh();
1049     }
1050   }
1051 
1052   if (!strcmp(fword,"unchop"))
1053   {
1054     int32_t rx,ry;
1055     the_game->btile_on(dlastx,dlasty,rx,ry);
1056     if (rx>=0 && ry>=0)
1057     {
1058       if (sscanf(command,"%s%d%d",fword,&l,&h)==3)
1059       {
1060     dprintf("unchopped %dx%d to ",l,h);
1061     l=(l+the_game->btile_width()-1)/the_game->btile_width();
1062     h=(h+the_game->btile_height()-1)/the_game->btile_height();
1063     for (y=0,i=cur_bg; y<h; y++)
1064           for (x=0; x<l; x++)
1065             the_game->put_bg(rx+x,ry+y,i++);
1066     dprintf("%dx%d\n",l,h);
1067       } else dprintf(symbol_str("unchop1"));
1068 
1069     }
1070   }
1071   if (!strcmp(fword,"center"))
1072   {
1073     view *v=the_game->first_view;
1074     for (; v; v=v->next)
1075     {
1076       v->pan_x=0;
1077       v->pan_y=0;
1078     }
1079     the_game->need_refresh();
1080   }
1081 
1082   if (!strcmp(fword,"size"))
1083   {
1084     int l,w;
1085     if (sscanf(command,"%s%d%d",fword,&l,&w)==3)
1086     {
1087       current_level->set_size(l,w);
1088       dprintf("level is now %dx%d\n",l,w);
1089     } else dprintf(symbol_str("size1"));
1090 
1091 
1092   }
1093   if (!strcmp(fword,"name"))
1094   {
1095     while (*command && *command!=' ') command++;
1096     if (*command)
1097       current_level->set_name(command+1);
1098     dprintf(symbol_str("name_now"),current_level->name());
1099   }
1100   if (!strcmp(fword,"set_first_level"))
1101   {
1102     strcpy(level_file,st);
1103     dprintf("first level will be '%s'\n",level_file);
1104   }
1105 
1106   if (!strcmp(fword,"load"))
1107   {
1108     if (!strcmp(st,"STARTING_LEVEL"))
1109       st=level_file;
1110 
1111     dprintf("loading '%s'\n",st);
1112     the_game->load_level(st);
1113     current_level->unactivate_all();
1114 
1115     the_game->need_refresh();
1116   }
1117 
1118   if (!strcmp(fword,"mem"))
1119   {
1120     if (st[0])
1121       show_char_mem(st);
1122     else show_mem();
1123   }
1124 
1125   if (!strcmp(fword,"esave"))
1126   {
1127     dprintf(symbol_str("esave"));
1128     save();
1129   }
1130 
1131   if (!strcmp(fword,"delete"))
1132   {
1133     if (selected_object)
1134     {
1135       if (!(dev&EDIT_MODE) && current_level->is_attacker(selected_object))
1136         the_game->show_help(symbol_str("nd_player"));
1137       else
1138       {
1139     if (selected_object->controller())
1140       the_game->show_help(symbol_str("nd_player"));
1141     else
1142     {
1143       current_level->delete_object(selected_object);
1144       if (S_DELETE_SND>0) cache.sfx(S_DELETE_SND)->play(sfx_volume/2);
1145       selected_object=NULL;
1146     }
1147       }
1148     } else if (selected_light)
1149     {
1150       if (!edit_light)
1151       {
1152     if (current_level)
1153     {
1154           current_level->remove_light(selected_light);
1155       if (S_DELETE_SND>0) cache.sfx(S_DELETE_SND)->play(sfx_volume/2);
1156     }
1157     else
1158           delete_light(selected_light);
1159     selected_light=NULL;
1160       }
1161     } else the_game->show_help(symbol_str("d_nosel"));
1162     the_game->need_refresh();
1163   }
1164 
1165   if (!strcmp(fword,"create"))
1166   {
1167     char oname[100];
1168     sscanf(command,"%s%s",fword,oname);       // read the type of object to create
1169     int x,t=-1;
1170     for (x=0; x<total_objects; x++)             // find the object type by name
1171        if (!strcmp(object_names[x],oname))
1172          t=x;
1173 
1174     if (t>=0)                                 // did we find it?
1175     {
1176       int32_t rx,ry;
1177       the_game->mouse_to_game(dlastx,dlasty,rx,ry);
1178       edit_object=create(t,rx,ry);
1179       current_level->add_object(edit_object);
1180       the_game->need_refresh();
1181       last_created_type=t;
1182     } else
1183     {
1184       sprintf(fword,"No such object type : %s\n",oname);
1185       the_game->show_help(fword);
1186     }
1187   }
1188 
1189   if (!strcmp(fword,"move"))
1190   {
1191     if (selected_object)
1192       edit_object=selected_object;
1193 
1194     if (edit_object)
1195       state=DEV_MOVE_OBJECT;
1196     else the_game->show_help("No object selected");
1197 
1198   }
1199   if (!strcmp(fword,"move_light"))
1200   {
1201     if (selected_light)
1202       edit_light=selected_light;
1203 
1204     if (edit_light)
1205       state=DEV_MOVE_LIGHT;
1206     else the_game->show_help("No light selected");
1207 
1208   }
1209 
1210 
1211   if (!strcmp(fword,"clear_auto"))
1212   {
1213     int32_t i,j;
1214     for (i=0; i<current_level->foreground_width(); i++)
1215       for (j=0; j<current_level->foreground_height(); j++)
1216         current_level->clear_fg(i,j);
1217   }
1218 
1219   if (!strcmp(fword,"fg_select"))
1220   {
1221     int32_t x,y;
1222     the_game->ftile_on(dlastx,dlasty,x,y);
1223     if (x>=0 && y>=0 && x<current_level->foreground_width() &&
1224     y<current_level->foreground_height())
1225     {
1226       cur_fg=current_level->get_fg(x,y);
1227       if (forew)
1228     ((tile_picker *)forew->read(DEV_FG_PICKER))->recenter(forew->screen);
1229       the_game->need_refresh();
1230     }
1231   }
1232 
1233   if (!strcmp(fword,"toggle_fg_raise"))
1234   {
1235     int32_t x,y;
1236     the_game->ftile_on(dlastx,dlasty,x,y);
1237     if (x>=0 && y>=0 && x<current_level->foreground_width() &&
1238     y<current_level->foreground_height())
1239       current_level->fg_set_raised(x,y,!current_level->fg_raised(x,y));
1240   }
1241 
1242   if (!strcmp(fword,"fg_add"))
1243   {
1244     int x;
1245     if (sscanf(st,"%d",&x))
1246     {
1247       cur_fg++;
1248       if (cur_fg<0) cur_fg=0;
1249       if (cur_fg>=nforetiles) cur_fg=nforetiles-1;
1250 
1251       if (forew)
1252     ((tile_picker *)forew->read(DEV_FG_PICKER))->recenter(forew->screen);
1253     }
1254   }
1255 
1256   if (!strcmp(fword,"restart"))
1257   {
1258     current_level->restart();
1259   }
1260   if (!strcmp(fword,"quit"))
1261   {
1262     the_game->end_session();
1263   }
1264 
1265   if (!strcmp(fword,"to_front"))
1266   {
1267     game_object *which=selected_object;
1268     if (!selected_object) which=edit_object;
1269     if (which)
1270       current_level->to_front(which);
1271     else the_game->show_help(symbol_str("forward?"));
1272   }
1273 
1274   if (!strcmp(fword,"to_back"))
1275   {
1276     game_object *which=selected_object;
1277     if (!selected_object) which=edit_object;
1278     if (which)
1279       current_level->to_back(which);
1280     else the_game->show_help(symbol_str("back?"));
1281   }
1282 
1283   if (!strcmp(fword,"set_aitype"))
1284   {
1285     game_object *which=selected_object;
1286     if (!selected_object) which=edit_object;
1287     if (which)
1288     {
1289       int x;
1290       if (*st && sscanf(st,"%d",&x)!=EOF)
1291         which->change_aitype(x);
1292       else
1293       {
1294     switch (ev.key)
1295     {
1296       case '0' : which->change_aitype(0); break;
1297       case '1' : which->change_aitype(1); break;
1298       case '2' : which->change_aitype(2); break;
1299       case '3' : which->change_aitype(3); break;
1300       case '4' : which->change_aitype(4); break;
1301       case '5' : which->change_aitype(5); break;
1302       case '6' : which->change_aitype(6); break;
1303       case '7' : which->change_aitype(7); break;
1304       case '8' : which->change_aitype(8); break;
1305       case '9' : which->change_aitype(9); break;
1306       case ')' : which->change_aitype(10); break;
1307       case '!' : which->change_aitype(11); break;
1308       case '@' : which->change_aitype(12); break;
1309       case '#' : which->change_aitype(13); break;
1310       case '$' : which->change_aitype(14); break;
1311       case '%' : which->change_aitype(15); break;
1312       case '^' : which->change_aitype(16); break;
1313       case '&' : which->change_aitype(17); break;
1314       case '*' : which->change_aitype(18); break;
1315       case '(' : which->change_aitype(19); break;
1316     }
1317       }
1318       the_game->need_refresh();
1319     }
1320     else the_game->show_help(symbol_str("aitype"));
1321   }
1322 }
1323 
1324 
toggle_light_window()1325 void dev_controll::toggle_light_window()
1326 {
1327     if(lightw)
1328     {
1329         prop->setd("light create x", lightw->x);
1330         prop->setd("light create y", lightw->y);
1331         prop->setd("light create w", atoi(lightw->read(DEV_LIGHTW)));
1332         prop->setd("light create h", atoi(lightw->read(DEV_LIGHTH)));
1333         prop->setd("light create r1", atoi(lightw->read(DEV_LIGHTR1)));
1334         prop->setd("light create r2", atoi(lightw->read(DEV_LIGHTR2)));
1335         wm->close_window(lightw);
1336         lightw = NULL;
1337         return;
1338     }
1339 
1340     int bh = 16 + 6, bw = 20 + 6, th = wm->font()->height() + 4;
1341 
1342     lightw = wm->new_window(prop->getd("light create x", 0),
1343                             prop->getd("light create y", 0), -1, -1,
1344         new button_box(0, 0, DEV_LIGHT_BUTTON_BOX, 1,
1345             new button(bw * 0, bh * 0, DEV_LIGHT0, cache.img(light_buttons[0]),
1346             new button(bw * 1, bh * 0, DEV_LIGHT1, cache.img(light_buttons[1]),
1347             new button(bw * 2, bh * 0, DEV_LIGHT2, cache.img(light_buttons[2]),
1348             new button(bw * 0, bh * 1, DEV_LIGHT3, cache.img(light_buttons[3]),
1349             new button(bw * 1, bh * 1, DEV_LIGHT4, cache.img(light_buttons[4]),
1350             new button(bw * 2, bh * 1, DEV_LIGHT5, cache.img(light_buttons[5]),
1351             new button(bw * 0, bh * 2, DEV_LIGHT6, cache.img(light_buttons[6]),
1352             new button(bw * 1, bh * 2, DEV_LIGHT7, cache.img(light_buttons[7]),
1353             new button(bw * 2, bh * 2, DEV_LIGHT8, cache.img(light_buttons[8]),
1354             new button(bw * 0, bh * 3, DEV_LIGHT9, cache.img(light_buttons[9]),
1355             new button(bw * 1, bh * 3, DEV_AMBIENT, cache.img(light_buttons[11]),
1356             NULL))))))))))),
1357         new text_field(0, bh * 4, DEV_LIGHTW, "W ", "******",
1358                        prop->getd("light create w", 0),
1359         new text_field(0, bh * 4 + th * 1, DEV_LIGHTH, "H ", "******",
1360                        prop->getd("light create h", 0),
1361         new text_field(0, bh * 4 + th * 2, DEV_LIGHTR1, "R1", "******",
1362                        prop->getd("light create r1", 1),
1363         new text_field(0, bh * 4 + th * 3, DEV_LIGHTR2, "R2", "******",
1364                        prop->getd("light create r2", 100), NULL))))),
1365         symbol_str("l_light"));
1366 }
1367 
make_ai_window(game_object * o)1368 void dev_controll::make_ai_window(game_object *o)
1369 {
1370   ai_object=o;
1371   int th=wm->font()->height()+4,wl = 0, wh = 20;
1372   if (figures[o->otype]->total_fields)
1373   {
1374     int maxl=0;
1375     int i=0;
1376     for (; i<figures[o->otype]->total_fields; i++)
1377       if( strlen(figures[o->otype]->fields[i]->descript_name) > (unsigned)maxl )
1378         maxl=strlen(figures[o->otype]->fields[i]->descript_name);
1379 
1380     int owh=wh;
1381     ifield *first=NULL,*last=NULL;
1382     for (i=0; i<figures[o->otype]->total_fields; i++)
1383     {
1384       char tmp[200];
1385       strcpy(tmp,figures[o->otype]->fields[i]->descript_name);
1386       for (int j=maxl-strlen(figures[o->otype]->fields[i]->descript_name); j; j--)
1387         strcat(tmp," ");
1388       int er;
1389       ifield *p=new text_field(wl,wh,ID_NULL,tmp,"######",
1390                    (double)o->get_var_by_name(figures[o->otype]->fields[i]->real_name,er),
1391                    NULL);
1392       if (last)
1393         last->next=p;
1394       else
1395         first=p;
1396       last=p;
1397       wh+=th;
1398     }
1399     aiw=wm->new_window(prop->getd("ai x",0),
1400                prop->getd("ai y",0),
1401                -1,-1,
1402        new button(wl,owh-20,DEV_AI_OK,cache.img(dev_ok),first),"ai");
1403 
1404   }
1405   else
1406   {
1407     aiw=wm->new_window(prop->getd("ai x",0),
1408                prop->getd("ai y",0),
1409                -1,-1,
1410        new button(wl,wh-20,DEV_AI_OK,cache.img(dev_ok),
1411        new text_field(wl,wh+th*0, DEV_AI_XVEL,    symbol_str("ai_xvel"),"#####",(double)o->xvel(),
1412        new text_field(wl,wh+th*1, DEV_AI_YVEL,    symbol_str("ai_yvel"),"#####",(double)o->yvel(),
1413        new text_field(wl,wh+th*2, DEV_AI_XACEL,   symbol_str("ai_xacel"),"#####",(double)o->xacel(),
1414        new text_field(wl,wh+th*3, DEV_AI_YACEL,   symbol_str("ai_yacel"),"#####",(double)o->yacel(),
1415        new text_field(wl,wh+th*4, DEV_AI_STTIME,  symbol_str("ai_stime"),"####",(double)o->aistate_time(),
1416        new text_field(wl,wh+th*5, DEV_AI_GRAVITY, symbol_str("ai_gravity"),"####",(double)o->gravity(),
1417        new text_field(wl,wh+th*6, DEV_AI_HEALTH,  symbol_str("ai_health"),"####",(double)o->hp(),
1418        new text_field(wl,wh+th*7, DEV_AI_MORPHPR, symbol_str("ai_morph"),"####",(double)o->mp(),
1419        new text_field(wl,wh+th*8, DEV_AI_TYPE,    symbol_str("ai_type"),"####",(double)o->aitype(),
1420        new text_field(wl,wh+th*9,DEV_AI_STATE,    symbol_str("ai_state"),"####",(double)o->aistate(),
1421        new text_field(wl,wh+th*10,DEV_AI_FADE,    symbol_str("ai_fade"),"####",(double)o->fade_count(),
1422               NULL)))))))))))),"ai");
1423   }
1424 
1425   wm->grab_focus(aiw);
1426 }
1427 
notify_deleted_light(light_source * l)1428 void dev_controll::notify_deleted_light(light_source *l)
1429 {
1430   if (l==edit_light)
1431   {
1432     if (ledit)
1433     {
1434       prop->setd("ledit x",ledit->x);
1435       prop->setd("ledit y",ledit->y);
1436       wm->close_window(ledit); ledit=NULL;
1437     }
1438     edit_light=NULL;
1439   }
1440   if (l==selected_light)
1441     selected_light=NULL;
1442 }
1443 
notify_deleted_object(game_object * o)1444 void dev_controll::notify_deleted_object(game_object *o)
1445 {
1446   if (o==edit_object)
1447   {
1448     state=DEV_SELECT;
1449     close_oedit_window();
1450   }
1451 
1452   if (o==ai_object)
1453     close_ai_window();
1454   if (o==search_object)
1455   { if (search_window)
1456       toggle_search_window();
1457     search_object=NULL;
1458   }
1459   if (o==link_object)
1460     link_object=NULL;
1461   if (o==selected_object)
1462   {
1463     selected_object=NULL;
1464     state=DEV_SELECT;
1465   }
1466 
1467 }
1468 
close_ai_window()1469 void dev_controll::close_ai_window()
1470 {
1471   if (aiw)
1472   {
1473     game_object *o=ai_object;
1474     int32_t x;
1475     if (o)
1476     {
1477       if (figures[o->otype]->total_fields)
1478       {
1479     ifield *f=aiw->inm->get(DEV_AI_OK)->next;
1480     for (int i=0; i<figures[o->otype]->total_fields; i++)
1481     {
1482       x=atoi(f->read());
1483       char *v=figures[o->otype]->fields[i]->real_name;
1484       int er;
1485       if (o->get_var_by_name(v,er)!=x)
1486       o->set_var_by_name(v,x);
1487       f=f->next;
1488     }
1489       }
1490       else
1491       {
1492     x=atoi(aiw->read(DEV_AI_XVEL)); if (x!=o->xvel()) o->set_xvel(x);
1493     x=atoi(aiw->read(DEV_AI_YVEL)); if (x!=o->yvel()) o->set_yvel(x);
1494 
1495     x=atoi(aiw->read(DEV_AI_XACEL)); if (x!=o->xacel()) o->set_xacel(x);
1496     x=atoi(aiw->read(DEV_AI_YACEL)); if (x!=o->yacel()) o->set_yacel(x);
1497 
1498     x=atoi(aiw->read(DEV_AI_STTIME)); if (x!=o->aistate_time()) o->set_aistate_time(x);
1499     x=atoi(aiw->read(DEV_AI_GRAVITY)); if (x!=o->gravity()) o->set_gravity(x);
1500 
1501     x=atoi(aiw->read(DEV_AI_HEALTH)); if (x!=o->hp()) o->set_hp(x);
1502     x=atoi(aiw->read(DEV_AI_MORPHPR)); if (x!=o->mp()) o->set_mp(x);
1503 
1504     x=atoi(aiw->read(DEV_AI_TYPE)); if (x!=o->aitype()) o->set_aitype(x);
1505     x=atoi(aiw->read(DEV_AI_STATE)); if (x!=o->aistate()) o->set_aistate(x);
1506     x=atoi(aiw->read(DEV_AI_FADE)); if (x!=o->fade_count()) o->set_fade_count(x);
1507       }
1508     }
1509     prop->setd("ai x",aiw->x);
1510     prop->setd("ai y",aiw->y);
1511     wm->close_window(aiw);
1512     aiw=NULL;
1513     ai_object=NULL;
1514     the_game->need_refresh();
1515   }
1516 }
1517 
1518 
area_handle_input(event & ev)1519 void dev_controll::area_handle_input(event &ev)
1520 {
1521 
1522   if (ev.type==EV_MOUSE_BUTTON && ev.mouse_button)
1523   {
1524     int32_t gx,gy;
1525     the_game->mouse_to_game(last_demo_mx,last_demo_my,gx,gy);
1526     if (!current_level) return ;
1527     current_area=current_level->area_list=new area_controller(gx,gy,
1528                                   the_game->ftile_width(),
1529                                   the_game->ftile_height(),
1530                                   current_level->area_list);
1531     the_game->need_refresh();
1532     state=DEV_DRAG_AREA_BOTTOM;
1533   }
1534 }
1535 
close_area_win(int read_values)1536 void dev_controll::close_area_win(int read_values)
1537 {
1538   if (area_win)
1539   {
1540     prop->setd("area_box x",area_win->x);
1541     prop->setd("area_box y",area_win->y);
1542 
1543     if (current_area && read_values)
1544     {
1545       current_area->ambient=atoi(area_win->read(DEV_AREA_AMBIENT));
1546       current_area->ambient_speed=atoi(area_win->read(DEV_AREA_AMBIENT_SPEED));
1547       current_area->view_xoff=atoi(area_win->read(DEV_AREA_VIEW_XOFF));
1548       current_area->view_yoff=atoi(area_win->read(DEV_AREA_VIEW_YOFF));
1549       current_area->view_xoff_speed=atoi(area_win->read(DEV_AREA_VIEW_XOFF_SPEED));
1550       current_area->view_yoff_speed=atoi(area_win->read(DEV_AREA_VIEW_YOFF_SPEED));
1551     }
1552     wm->close_window(area_win);
1553     area_win=NULL;
1554   }
1555 }
1556 
pick_handle_input(event & ev)1557 void dev_controll::pick_handle_input(event &ev)
1558 {
1559   area_controller *find=NULL;
1560   int find_top=0;
1561   if (!current_level) return;
1562   if (ev.type==EV_MOUSE_BUTTON && ev.mouse_button)
1563   {
1564     int32_t mx=last_demo_mx,my=last_demo_my;
1565     view *v=the_game->view_in(mx,my);
1566     for (area_controller *a=current_level->area_list; a; a=a->next)
1567     {
1568       int32_t x1,y1,x2,y2;
1569       the_game->game_to_mouse(a->x,a->y,v,x1,y1);
1570       the_game->game_to_mouse(a->x+a->w,a->y+a->h,v,x2,y2);
1571       if (abs(x1-mx)<2 && abs(y1-my)<2)
1572       { find=a;    find_top=1; }
1573       else if (abs(x2-mx)<2 && abs(y2-my)<2)
1574       { find=a;    find_top=0; }
1575     }
1576 
1577     time_marker now;
1578     int dc=now.diff_time(&last_area_click)<0.5;
1579     last_area_click.get_time();
1580     if (find && current_area && dc)
1581     {
1582       if (area_win) close_area_win(0);
1583       int wl=0,wh=0,th=wm->font()->height()+12,bw=cache.img(dev_ok)->Size().x+10;
1584       area_win=wm->new_window(prop->getd("area_box x",0),
1585                   prop->getd("area_box y",0),
1586                   -1,-1,
1587 
1588                   new button(wl+bw*0,wh-8,DEV_AREA_OK,cache.img(dev_ok),
1589                   new button(wl+bw*1,wh-8,DEV_AREA_DELETE,cache.img(dev_del),
1590 
1591                   new text_field(wl,wh+th*1,DEV_AREA_AMBIENT,         symbol_str("a_ambient"),"******",current_area->ambient,
1592                               new text_field(wl,wh+th*2,DEV_AREA_AMBIENT_SPEED,   symbol_str("a_aspeed"),"******",current_area->ambient_speed,
1593                               new text_field(wl,wh+th*3,DEV_AREA_VIEW_XOFF,       symbol_str("a_view_xoff"),"******",current_area->view_xoff,
1594                               new text_field(wl,wh+th*4,DEV_AREA_VIEW_YOFF,       symbol_str("a_view_yoff"),"******",current_area->view_yoff,
1595                               new text_field(wl,wh+th*5,DEV_AREA_VIEW_XOFF_SPEED, symbol_str("a_view_xspd"),"******",current_area->view_xoff_speed,
1596                               new text_field(wl,wh+th*6,DEV_AREA_VIEW_YOFF_SPEED, symbol_str("a_view_yspd"),"******",current_area->view_yoff_speed,
1597                          NULL)))))))));
1598     } else if (find)
1599     {
1600       current_area=find;
1601       current_area->active=1;
1602       if (find_top)
1603       state=DEV_DRAG_AREA_TOP;
1604       else state=DEV_DRAG_AREA_BOTTOM;
1605       the_game->need_refresh();
1606     } else if (current_area)
1607     {
1608       current_area->active=0;
1609       current_area=NULL;
1610       the_game->need_refresh();
1611     }
1612   }
1613 }
1614 
close_oedit_window()1615 void dev_controll::close_oedit_window()
1616 {
1617   if (oedit)
1618   {
1619     prop->setd("oedit x",oedit->x);
1620     prop->setd("oedit y",oedit->y);
1621     wm->close_window(oedit);
1622     oedit=NULL;
1623     edit_object=NULL;
1624   }
1625 }
1626 
1627 int screen_shot_on=1;
1628 int sshot_fcount=-1;
1629 
handle_event(event & ev)1630 void dev_controll::handle_event(event &ev)
1631 {
1632   int32_t x,y;
1633   if (link_object && (dlastx!=last_link_x || dlasty!=last_link_y))
1634   {
1635     last_link_x=dlastx;
1636     last_link_y=dlasty;
1637     the_game->need_refresh();
1638   }
1639 
1640   if (dev_menu && dev_menu->handle_event(ev,screen)) return ;
1641 
1642   if (!current_level) return ;
1643 
1644   for (x=0; x<total_pals; x++)
1645     pal_wins[x]->handle_event(ev);
1646   if (ev.type==EV_MOUSE_MOVE)
1647   {
1648     dlastx=last_demo_mx;
1649     dlasty=last_demo_my;
1650   }
1651   if (dev_console && dev_console->handle_event(ev))
1652     return;
1653 
1654   if (ev.type==EV_KEY && ev.key==JK_F2)
1655     write_PCX(screen,pal,"scrnshot.pcx");
1656   else if (ev.type==EV_KEY && ev.key==JK_F3)
1657   {
1658     char name[100];
1659     sprintf(name,"shot%04d.pcx",screen_shot_on++);
1660     write_PCX(screen,pal,name);
1661   } else if (ev.type==EV_KEY && ev.key==JK_F5)
1662   {
1663     if (sshot_fcount!=-1)
1664     {
1665       sshot_fcount=-1;
1666       the_game->show_help(symbol_str("seqs_off"));
1667     }
1668     else
1669     {
1670       sshot_fcount=0;
1671       the_game->show_help(symbol_str("seqs_on"));
1672     }
1673   }
1674 
1675   switch (state)
1676   {
1677     case DEV_MOUSE_RELEASE :
1678     {
1679       if (!ev.mouse_button)
1680         state=DEV_SELECT;
1681     } break;
1682 
1683     case DEV_CREATE_OBJECT :
1684     {
1685       if (!ev.mouse_button)
1686         state=DEV_MOVE_OBJECT;
1687     } break;
1688 
1689 
1690     case DEV_MOVE_OBJECT :
1691     {
1692       if (!edit_object)
1693       { state=DEV_SELECT; }
1694       else
1695       {
1696     if (ev.type==EV_MOUSE_MOVE)
1697     {
1698       the_game->mouse_to_game(last_demo_mx,last_demo_my,edit_object->x,edit_object->y);
1699       edit_object->x=snap_x(edit_object->x);
1700       edit_object->y=snap_y(edit_object->y);
1701       the_game->need_refresh();
1702     }
1703     else if (ev.mouse_button==1 && ev.window==NULL)
1704     {
1705       state=DEV_MOUSE_RELEASE;
1706       selected_object=edit_object=NULL;
1707     }
1708     if (ev.window==NULL && ev.type==EV_KEY && ev.key=='d')
1709     {
1710       int32_t xv=0,yv=100;
1711       edit_object->try_move(edit_object->x,edit_object->y,xv,yv,1);
1712       edit_object->y+=yv;
1713       state=DEV_SELECT;
1714       selected_object=edit_object=NULL;
1715     }
1716       }
1717     } break;
1718 
1719 
1720     case DEV_MOVE_LIGHT :
1721     {
1722       if (edit_light)
1723       {
1724     if (ev.type==EV_MOUSE_MOVE)
1725     {
1726       the_game->mouse_to_game(last_demo_mx,last_demo_my,edit_light->x,edit_light->y);
1727       edit_light->x=snap_x(edit_light->x);
1728       edit_light->y=snap_y(edit_light->y);
1729 
1730       edit_light->calc_range();
1731       the_game->need_refresh();
1732     } else if (ev.type==EV_KEY)
1733     {
1734       int rd=0;
1735       switch (ev.key)
1736       {
1737         case '+' :
1738         {
1739           if (edit_light->type==9)
1740           {
1741         if (edit_light->inner_radius<64)
1742         { edit_light->inner_radius++; rd=1; }
1743           } else { edit_light->outer_radius++; rd=1; }
1744         } break;
1745         case '-' :
1746         {
1747           if (edit_light->type==9)
1748           {
1749         if (edit_light->inner_radius>0)
1750         { edit_light->inner_radius--; rd=1; }
1751           } else if (edit_light->outer_radius>edit_light->inner_radius+1)
1752           { edit_light->outer_radius--; rd=1; }
1753         } break;
1754         case JK_RIGHT :
1755         {
1756           if (edit_light->type==9)
1757           { edit_light->xshift++; rd=1; }
1758           else if (edit_light->xshift>0)
1759           { edit_light->xshift--; rd=1; }
1760         } break;
1761         case JK_LEFT :
1762         {
1763           if (edit_light->type==9)
1764           {
1765         if (edit_light->xshift>1)
1766         { edit_light->xshift--; rd=1; }
1767           }
1768           else
1769           { edit_light->xshift++; rd=1; }
1770         } break;
1771         case JK_UP :
1772         {
1773           if (edit_light->type==9)
1774           { edit_light->yshift++; rd=1; }
1775           else if (edit_light->yshift>0)
1776           { edit_light->yshift--; rd=1; }
1777         } break;
1778         case JK_DOWN :
1779         {
1780           if (edit_light->type==9)
1781           {
1782         if (edit_light->yshift>1)
1783         { edit_light->yshift--; rd=1; }
1784           }
1785           else
1786           { edit_light->yshift++; rd=1; }
1787         } break;
1788 
1789       }
1790       if (rd)
1791       {
1792         edit_light->calc_range();
1793         the_game->need_refresh();
1794       }
1795 
1796     }
1797       }
1798 
1799       if ((ev.mouse_button==1 && ev.window==NULL) || !edit_light)
1800         state=DEV_MOUSE_RELEASE;
1801     } break;
1802 
1803 
1804     case DEV_DRAG_AREA_BOTTOM :
1805     {
1806       if (current_area)
1807       {
1808     int32_t gx,gy;
1809     the_game->mouse_to_game(last_demo_mx,last_demo_my,gx,gy);
1810     if (gx>current_area->x && gy>current_area->y)
1811     {
1812       if (gx-current_area->x!=current_area->w || gy-current_area->y!=current_area->h)
1813       {
1814         the_game->need_refresh();
1815         current_area->w=gx-current_area->x;
1816         current_area->h=gy-current_area->y;
1817       }
1818     }
1819     if (ev.type==EV_MOUSE_BUTTON && !ev.mouse_button)
1820     {
1821       current_area->active=0;
1822       state=DEV_SELECT;
1823     }
1824       }
1825     } break;
1826 
1827     case DEV_DRAG_AREA_TOP :
1828     {
1829       if (current_area)
1830       {
1831     int32_t gx,gy;
1832     the_game->mouse_to_game(last_demo_mx,last_demo_my,gx,gy);
1833     if (gx<current_area->x+current_area->w && gy<current_area->y+current_area->h)
1834     {
1835       if (gx!=current_area->x || gy!=current_area->y)
1836       {
1837         the_game->need_refresh();
1838         current_area->x=gx;
1839         current_area->y=gy;
1840       }
1841     }
1842     if (ev.type==EV_MOUSE_BUTTON && !ev.mouse_button)
1843     {
1844       current_area->active=0;
1845       state=DEV_SELECT;
1846     }
1847       }
1848     } break;
1849 
1850     case DEV_SELECT :
1851     {
1852       if (dev&EDIT_MODE)
1853       {
1854     game_object *old=selected_object;
1855     selected_object=NULL;
1856     if (ev.window==NULL)
1857     {
1858       int32_t rx,ry;
1859       the_game->mouse_to_game(last_demo_mx,last_demo_my,rx,ry);
1860 
1861       if (!(dev & MAP_MODE))
1862       {
1863         if (dev&DRAW_PEOPLE_LAYER)
1864               selected_object=current_level->find_object(rx,ry);
1865         light_source *old_light=selected_light;
1866         if (selected_object)
1867           selected_light=NULL;
1868         else
1869           selected_light=find_light(rx,ry);
1870         if (selected_light!=old_light)
1871           the_game->need_refresh();
1872       } else { selected_light=NULL; }
1873 
1874       if (edit_mode==ID_DMODE_DRAW)
1875       {
1876         if (ev.mouse_button==1 && !selected_object && !selected_light)
1877         {
1878           int32_t xs,ys;
1879           the_game->ftile_on(last_demo_mx,last_demo_my,xs,ys);
1880           if (xs>=0 && ys>=0 && xs<current_level->foreground_width() &&
1881           ys<current_level->foreground_height())
1882           current_level->put_fg(xs,ys,raise_all ? make_above_tile(cur_fg) : cur_fg);
1883           the_game->need_refresh();
1884         } else if (ev.mouse_button==1 && !selected_object && !selected_light)
1885         {
1886           int32_t xs,ys;
1887           the_game->btile_on(last_demo_mx,last_demo_my,xs,ys);
1888           if (xs>=0 && ys>=0 && xs<current_level->background_width() &&
1889           ys<current_level->background_height())
1890           current_level->put_bg(xs,ys,cur_fg);
1891           the_game->need_refresh();
1892         }
1893       } else if (edit_mode==ID_DMODE_AREA)
1894         area_handle_input(ev);
1895       else if (edit_mode==ID_DMODE_PICK)
1896         pick_handle_input(ev);
1897     }
1898 
1899     if (old!=selected_object)
1900         the_game->need_refresh();
1901 
1902 
1903     if (ev.mouse_button)
1904     {
1905       if (selected_object)
1906       {
1907         if (edit_object && edit_object!=selected_object)
1908              edit_object->add_object(selected_object);
1909 
1910         if (oedit)
1911           close_oedit_window();
1912 
1913         int bw=20+6,bh=16+6;
1914 
1915         oedit=wm->new_window(prop->getd("oedit x",0),
1916                  prop->getd("oedit y",0),
1917                  -1,-1,new button_box(0,0,ID_NULL,1,
1918         new button(bw*0,0,DEV_OEDIT_OK,cache.img(dev_ok),
1919         new button(bw*1,0,DEV_OEDIT_MOVE,cache.img(dev_move),
1920         new button(bw*2,0,DEV_OEDIT_FRONT,cache.img(dev_front),
1921             new button(bw*3,0,DEV_OEDIT_BACK,cache.img(dev_back),
1922             new button(bw*4,0,DEV_OEDIT_COPY,cache.img(dev_copy),
1923         new button(bw*0,bh*1,DEV_OEDIT_DELETE,cache.img(dev_del),
1924                NULL)))))),
1925            new button(bw*5,bh*0,DEV_OEDIT_AI,cache.img(dev_ai),
1926 
1927            new button_box(bw*1,bh*1,DEV_OEDIT_CHAR_BOX,0,
1928            new button(bw*1,bh*1,DEV_OEDIT_LEFT,cache.img(dev_char_left),
1929            new button(bw*2,bh*1,DEV_OEDIT_RIGHT,cache.img(dev_char_right),NULL)),
1930 
1931            new button(bw*3,bh*1,DEV_OBJECTS_DELETE,cache.img(dev_objects),
1932            new button(bw*4,bh*1,DEV_LIGHTS_DELETE,cache.img(dev_lights),NULL))))),
1933                  symbol_str("l_EDIT"));
1934 
1935 
1936         edit_object=selected_object;
1937       } else if (selected_light)
1938       {
1939         if (ledit)
1940         {
1941           prop->setd("ledit x",ledit->x);
1942           prop->setd("ledit x",ledit->y);
1943           wm->close_window(ledit);
1944         }
1945         int bw=20+6,bh=16+6,th=wm->font()->height()+4;
1946         edit_light=selected_light;
1947         if (edit_object)
1948         {
1949           edit_object->add_light(edit_light);
1950           edit_light->known=1;
1951         }
1952         ledit=wm->new_window(prop->getd("ledit x",0),
1953                  prop->getd("ledit y",0),
1954                  -1,-1,
1955               new button_box(0,0,ID_NULL,1,
1956                    new button(bw*0,0,DEV_LEDIT_OK,cache.img(dev_ok),
1957                new button(bw*1,0,DEV_LEDIT_MOVE,cache.img(dev_move),
1958                   new button(bw*2,0,DEV_LEDIT_COPY,cache.img(dev_copy),
1959             new button(bw*3,0,DEV_LEDIT_DEL,cache.img(dev_del),NULL)))),
1960             new text_field(0,bh,DEV_LEDIT_W,      "W ","******",edit_light->xshift,
1961             new text_field(0,bh+th*1,DEV_LEDIT_H, "H ","******",edit_light->yshift,
1962           new text_field(0,bh+th*2,DEV_LEDIT_R1,"R1","******",(int)(edit_light->inner_radius),
1963          new text_field(0,bh+th*3,DEV_LEDIT_R2,"R2","******",(int)(edit_light->outer_radius),
1964                    NULL))))));
1965       }
1966       else if (ev.window==NULL)
1967       {
1968         if (dlastx>=0 && dlasty>=0 && edit_mode==ID_DMODE_DRAW)
1969         {
1970           if ((dev & DRAW_FG_LAYER) && ev.mouse_button==1)
1971           {
1972         the_game->ftile_on(last_demo_mx,last_demo_my,x,y);
1973         if (x>=0 && y>=0 && x<current_level->foreground_width() &&
1974             y<current_level->foreground_height())
1975         the_game->put_fg(x,y,raise_all ? make_above_tile(cur_fg) : cur_fg);
1976           }
1977           if ((dev & DRAW_BG_LAYER) && ev.mouse_button==2)
1978           {
1979         the_game->btile_on(last_demo_mx,last_demo_my,x,y);
1980         if (x>=0 && y>=0 && x<current_level->background_width() &&
1981             y<current_level->background_height())
1982         the_game->put_bg(x,y,cur_bg);
1983           }
1984         }
1985       }
1986     }
1987       }
1988     }
1989     default:
1990       break;
1991   }
1992 
1993   switch (ev.type)
1994   {
1995     case EV_MESSAGE :
1996     {
1997       switch (ev.message.id)
1998       {
1999     case ID_DMODE_DRAW :
2000     case ID_DMODE_PICK :
2001     case ID_DMODE_FILL :
2002     case ID_DMODE_LINE :
2003     case ID_DMODE_RECT :
2004     case ID_DMODE_BAR  :
2005     case ID_DMODE_AREA :
2006     {
2007       edit_mode=ev.message.id;
2008     } break;
2009 /*    case ID_ENLARGE_RENDER :
2010     {
2011       if (!small_render)
2012         double_render();
2013       else
2014         single_render();
2015 
2016       view_shift_disabled=!view_shift_disabled;
2017     } break; */
2018 
2019     case ID_SEARCH :
2020     {
2021       toggle_search_window();
2022     } break;
2023     case ID_SEARCH_FOREWARD :
2024     { search_forward();
2025     } break;
2026     case ID_SEARCH_BACKWARD :
2027     { search_forward();
2028     } break;
2029     case ID_CANCEL :
2030     {
2031       if (mess_win)
2032       {
2033         wm->close_window(mess_win);
2034         mess_win=NULL;
2035       } break;
2036     } break;
2037     case ID_LEVEL_LOAD :
2038     {
2039       if (!mess_win)
2040       {
2041         mess_win=file_dialog(symbol_str("level_name"),current_level ? current_level->name() : "",
2042                  ID_LEVEL_LOAD_OK,symbol_str("ok_button"),ID_CANCEL,symbol_str("cancel_button"),
2043                  symbol_str("FILENAME"),ID_MESS_STR1);
2044         wm->grab_focus(mess_win);
2045       }
2046     } break;
2047     case ID_LEVEL_LOAD_OK :
2048     {
2049       char cmd[100];
2050       sprintf(cmd,"load %s",mess_win->read(ID_MESS_STR1));
2051       dev_cont->do_command(cmd,ev);
2052       wm->push_event(new event(ID_CANCEL,NULL));        // close window
2053     } break;
2054     case ID_GAME_SAVE :
2055     {
2056       current_level->save("savegame.spe",1);
2057       the_game->show_help(symbol_str("saved_game"));
2058       the_game->need_refresh();
2059     } break;
2060     case ID_LEVEL_SAVE :
2061     { if (current_level)
2062       {
2063         if (current_level->save(current_level->name(),0))
2064         {
2065           char msg[100];
2066           sprintf(msg,symbol_str("saved_level"),current_level->name());
2067           the_game->show_help(msg);
2068           the_game->need_refresh();
2069         }
2070       }
2071       else the_game->show_help("no current level, cannot save");
2072     } break;
2073     case ID_LEVEL_SAVEAS :
2074     {
2075       if (!mess_win)
2076       {
2077         mess_win=file_dialog(symbol_str("saveas_name"),current_level ? current_level->name() : "untitled.spe",
2078                    ID_LEVEL_SAVEAS_OK,symbol_str("ok_button"),
2079                  ID_CANCEL,symbol_str("cancel_button"),
2080                  symbol_str("FILENAME"),ID_MESS_STR1);
2081         wm->grab_focus(mess_win);
2082       }
2083     } break;
2084     case ID_LEVEL_SAVEAS_OK :
2085     {
2086       if (current_level)
2087       {
2088         current_level->set_name(mess_win->read(ID_MESS_STR1));
2089         wm->push_event(new event(ID_CANCEL,NULL));        // close window after save
2090         wm->push_event(new event(ID_LEVEL_SAVE,NULL));
2091       }
2092     } break;
2093     case ID_EDIT_SAVE :
2094     {
2095       do_command("esave",ev);
2096       the_game->show_help(symbol_str("edit_saved"));
2097     } break;
2098     case ID_CACHE_PROFILE :
2099     {
2100       if (current_level && !cache.prof_is_on())
2101       {
2102         cache.prof_init();
2103         the_game->show_help("Cache profiling is now on.");
2104       }
2105       else the_game->show_help("Cache profiling is already on!");
2106     } break;
2107 
2108     case ID_CACHE_PROFILE_END :  // ask the user for a file name to save as
2109     {
2110       if (cache.prof_is_on())
2111       {
2112         cache.prof_uninit();
2113         the_game->show_help(symbol_str("prof_off"));
2114       } else the_game->show_help(symbol_str("prof"));
2115     } break;
2116 
2117     case ID_LEVEL_NEW :
2118     {
2119       if (!mess_win)
2120       {
2121         mess_win=wm->new_window(xres/2,yres/2,-1,-1,
2122                new button(10,20,ID_LEVEL_NEW_OK,symbol_str("YES"),
2123                         new button(40,20,ID_CANCEL,symbol_str("NO"),
2124           new info_field(0,0,ID_NULL,symbol_str("sure?"),NULL))),symbol_str("New?"));
2125         wm->grab_focus(mess_win);
2126       }
2127     } break;
2128     case ID_LEVEL_NEW_OK :
2129     {
2130       wm->push_event(new event(ID_CANCEL,NULL));  // close_window
2131       if (current_level)
2132         delete current_level;
2133       current_level=new level(100,100,"untitled.spe");
2134     } break;
2135     case ID_LEVEL_RESIZE :
2136     {
2137       if (!mess_win)
2138       {
2139         int h=wm->font()->height()+8;
2140         mess_win=wm->new_window(xres/2,yres/2,-1,-1,
2141             new text_field(0,h*0,ID_MESS_STR1,symbol_str("width_"),"****",
2142                    current_level ? current_level->foreground_width() : 100,
2143             new text_field(0,h*1,ID_MESS_STR2,symbol_str("height_"),"****",
2144                    current_level ? current_level->foreground_height() : 100,
2145                    new button(10,h*4,ID_LEVEL_RESIZE_OK,symbol_str("ok_button"),
2146                    new button(40,h*4,ID_CANCEL,symbol_str("cancel_button"),NULL)))),symbol_str("_scroll"));
2147       }
2148     } break;
2149     case ID_LEVEL_RESIZE_OK :
2150     {
2151       if (current_level)
2152       {
2153         current_level->set_size(atoi(mess_win->read(ID_MESS_STR1)),
2154                     atoi(mess_win->read(ID_MESS_STR2)));
2155       } else the_game->show_help("Create a level first!");
2156       wm->push_event(new event(ID_CANCEL,NULL));  // close_window
2157     } break;
2158 
2159     case ID_SUSPEND :
2160     {
2161       dev^=SUSPEND_MODE;
2162       if (dev&SUSPEND_MODE)
2163         the_game->show_help(symbol_str("suspend_on"));
2164       else
2165          the_game->show_help(symbol_str("suspend_off"));
2166     } break;
2167     case ID_PLAY_MODE :
2168     {
2169       dev^=EDIT_MODE;
2170     } break;
2171     case ID_QUIT :
2172     {
2173       if (confirm_quit())
2174         do_command("quit",ev);
2175     } ;
2176     case ID_TOGGLE_MAP :
2177     {
2178       if (dev&MAP_MODE) dev-=MAP_MODE;
2179       else dev|=MAP_MODE;
2180       the_game->need_refresh();
2181     } break;
2182     case ID_TOGGLE_LIGHT :
2183     {
2184       dev^=DRAW_LIGHTS;
2185       the_game->need_refresh();
2186     } break;
2187     case ID_RECORD_DEMO :
2188     {
2189       if (!mess_win)
2190       {
2191         int h=wm->font()->height()+8;
2192         mess_win=wm->new_window(xres/2,yres/2,-1,-1,
2193             new text_field(0,h*0,ID_RECORD_DEMO_FILENAME,
2194                    "demo filename","*******************",
2195                    "demo.dat",
2196                    new button(10,h*2,ID_RECORD_DEMO_OK,symbol_str("ok_button"),
2197                    new button(40,h*2,ID_CANCEL,symbol_str("cancel_button"),NULL))));
2198       }
2199     } break;
2200 
2201         case ID_RECORD_DEMO_OK :
2202     {
2203       demo_man.set_state(demo_manager::RECORDING,mess_win->read(ID_RECORD_DEMO_FILENAME));
2204       wm->push_event(new event(ID_CANCEL,NULL));        // close window
2205     } break;
2206 
2207     case ID_PLAY_DEMO :
2208     {
2209       if (!mess_win)
2210       {
2211         int h=wm->font()->height()+8;
2212         mess_win=wm->new_window(xres/2,yres/2,-1,-1,
2213             new text_field(0,h*0,ID_PLAY_DEMO_FILENAME,
2214                    "demo filename","*******************",
2215                    "demo.dat",
2216                    new button(10,h*2,ID_PLAY_DEMO_OK,symbol_str("ok_button"),
2217                    new button(40,h*2,ID_CANCEL,symbol_str("cancel_button"),NULL))));
2218       }
2219     } break;
2220 
2221         case ID_PLAY_DEMO_OK :
2222     {
2223       demo_man.set_state(demo_manager::PLAYING,mess_win->read(ID_PLAY_DEMO_FILENAME));
2224       wm->close_window(mess_win);
2225       mess_win=NULL;
2226     } break;
2227 
2228     case ID_SET_SCROLL :
2229     {
2230       if (!mess_win)
2231       {
2232         int h=wm->font()->height()+8;
2233         mess_win=wm->new_window(xres/2,yres/2,-1,-1,
2234             new text_field(0,h*0,ID_MESS_STR1,symbol_str("x_mul"),"****",bg_xmul,
2235             new text_field(0,h*1,ID_MESS_STR2,symbol_str("x_div"),"****",bg_xdiv,
2236             new text_field(0,h*2,ID_MESS_STR3,symbol_str("y_mul"),"****",bg_ymul,
2237             new text_field(0,h*3,ID_MESS_STR4,symbol_str("y_div"),"****",bg_ydiv,
2238                    new button(10,h*4,ID_SET_SCROLL_CHECK,symbol_str("ok_button"),
2239                    new button(40,h*4,ID_CANCEL,symbol_str("cancel_button"),NULL)))))),symbol_str("_scroll"));
2240       }
2241     } break;
2242     case ID_SET_SCROLL_CHECK :
2243     {
2244       int tbg_xmul=atoi(mess_win->read(ID_MESS_STR1));
2245       int tbg_xdiv=atoi(mess_win->read(ID_MESS_STR2));
2246       int tbg_ymul=atoi(mess_win->read(ID_MESS_STR3));
2247       int tbg_ydiv=atoi(mess_win->read(ID_MESS_STR4));
2248 
2249       if ( (((float)tbg_xmul/(float)tbg_xdiv) < ((float)bg_xmul/(float)bg_xdiv)) ||
2250           (((float)tbg_ymul/(float)tbg_ydiv) < ((float)bg_ymul/(float)bg_ydiv)))
2251       {
2252         int h=wm->font()->height()+8;
2253 
2254         warn_win=wm->new_window(xres/2-40,yres/2-40,-1,-1,
2255                   new info_field(0,0,ID_NULL,
2256                       symbol_str("back_loss"),
2257                       new button(10,h*4,ID_SET_SCROLL_OK,symbol_str("ok_button"),
2258                       new button(40,h*4,ID_WARN_CANCEL,symbol_str("cancel_button"),NULL))),
2259                     symbol_str("WARNING"));
2260         wm->grab_focus(warn_win);
2261       } else wm->push_event(new event(ID_SET_SCROLL_OK,NULL));
2262     } break;
2263     case ID_WARN_CANCEL :
2264     {
2265       wm->close_window(warn_win); warn_win=NULL;
2266       wm->push_event(new event(ID_CANCEL,NULL));
2267     } break;
2268     case ID_SET_SCROLL_OK :
2269     {
2270       if (warn_win) { wm->close_window(warn_win); warn_win=NULL; }
2271       bg_xmul=atoi(mess_win->read(ID_MESS_STR1));
2272       bg_xdiv=atoi(mess_win->read(ID_MESS_STR2));
2273       bg_ymul=atoi(mess_win->read(ID_MESS_STR3));
2274       bg_ydiv=atoi(mess_win->read(ID_MESS_STR4));
2275       wm->push_event(new event(ID_CANCEL,NULL));        // close window
2276     } break;
2277 
2278     case ID_CENTER_PLAYER :
2279     {
2280        do_command("center",ev); break;
2281     } break;
2282 
2283     case ID_INTERPOLATE_DRAW :
2284     {
2285       interpolate_draw=!interpolate_draw;
2286     } break;
2287 
2288     case ID_DISABLE_AUTOLIGHT :
2289     {
2290       disable_autolight=!disable_autolight;
2291     } break;
2292 
2293     case ID_ADD_PALETTE :
2294     {
2295       if (!mess_win)
2296       {
2297         int h=wm->font()->height()+8;
2298         mess_win=wm->new_window(xres/2,yres/2,-1,-1,
2299             new text_field(0,h*0,ID_MESS_STR1,symbol_str("ap_width"),"****",2,
2300             new text_field(0,h*1,ID_MESS_STR2,symbol_str("ap_height"),"****",2,
2301             new text_field(0,h*2,ID_MESS_STR3,symbol_str("ap_name"),"***********","pal",
2302                    new button(10,h*3,ID_ADD_PALETTE_OK,symbol_str("ok_button"),
2303                    new button(40,h*3,ID_CANCEL,symbol_str("cancel_button"),NULL))))),symbol_str("ap_pal"));
2304       }
2305     } break;
2306     case ID_ADD_PALETTE_OK :
2307     {
2308       char name[70];
2309       sprintf(name,"(add_palette \"%s\" %d %d)",mess_win->read(ID_MESS_STR3),
2310           atoi(mess_win->read(ID_MESS_STR1)),
2311           atoi(mess_win->read(ID_MESS_STR2)));
2312       char const *s=name;
2313       LObject::Compile(s)->Eval();
2314       wm->push_event(new event(ID_CANCEL,NULL));        // close window
2315     } break;
2316     case ID_TOGGLE_DELAY :
2317     {
2318       the_game->toggle_delay(); break;
2319     } break;
2320 
2321     case ID_SMALL_MODE :
2322     {
2323       make_screen_size(311,160); break;
2324     } break;
2325     case ID_CLEAR_WEAPONS :
2326     {
2327       event ev;
2328       do_command("clear_weapons",ev);
2329     } break;
2330     case ID_GOD_MODE :
2331     {
2332       for (view *v=player_list; v; v=v->next)
2333         v->god=!v->god;
2334     } break;
2335     case ID_MOUSE_SCROLL :
2336     {
2337       mouse_scrolling=!mouse_scrolling;
2338       prop->setd("mouse_scrolling",mouse_scrolling);
2339       if (mouse_scrolling)
2340         the_game->show_help(symbol_str("ms_on"));
2341       else
2342         the_game->show_help(symbol_str("ms_off"));
2343     } break;
2344 
2345     case ID_LOCK_PALETTES :
2346     {
2347       palettes_locked=!palettes_locked;
2348       prop->setd("palettes_locked",palettes_locked);
2349       if (palettes_locked)
2350         the_game->show_help(symbol_str("pal_lock"));
2351       else the_game->show_help(symbol_str("pal_unlock"));
2352     } break;
2353 
2354     case ID_DISABLE_VIEW_SHIFT :
2355     {
2356       view_shift_disabled=!view_shift_disabled;
2357       prop->setd("view_shift_disabled",view_shift_disabled);
2358       if (view_shift_disabled)
2359         the_game->show_help(symbol_str("vs_dis"));
2360       else the_game->show_help(symbol_str("vs_en"));
2361     } break;
2362 
2363     case ID_WIN_FORE :
2364     {
2365       toggle_fgw();
2366     } break;
2367     case ID_WIN_BACK :
2368     {
2369       toggle_bgw();
2370     } break;
2371     case ID_WIN_OBJECTS :
2372     {
2373       toggle_omenu();
2374     } break;
2375     case ID_WIN_PALETTES :
2376     {
2377       toggle_pmenu();
2378     } break;
2379     case ID_WIN_LIGHTING :
2380     {
2381       toggle_light_window();
2382     } break;
2383     case ID_WIN_LAYERS :
2384     {
2385       toggle_show_menu();
2386     } break;
2387     case ID_WIN_CONSOLE :
2388     {
2389       if (dev_console) dev_console->toggle();
2390     } break;
2391     case ID_WIN_TOOLBAR :
2392     {
2393       toggle_toolbar();
2394     } break;
2395 
2396     case DEV_AMBIENT :
2397     { if (!ambw) make_ambient(); } break;
2398     case DEV_AREA_OK :
2399     { close_area_win(1); } break;
2400     case DEV_AREA_DELETE :
2401     { close_area_win(0);
2402       if (current_area && current_level)
2403       {
2404         if (current_level->area_list==current_area)
2405           current_level->area_list=current_level->area_list->next;
2406         else
2407         {
2408           area_controller *a=current_level->area_list,*l=NULL;
2409           for (; a!=current_area && a; a=a->next) { l=a; }
2410           l->next=a->next;
2411           delete a;
2412         }
2413         current_area=NULL;
2414         the_game->need_refresh();
2415       }
2416     } break;
2417     case DEV_AI_OK :
2418       close_ai_window(); break;
2419     case DEV_OEDIT_AI :
2420       make_ai_window(edit_object); break;
2421     case DEV_OBJECTS_DELETE :
2422     {
2423       if (edit_object)
2424       {
2425         for (int i=0; i<edit_object->total_objects(); i++)
2426           edit_object->remove_object(edit_object->get_object(0));
2427         the_game->need_refresh();
2428       }
2429     } break;
2430 
2431     case DEV_LIGHTS_DELETE :
2432     {
2433       if (edit_object)
2434       {
2435         for (int i=0; i<edit_object->total_lights(); i++)
2436           edit_object->remove_light(edit_object->get_light(0));
2437         the_game->need_refresh();
2438       }
2439     } break;
2440 
2441     case DEV_LEDIT_DEL :
2442     {
2443       prop->setd("ledit x",ledit->x);
2444       prop->setd("ledit y",ledit->y);
2445       wm->close_window(ledit); ledit=NULL;
2446       if (current_level)
2447         current_level->remove_light(edit_light);
2448       else
2449         delete_light(edit_light);
2450       edit_light=NULL;
2451       the_game->need_refresh();
2452     } break;
2453     case DEV_LEDIT_OK :
2454     {
2455       edit_light->xshift=atoi(ledit->read(DEV_LEDIT_W));
2456       edit_light->yshift=atoi(ledit->read(DEV_LEDIT_H));
2457       edit_light->inner_radius=atoi(ledit->read(DEV_LEDIT_R1));
2458       edit_light->outer_radius=atoi(ledit->read(DEV_LEDIT_R2));
2459       if (edit_light->outer_radius<=edit_light->inner_radius)
2460       {
2461         edit_light->inner_radius=edit_light->outer_radius-1;
2462         if (edit_light->inner_radius<1)
2463         {
2464           edit_light->inner_radius=1;
2465           edit_light->outer_radius=2;
2466         }
2467       }
2468 
2469       edit_light->calc_range();
2470       edit_light=NULL;
2471       prop->setd("ledit x",ledit->x);
2472       prop->setd("ledit y",ledit->y);
2473       wm->close_window(ledit); ledit=NULL;
2474       the_game->need_refresh();
2475     } break;
2476     case DEV_LEDIT_MOVE :
2477     {
2478       prop->setd("ledit x",ledit->x);
2479       prop->setd("ledit y",ledit->y);
2480       wm->close_window(ledit); ledit=NULL;
2481       state=DEV_MOVE_LIGHT;
2482     } break;
2483     case DEV_LEDIT_COPY :
2484     {
2485       edit_light=edit_light->copy();
2486       prop->setd("ledit x",ledit->x);
2487       prop->setd("ledit y",ledit->y);
2488       wm->close_window(ledit); ledit=NULL;
2489       state=DEV_MOVE_LIGHT;
2490     } break;
2491 
2492 
2493     case DEV_LIGHT0 :
2494     case DEV_LIGHT1 :
2495     case DEV_LIGHT2 :
2496     case DEV_LIGHT3 :
2497     case DEV_LIGHT4 :
2498     case DEV_LIGHT5 :
2499     case DEV_LIGHT6 :
2500     case DEV_LIGHT7 :
2501     case DEV_LIGHT8 :
2502     case DEV_LIGHT9 :
2503     {
2504       int32_t lx,ly;
2505       the_game->mouse_to_game(last_demo_mx,last_demo_my,lx,ly);
2506       lx=snap_x(lx);
2507       ly=snap_y(ly);
2508       edit_light=add_light_source(ev.message.id-DEV_LIGHT0,lx,ly,
2509                        atoi(lightw->read(DEV_LIGHTR1)),
2510                        atoi(lightw->read(DEV_LIGHTR2)),
2511                        atoi(lightw->read(DEV_LIGHTW)),
2512                        atoi(lightw->read(DEV_LIGHTH)));
2513       state=DEV_MOVE_LIGHT;
2514     } break;
2515     case ID_RAISE_ALL :
2516     {
2517       raise_all=!raise_all;
2518       prop->setd("raise_all",raise_all);
2519       if (raise_all)
2520         the_game->show_help(symbol_str("fg_r"));
2521       else
2522         the_game->show_help(symbol_str("fg_l"));
2523     } break;
2524     case DEV_OEDIT_COPY :
2525     {
2526       game_object *use=copy_object;
2527       if (!use) use=edit_object;
2528       if (use)
2529       {
2530         game_object *old=use;
2531         close_oedit_window();
2532         if (use->controller())
2533           the_game->show_help(symbol_str("no_clone"));
2534         else
2535         {
2536           edit_object=old->copy();
2537 
2538           current_level->add_object(edit_object);
2539           the_game->need_refresh();
2540           state=DEV_MOVE_OBJECT;
2541 
2542           close_oedit_window();
2543           copy_object=NULL;
2544         }
2545       }
2546     } break;
2547     case DEV_OEDIT_LEFT :
2548     {
2549       if (edit_object)
2550       {
2551         the_game->need_refresh();
2552         edit_object->direction=-1;
2553       }
2554     } break;
2555     case DEV_OEDIT_RIGHT :
2556     {
2557       if (edit_object)
2558       {
2559         the_game->need_refresh();
2560         edit_object->direction=1;
2561       }
2562     } break;
2563 
2564 
2565     case DEV_COMMAND_OK :
2566     {
2567       char cmd[100];
2568       strcpy(cmd,commandw->inm->get(DEV_COMMAND)->read());
2569       prop->setd("commandw x",commandw->x);
2570       prop->setd("commandw y",commandw->y);
2571       wm->close_window(commandw);
2572       commandw=NULL;
2573       do_command(cmd,ev);
2574     } break;
2575 
2576     case ID_SHOW_FPS :
2577     { fps_on=!fps_on; } break;
2578     case ID_PROFILE :
2579     { profile_toggle();
2580       profile_on=!profile_on;
2581     } break;
2582 
2583     case ID_TOGGLE_NAMES : { show_names=!show_names; } break;
2584     case DEV_QUIT : the_game->end_session(); break;
2585     case DEV_EDIT_FG : dev=1; break; //the_game->draw(); break;
2586     case DEV_EDIT_BG : dev=2; break; //the_game->draw(); break;
2587     case DEV_EDIT_FGBG : dev=3; break; //the_game->draw(); break;
2588     case DEV_PLAY : dev=0; break; //the_game->draw(); break;
2589     case SHOW_FOREGROUND :
2590     { dev=dev^DRAW_FG_LAYER; the_game->need_refresh(); } break;
2591     case SHOW_FOREGROUND_BOUND :
2592     { dev=dev^DRAW_FG_BOUND_LAYER; the_game->need_refresh(); } break;
2593     case SHOW_BACKGROUND :
2594     { dev=dev^DRAW_BG_LAYER; the_game->need_refresh(); } break;
2595     case SHOW_CHARACTERS :
2596     { dev=dev^DRAW_PEOPLE_LAYER; the_game->need_refresh(); } break;
2597     case SHOW_LIGHT :
2598     { dev=dev^DRAW_LIGHTS; the_game->need_refresh(); } break;
2599     case SHOW_LINKS :
2600     { dev=dev^DRAW_LINKS;  the_game->need_refresh(); } break;
2601 
2602 
2603     case DEV_CREATE :
2604     {
2605       int val=get_omenu_item(((pick_list *)ev.message.data)->get_selection());
2606       char cmd[100];
2607       sprintf(cmd,"create %s",object_names[val]);
2608       do_command(cmd,ev);
2609       state=DEV_CREATE_OBJECT;
2610       dev|=(EDIT_MODE | DRAW_PEOPLE_LAYER);
2611     }
2612     break;
2613 
2614     case DEV_PALETTE :
2615     {
2616       int val=((pick_list *)ev.message.data)->get_selection();
2617       pal_wins[val]->open_window();
2618     } break;
2619 
2620     case DEV_MUSIC_PICKLIST :
2621     {
2622 /*        int *val=((int *)((pick_list *)ev.message.data)->read());
2623         if (current_song) delete current_song;
2624         current_song=new song(song_list[*val]);
2625         current_song->play();        */
2626     }
2627     break;
2628 
2629     case DEV_OEDIT_OK :
2630     { close_oedit_window(); } break;
2631 
2632     case DEV_OEDIT_DELETE :
2633     {
2634       selected_object=edit_object;
2635       do_command("delete",ev);
2636       close_oedit_window();
2637     }
2638     break;
2639 
2640     case DEV_OEDIT_FRONT :
2641     {
2642       do_command("to_front",ev);
2643       close_oedit_window();
2644     }
2645     break;
2646 
2647     case DEV_OEDIT_BACK :
2648     {
2649       do_command("to_back",ev);
2650       close_oedit_window();
2651     }
2652     break;
2653 
2654     case DEV_OEDIT_MOVE :
2655     {
2656       game_object *o=edit_object;
2657       close_oedit_window();
2658       edit_object=o;
2659       do_command("move",ev);
2660     }
2661     break;
2662       }
2663     } break;
2664 
2665 
2666     case EV_CLOSE_WINDOW :
2667     {
2668       if (ev.window)
2669       {
2670     if (ev.window==commandw)
2671     {
2672       prop->setd("commandw x",commandw->x);
2673       prop->setd("commandw y",commandw->y);
2674       wm->close_window(commandw);
2675       commandw=NULL;
2676     } else if (ev.window==oedit)
2677       close_oedit_window();
2678     else if (ev.window==ambw)
2679     { wm->close_window(ambw); ambw=NULL; }
2680     else if (ev.window==backw) toggle_bgw();
2681     else if (ev.window==forew) toggle_fgw();
2682     else if (ev.window==lightw) toggle_light_window();
2683     else if (ev.window==show_menu) toggle_show_menu();
2684     else if (ev.window==pmenu) toggle_pmenu();
2685     else if (ev.window==tbw) toggle_toolbar();
2686     else if (ev.window==omenu) toggle_omenu();
2687     else if (ev.window==search_window) toggle_search_window();
2688     else if (profile_handle_event(ev))  profile_on=!profile_on;
2689     else if (chat->chat_event(ev)) chat->toggle();
2690 
2691       }
2692     }
2693     break;
2694     case EV_KEYRELEASE :
2695     {
2696       if (ev.key==JK_CTRL_L)
2697       {
2698         if (!edit_object && link_object && selected_object && link_object!=selected_object)
2699     {
2700       link_object->add_object(selected_object);
2701       if (S_LINK_SND>0) cache.sfx(S_LINK_SND)->play(sfx_volume/2);
2702       the_game->need_refresh();
2703     }
2704 
2705     link_object=NULL;
2706       }
2707     } break;
2708     case EV_KEY :
2709     {
2710       if (backw && ev.window==backw)
2711       { if (ev.key=='-' && bg_scale<the_game->btile_height()/2)
2712     { toggle_bgw();
2713       bg_scale++;
2714       toggle_bgw();
2715     } else if (ev.key=='+' && bg_scale>1)
2716     { toggle_bgw();
2717       bg_scale--;
2718       toggle_bgw();
2719     } else if (ev.key=='b') toggle_bgw();
2720     else if (ev.key=='B') { toggle_bgw(); bg_w++; if (bg_w>6) bg_w=1; toggle_bgw(); }
2721       }
2722       if (forew && ev.window==forew)
2723       { if (ev.key=='-' && fg_scale<the_game->ftile_height()/2)
2724     { toggle_fgw();
2725       fg_scale++;
2726       toggle_fgw();
2727     } else if (ev.key=='+' && fg_scale>1)
2728     { toggle_fgw();
2729       fg_scale--;
2730       toggle_fgw();
2731     } else if (ev.key=='i')
2732     {
2733       toggle_fgw();
2734       fg_reversed=!fg_reversed;
2735       prop->setd("fg_reversed",fg_reversed);
2736       toggle_fgw();
2737     } else if (ev.key=='f') toggle_fgw();
2738 
2739     else if (ev.key=='F') { toggle_fgw(); fg_w++; if (fg_w>6) fg_w=1; toggle_fgw(); }
2740       }
2741       if (ev.window==NULL || ev.window==pmenu ||
2742       ev.window==forew || is_pal_win(ev.window))  // main window actions
2743       {
2744     switch (ev.key)
2745     {
2746       case JK_CTRL_L : if (!edit_object && !link_object) { link_object=selected_object; }
2747       case 'n' : current_level->next_focus(); break;
2748 //      case '/' : if (dev_console) dev_console->toggle(); break;
2749       case 't' :
2750       {
2751         if (ev.window==NULL || ev.window==forew)
2752         {
2753           the_game->ftile_on(last_demo_mx,last_demo_my,x,y);
2754           fg_fill(cur_fg,x,y,NULL);
2755         }
2756       } break;
2757       case 'f' : toggle_fgw(); break;
2758       case 'M' : toggle_music_window(); break;
2759 
2760       case 'b' : toggle_bgw(); break;
2761       case 'a' : toggle_toolbar(); break;
2762       case 'A' : { if (selected_object)
2763                {
2764              if (oedit) wm->push_event(new event(DEV_OEDIT_OK,NULL));
2765              make_ai_window(selected_object);
2766                }
2767              } break;
2768 
2769       case 'o' : toggle_omenu(); break;
2770 
2771       case '<' : do_command("to_back",ev); break;
2772 
2773       case '>' : do_command("to_front",ev); break;
2774       case 'p' : toggle_pmenu(); break;
2775       case 'P' : profile_toggle(); break;
2776       case '.' :
2777       {
2778         if (last_created_type>=0)
2779         {
2780           int val=last_created_type;
2781           char cmd[100];
2782           sprintf(cmd,"create %s",object_names[val]);
2783           do_command(cmd,ev);
2784           state=DEV_CREATE_OBJECT;
2785           dev|=(EDIT_MODE | DRAW_PEOPLE_LAYER);
2786         }
2787       }
2788       break;
2789 
2790 
2791       case 'd' : { do_command("delete",ev);  the_game->need_refresh(); } break;
2792       case 'i' :
2793       {
2794         fg_reversed=!fg_reversed;
2795         prop->setd("fg_reversed",fg_reversed);
2796         if (forew)
2797         {
2798           toggle_fgw();
2799           toggle_fgw();
2800         }
2801       } break;
2802       case 'l' : toggle_light_window(); break;
2803       case '!' :
2804       case '@' :
2805       case '#' :
2806       case '$' :
2807       case '%' :
2808       case '^' :
2809       case '&' :
2810       case '*' :
2811       case '(' :
2812       case ')' :
2813 
2814       case '0' :
2815       case '1' :
2816       case '2' :
2817       case '3' :
2818       case '4' :
2819       case '5' :
2820       case '6' :
2821       case '7' :
2822       case '8' :
2823       case '9' : do_command("set_aitype",ev); break;
2824       case 'c' : do_command("center",ev); break;
2825       case 'C' :
2826       if (selected_object && selected_object->controller()==NULL)
2827       { copy_object=selected_object;
2828             wm->push_event(new event(DEV_OEDIT_COPY,NULL)); } break;
2829 
2830       case 'D' : the_game->toggle_delay(); break;
2831       case 'L' : toggle_show_menu(); break;
2832       case '`' : do_command("fg_select",ev); break;
2833       case 'r' : { do_command("toggle_fg_raise",ev); the_game->need_refresh(); }  break;
2834       case '[' : do_command("fg_add -1",ev); break;
2835       case ']' : do_command("fg_add 1",ev); break;
2836       case 'R' : do_command("reload",ev); break;
2837       case 'w' :
2838       {
2839         int32_t rx,ry;
2840         the_game->mouse_to_game(dlastx,dlasty,rx,ry);
2841         char msg[100]; sprintf(msg,symbol_str("mouse_at"),rx,ry);
2842         the_game->show_help(msg);
2843         the_game->need_refresh();
2844       } break;
2845       case 'k' :
2846       {
2847         if (selected_object && selected_object->total_objects())
2848           selected_object->remove_object(selected_object->get_object(0));
2849         the_game->need_refresh();
2850       } break;
2851       case 'K' :
2852       {
2853         if (selected_object && selected_object->total_objects())
2854           selected_object->remove_object(selected_object->get_object(selected_object->total_objects()-1));
2855         the_game->need_refresh();
2856       } break;
2857       case 'j' :
2858       {
2859         if (current_level && player_list && player_list->focus)
2860         {
2861           int32_t rx,ry;
2862           the_game->mouse_to_game(dlastx,dlasty,rx,ry);
2863           player_list->focus->x=rx;
2864           player_list->focus->y=ry;
2865           do_command("center",ev);
2866           the_game->need_refresh();
2867         }
2868       } break;
2869       case 'z' : do_command("clear_weapons",ev); break;
2870       case 'Z' : if (dev&EDIT_MODE)
2871       { view *v=the_game->view_in(last_demo_mx,last_demo_my);
2872         if (v)
2873         {
2874           v->god=!v->god;
2875           sbar.redraw(screen);
2876         }
2877       } break;
2878       case ' ' :
2879       {
2880         if (dev & EDIT_MODE)
2881         {
2882           if (selected_object)
2883           {
2884         if (oedit)
2885           close_oedit_window();
2886         edit_object=selected_object;
2887         do_command("move",ev);
2888           } else if (selected_light)
2889           {
2890         if (ledit)
2891         {
2892           wm->close_window(ledit);
2893           ledit=NULL;
2894         }
2895         edit_light=selected_light;
2896         do_command("move_light",ev);
2897           }
2898 
2899         } break;
2900       }
2901       case 'x' :
2902       {
2903         if (selected_object)
2904         { if (selected_object->direction>0)
2905           selected_object->direction=-1;
2906         else selected_object->direction=1;
2907         }
2908       } break;
2909 
2910     }
2911       }
2912     }
2913   }
2914 
2915 
2916 }
2917 
2918 
add_palette(void * args)2919 void dev_controll::add_palette(void *args)
2920 {
2921   total_pals++;
2922   pal_wins=(pal_win **)realloc(pal_wins,sizeof(pal_win *)*total_pals);
2923   pal_wins[total_pals-1]=new pal_win(args);
2924 }
2925 
2926 
pal_win(void * args)2927 pal_win::pal_win(void *args)
2928 {
2929   int i=0;
2930   Cell *ao=(Cell *)args;
2931 
2932   name = strdup(lstring_value(CAR(args)));
2933   ao=CDR(ao);
2934   scale=w=h=1;
2935   x=y=0;
2936 
2937   if (!NILP(ao))
2938   {
2939     w=lnumber_value(CAR(ao)); ao=CDR(ao);
2940     if (!NILP(ao))
2941     {
2942       h=lnumber_value(CAR(ao)); ao=CDR(ao);
2943       if (!NILP(ao))
2944       {
2945     x=lnumber_value(CAR(ao)); ao=CDR(ao);
2946     if (!NILP(ao))
2947     {
2948       y=lnumber_value(CAR(ao)); ao=CDR(ao);
2949       if (!NILP(ao))
2950         scale=lnumber_value(CAR(ao)); ao=CDR(ao);
2951     }
2952       }
2953     }
2954   }
2955 
2956   if (w<=0) w=0;
2957   if (h<=0) h=0;
2958 
2959   pat=(unsigned short *)malloc(w*h*sizeof(unsigned short));
2960   memset(pat,0,sizeof(unsigned short)*w*h);   // set the palette to black if no parameters are given
2961   while (!NILP(ao))   // loop until we run out of parameters
2962   {
2963     if (i>w*h)
2964     {
2965       lbreak("to many parameters to add_palette ");
2966       exit(0);
2967     }
2968     pat[i]=lnumber_value(CAR(ao));
2969     // make sure the tile that they suggested exists
2970     if (pat[i]<=0 || pat[i]>nforetiles || foretiles[pat[i]]<0)
2971       pat[i]=0;
2972     ao=CDR(ao);
2973     i++;
2974   }
2975   last_selected=-1;
2976   me=NULL;
2977   open_window();
2978 }
2979 
open_window()2980 void pal_win::open_window()
2981 {
2982   if (me) close_window();
2983   me=wm->new_window(x,y,w*f_wid/scale,h*f_hi/scale,NULL,name);
2984   draw();
2985 }
2986 
close_window()2987 void pal_win::close_window()
2988 {
2989   if (me)       // dont' close the window if the window is already closed
2990   {
2991     x=me->x;    //  save the old poisition of the window so that when we  open it
2992                 //  it will be in the same spot
2993     y=me->y;
2994     wm->close_window(me);
2995     me=NULL;
2996 
2997   }
2998 }
2999 
draw()3000 void pal_win::draw()
3001 {
3002   int i,find=-1,d=cur_fg;
3003   if (me)
3004   {
3005     me->clear();
3006     image *im=new image(vec2i(the_game->ftile_width(),the_game->ftile_height()));
3007     int th=the_game->ftile_height()/scale,tw=the_game->ftile_width()/scale;
3008 
3009     for (i=0; i<w*h; i++)
3010     {
3011       im->clear();
3012       the_game->get_fg(pat[i])->im->PutImage(im,vec2i(0,0));
3013       scale_put(im,me->screen,me->x1()+(i%w)*tw,
3014         me->y1()+(i/w)*th,tw,th);
3015       if (d==pat[i])
3016       {
3017     find=i;
3018     me->screen->rectangle(me->x1()+(i%w)*tw,
3019               me->y1()+(i/w)*th,
3020               me->x1()+(i%w)*tw+tw-1,
3021               me->y1()+(i/w)*th+th-1,wm->bright_color());
3022       }
3023     }
3024     delete im;
3025     last_selected=d;
3026   }
3027 }
3028 
handle_event(event & ev)3029 void pal_win::handle_event(event &ev)
3030 {
3031   int d=cur_fg;
3032 
3033   if (d!=last_selected)  // if so see if we need to hilight any of our tiles.
3034   {
3035     int i,dr=0;
3036     for (i=0; i<w*h; i++)
3037     {
3038       if (pat[i]==d || pat[i]==last_selected)
3039         dr=1;
3040     }
3041     if (dr) draw();
3042     last_selected=d;
3043   }
3044 
3045   if (ev.window && ev.window==me)
3046   {
3047     switch (ev.type)
3048     {
3049       case EV_MOUSE_BUTTON :
3050       {
3051         if (ev.mouse_button==1)
3052     {
3053       int selx=(last_demo_mx-me->x-me->x1())/(the_game->ftile_width()/scale),
3054           sely=(last_demo_my-me->y-me->y1())/(the_game->ftile_height()/scale);
3055       if (selx>=0 && sely>=0 && selx<w && sely<h)
3056       {
3057         cur_fg=pat[selx+sely*w];
3058         if (dev_cont->forew)
3059           ((tile_picker *)dev_cont->forew->
3060            read(DEV_FG_PICKER))->recenter(dev_cont->forew->screen);
3061       }
3062     } else if (ev.mouse_button==2)
3063     {
3064       if (palettes_locked)
3065         the_game->show_help(symbol_str("pal_lock"));
3066       else
3067       {
3068         int selx=(last_demo_mx-me->x-me->x1())/(the_game->ftile_width()/scale),
3069             sely=(last_demo_my-me->y-me->y1())/(the_game->ftile_height()/scale);
3070         if (selx>=0 && sely>=0 && selx<w && sely<h)
3071         {
3072           pat[selx+sely*w]=cur_fg;
3073           draw();
3074         }
3075       }
3076     }
3077       } break;
3078 
3079       case EV_KEY :
3080       {
3081         switch (ev.key)
3082     {
3083       case '+' :
3084       { if (scale>1)
3085         {
3086           close_window();
3087           scale--;
3088           open_window();
3089         }
3090       } break;
3091       case '-' :
3092       { if (scale<the_game->ftile_height()/2)
3093         {
3094           close_window();
3095           scale++;
3096           open_window();
3097         }
3098       } break;
3099       case JK_LEFT :
3100       {
3101         if (palettes_locked) the_game->show_help(symbol_str("pal_lock"));
3102         else if (w>1) resize(-1,0);
3103       } break;
3104       case JK_RIGHT :
3105       {
3106         if (palettes_locked) the_game->show_help(symbol_str("pal_lock"));
3107         else
3108           resize(1,0);
3109       } break;
3110       case JK_UP :
3111       {
3112         if (palettes_locked) the_game->show_help(symbol_str("pal_lock"));
3113         else if (h>1) resize(0,-1);
3114       } break;
3115       case JK_DOWN :
3116       {
3117         if (palettes_locked)
3118           the_game->show_help(symbol_str("pal_lock"));
3119         else
3120           resize(0,1);
3121       } break;
3122       case JK_ESC : close_window();     break;
3123       case ' ' :
3124       {
3125         int32_t xs,ys,xx,yy;
3126         the_game->ftile_on(me->x,me->y,xs,ys);
3127 
3128         for (xx=xs; xx<xs+w; xx++)
3129         {
3130           for (yy=ys; yy<ys+h; yy++)
3131           {
3132         if (xx>=0 && yy>=0 && xx<current_level->foreground_width() &&
3133             yy<current_level->foreground_height())
3134           the_game->put_fg(xx,yy,raise_all ? make_above_tile(pat[xx-xs+(yy-ys)*w]) : pat[xx-xs+(yy-ys)*w] );
3135           }
3136         }
3137       } break;
3138       case 't' :
3139       {
3140         int32_t xs,ys;
3141         the_game->ftile_on(me->x,me->y,xs,ys);
3142         dev_cont->fg_fill(-1,xs,ys,this);
3143       } break;
3144 
3145     }
3146       } break;
3147 
3148       case EV_CLOSE_WINDOW : close_window(); break;
3149     }
3150   }
3151 
3152 
3153 }
3154 
3155 
resize(int xa,int ya)3156 void pal_win::resize(int xa, int ya)
3157 {
3158   int i,j;
3159   unsigned short *npat;
3160   if (w+xa<1 || y+ya<1) return ;
3161 
3162   npat=(unsigned short *)malloc(sizeof(unsigned short)*(w+xa)*(h+ya));
3163   memset(npat,0,sizeof(unsigned short)*(w+xa)*(h+ya));
3164   for (i=0; i<(w+xa); i++)
3165     for (j=0; j<(h+ya); j++)
3166       if (i+j*w<w*h)
3167         npat[i+j*(w+xa)]=pat[i+j*w];
3168   free(pat);
3169   w+=xa;
3170   h+=ya;
3171   pat=npat;
3172   last_selected=-1;
3173   close_window();
3174   open_window();
3175 }
3176 
3177 
save(FILE * fp)3178 void pal_win::save(FILE *fp)
3179 {
3180   if (me)
3181   {
3182     x=me->x;
3183     y=me->y;
3184   }
3185 
3186   fprintf(fp,"(add_palette \"%s\" %ld %ld %ld %ld %ld ",name,(long)w,(long)h,(long)x,(long)y,(long)scale);
3187   int i;
3188   for (i=0; i<w*h; i++)
3189     fprintf(fp,"%d ",pat[i]&0x7fff);
3190   fprintf(fp,")\n");
3191 
3192 }
3193 
save()3194 void dev_controll::save()
3195 {
3196   FILE *fp=open_FILE("edit.lsp","w");
3197   if (!fp)
3198     the_game->show_help(symbol_str("no_edit.lsp"));
3199   else
3200   {
3201     fprintf(fp,"(set_zoom %d)\n",the_game->zoom);
3202 
3203     int i;
3204     for (i=0; i<total_pals; i++)
3205     {
3206       pal_wins[i]->save(fp);
3207     }
3208     fprintf(fp,"\n");
3209     fclose(fp);
3210   }
3211 
3212 }
3213 
is_pal_win(Jwindow * win)3214 int dev_controll::is_pal_win(Jwindow *win)
3215 {
3216   int i;
3217   for (i=0; i<total_pals; i++)
3218     if (win==pal_wins[i]->me) return 1;
3219   return 0;
3220 }
3221 
3222 
3223 class fill_rec
3224 {
3225 public :
3226   short x,y;
3227   fill_rec *last;
fill_rec(short X,short Y,fill_rec * Last)3228   fill_rec(short X, short Y, fill_rec *Last)
3229   { x=X; y=Y; last=Last; }
3230 } ;
3231 
get_color(int color,int x,int y,pal_win * p)3232 static int get_color(int color, int x, int y, pal_win *p)
3233 {
3234   if (p)
3235   {
3236     while (x<0) x+=p->width();
3237     while (y<0) y+=p->height();
3238     return p->get_pat(x%p->width(),y%p->height());
3239   }
3240   else return color;
3241 }
3242 
fg_fill(int color,int x,int y,pal_win * p)3243 void dev_controll::fg_fill(int color, int x, int y, pal_win *p)
3244 {
3245   unsigned short *sl,*above,*below;
3246   fill_rec *recs=NULL,*r;
3247   unsigned short fcolor;
3248   sl=current_level->get_fgline(y);
3249   fcolor=fgvalue(sl[x]);
3250   int startx=x,starty=y;
3251   if (fcolor==color) return ;
3252   do
3253   {
3254     if (recs)
3255     { r=recs;
3256       recs=recs->last;
3257       x=r->x; y=r->y;
3258       delete r;
3259     }
3260     sl=current_level->get_fgline(y);
3261     if (fgvalue(sl[x])==fcolor)
3262     {
3263       while (x>0 && fgvalue(sl[x])==fcolor) x--;
3264       if (fgvalue(sl[x])!=fgvalue(fcolor) && x<current_level->foreground_width()-1) x++;
3265       if (y>0)
3266       {
3267         above=current_level->get_fgline(y-1);
3268         if (fgvalue(above[x])==fcolor)
3269         { r=new fill_rec(x,y-1,recs);
3270           recs=r;
3271         }
3272       }
3273       if (y<current_level->foreground_height()-1)
3274       {
3275         above=current_level->get_fgline(y+1);
3276         if (above[x]==fcolor)
3277         { r=new fill_rec(x,y+1,recs);
3278           recs=r;
3279         }
3280       }
3281 
3282 
3283 
3284       do
3285       {
3286         sl[x]=get_color(color,x-startx,y-starty,p);
3287         if (y>0)
3288         { above=current_level->get_fgline(y-1);
3289           if (x>0 && fgvalue(above[x-1])!=fgvalue(fcolor) && fgvalue(above[x])==fgvalue(fcolor))
3290           { r=new fill_rec(x,y-1,recs);
3291             recs=r;
3292           }
3293         }
3294         if (y<current_level->foreground_height()-1)
3295         { below=current_level->get_fgline(y+1);
3296           if (x>0 && fgvalue(below[x-1])!=fgvalue(fcolor) && fgvalue(below[x])==fgvalue(fcolor))
3297           { r=new fill_rec(x,y+1,recs);
3298             recs=r;
3299           }
3300         }
3301         x++;
3302       } while (fgvalue(sl[x])==fgvalue(fcolor) && x<current_level->foreground_width());
3303       x--;
3304       if (y>0)
3305       {
3306         above=current_level->get_fgline(y-1);
3307         if (fgvalue(above[x])==fgvalue(fcolor))
3308         { r=new fill_rec(x,y-1,recs);
3309           recs=r;
3310         }
3311       }
3312       if (y<current_level->foreground_height()-1)
3313       {
3314         above=current_level->get_fgline(y+1);
3315         if (fgvalue(above[x])==fgvalue(fcolor))
3316         { r=new fill_rec(x,y+1,recs);
3317           recs=r;
3318         }
3319       }
3320     }
3321   } while (recs);
3322   the_game->need_refresh();
3323 }
3324 
get_char_mem(int type,int print)3325 static int get_char_mem(int type, int print)
3326 {
3327   int t=0;
3328   for (int j=0; j<MAX_STATE; j++)
3329   {
3330     if (figures[type]->has_sequence((character_state)j))
3331     {
3332       int s=figures[type]->get_sequence((character_state)j)->MemUsage();
3333       if (print)
3334         dprintf("(%s=%d)",state_names[j],s);
3335       t+=s;
3336     }
3337   }
3338   if (print)
3339     dprintf("\ntotal=%d\n",t);
3340   return t;
3341 }
3342 
show_char_mem(char const * name)3343 void dev_controll::show_char_mem(char const *name)
3344 {
3345   int find=-1;
3346   for (int i=0; i<total_objects; i++)
3347   {
3348     if (!strcmp(name,object_names[i]))
3349       find=i;
3350   }
3351   if (find<0)
3352     dprintf("No character '%s' defined\n",name);
3353   else
3354     get_char_mem(find,1);
3355 
3356 }
3357 
show_mem()3358 void dev_controll::show_mem()
3359 {
3360   int t=0,s=0;
3361   int i=0;
3362   for (; i<nforetiles; i++)
3363   {
3364     if (foretiles[i]>=0)
3365     {
3366       if (cache.loaded(foretiles[i]))
3367       {
3368     t++;
3369     s+=cache.foret(foretiles[i])->size();
3370       }
3371     }
3372   }
3373   dprintf("%d loaded foretiles=%d bytes\n",t,s);
3374 
3375   t=0; s=0;
3376   for (i=0; i<nbacktiles; i++)
3377   {
3378     if (backtiles[i]>=0)
3379     {
3380       if (cache.loaded(foretiles[i]))
3381       {
3382     t++;
3383     s+=cache.backt(backtiles[i])->size();
3384       }
3385     }
3386   }
3387   dprintf("%d loaded backtiles=%d bytes\n",t,s);
3388 
3389   t=0; s=0;
3390   for (i=0; i<total_objects; i++)
3391   {
3392     t++;
3393     s+=get_char_mem(i,0);
3394   }
3395   dprintf("%d character=%d bytes\n",t,s);
3396 
3397 }
3398 
3399 
3400 
dev_cleanup()3401 void dev_cleanup()
3402 {
3403   if (start_edit)
3404     prop->save("defaults.prp");
3405   delete prop;
3406   if (listable_objs)
3407   {
3408     free(listable_objs);
3409     listable_objs=NULL;
3410   }
3411   crc_manager.clean_up();
3412 
3413 }
3414 
3415 
3416 
3417 struct pmi
3418 {
3419   char const *name;
3420   int id;
3421   char const *on_off;
3422   int key;
3423 } ;
3424 
3425 
3426 static pmi filemenu[]={
3427           { "menu1_load",         ID_LEVEL_LOAD,NULL,-1},
3428       { NULL,0,NULL,-1},
3429       { "menu1_save",     ID_LEVEL_SAVE,NULL,-1},
3430       { "menu1_saveas",      ID_LEVEL_SAVEAS,NULL,-1},
3431       { "menu1_savegame",          ID_GAME_SAVE,NULL,-1},
3432       { "menu1_new",          ID_LEVEL_NEW,NULL,-1},
3433       { "menu1_resize",         ID_LEVEL_RESIZE,NULL,-1},
3434       { NULL,0,NULL,-1},
3435       { "menu1_suspend",ID_SUSPEND,NULL,-1},
3436       { "menu1_toggle",ID_PLAY_MODE,NULL,-1},
3437       { NULL,0,NULL,-1},
3438       { "menu1_savepal",ID_EDIT_SAVE,NULL,-1},
3439 //      { "menu1_startc",ID_CACHE_PROFILE,NULL,-1},
3440 //      { "menu1_endc",ID_CACHE_PROFILE_END,NULL,-1},
3441       { NULL,0,NULL,-1},
3442       { "menu1_quit",      ID_QUIT,NULL,-1},
3443       { NULL,-1,NULL,-1}
3444     };
3445 
3446 
3447 static pmi editmenu[]={
3448   { "menu2_light",               ID_TOGGLE_LIGHT,NULL,-1},
3449   { "menu2_scroll",            ID_SET_SCROLL,NULL,-1},
3450   { "menu2_center",       ID_CENTER_PLAYER,NULL,-1},
3451   { "menu2_addpal",                ID_ADD_PALETTE,NULL,-1},
3452   { "menu2_delay",          ID_TOGGLE_DELAY,NULL,-1},
3453 
3454   { "menu2_god",                   ID_GOD_MODE,NULL,-1},
3455   { "menu2_clear",          ID_CLEAR_WEAPONS,NULL,-1},
3456   { "menu2_mscroll",               ID_MOUSE_SCROLL,&mouse_scrolling,-1},
3457   { "menu2_lock",       ID_LOCK_PALETTES,&palettes_locked,-1},
3458   { "menu2_raise",       ID_RAISE_ALL,&raise_all,-1},
3459   { "menu2_names",        ID_TOGGLE_NAMES,&show_names,-1},
3460 
3461   { NULL,0,NULL,-1},
3462   { "menu2_map",      ID_TOGGLE_MAP,NULL,-1},
3463 //  { "Shrink to 320x200 (F10)",    ID_SMALL_MODE,NULL,-1},
3464   { "menu2_view",        ID_DISABLE_VIEW_SHIFT,&view_shift_disabled,-1},
3465 //  { "Ultra Smooth draw (U)",      ID_INTERPOLATE_DRAW,  &interpolate_draw,'U'},
3466   { "menu2_alight",      ID_DISABLE_AUTOLIGHT, &disable_autolight,'A'},
3467   { "menu2_fps",         ID_SHOW_FPS,          &fps_on,-1},
3468 //  { NULL,0,NULL,-1},
3469 //  { "Record demo",                ID_RECORD_DEMO,NULL,-1},
3470 //  { "Play demo",                  ID_PLAY_DEMO,NULL,-1},
3471   { NULL,-1,NULL,-1}
3472 };
3473 
3474 
3475 
3476 // Window Menus
3477 static pmi winmenu[]={
3478           { "menu3_fore",    ID_WIN_FORE,    &forew_on,-1},
3479           { "menu3_back",    ID_WIN_BACK,    &backw_on,-1},
3480           { "menu3_layers",    ID_WIN_LAYERS,  &show_menu_on,-1},
3481       { "menu3_light",    ID_WIN_LIGHTING,&ledit_on,-1},
3482       { "menu3_pal",    ID_WIN_PALETTES,&pmenu_on,-1},
3483       { "menu3_objs",    ID_WIN_OBJECTS, &omenu_on,-1},
3484 //      { "menu3_console",    ID_WIN_CONSOLE, &commandw_on,-1},
3485       { "menu3_toolbar",    ID_WIN_TOOLBAR, &tbw_on,-1},
3486 //      { "Search      (s)",    ID_SEARCH,      &searchw_on,-1},
3487       { "menu3_prof",    ID_PROFILE,     &profile_on,-1},
3488       { "menu3_save",     ID_SAVE_WINDOWS,NULL,-1},
3489       { NULL,-1,NULL,-1}
3490     };
3491 
3492 
3493 
3494 /*
3495 static pmi filemenu[]={
3496           { "Load Level",         ID_LEVEL_LOAD,NULL,-1},
3497       { NULL,0,NULL,-1},
3498       { "Save Level (S)",     ID_LEVEL_SAVE,NULL,-1},
3499       { "Save level as",      ID_LEVEL_SAVEAS,NULL,-1},
3500       { "Save game",          ID_GAME_SAVE,NULL,-1},
3501       { "New level",          ID_LEVEL_NEW,NULL,-1},
3502       { "Resize map",         ID_LEVEL_RESIZE,NULL,-1},
3503       { NULL,0,NULL,-1},
3504       { "Suspend non-players",ID_SUSPEND,NULL,-1},
3505       { "Play mode toggle (TAB)",ID_PLAY_MODE,NULL,-1},
3506       { NULL,0,NULL,-1},
3507       { "Save Palettes         ",ID_EDIT_SAVE,NULL,-1},
3508       { "Start cache profile   ",ID_CACHE_PROFILE,NULL,-1},
3509       { "End cache profile     ",ID_CACHE_PROFILE_END,NULL,-1},
3510       { NULL,0,NULL,-1},
3511       { "Quit      (Q)",      ID_QUIT,NULL,-1},
3512       { NULL,-1,NULL,-1}
3513     };
3514 
3515 
3516 static pmi editmenu[]={
3517   { "Toggle light",               ID_TOGGLE_LIGHT,NULL,-1},
3518   { "Set scroll rate",            ID_SET_SCROLL,NULL,-1},
3519   { "Center on player   (c)",       ID_CENTER_PLAYER,NULL,-1},
3520   { "Add palette",                ID_ADD_PALETTE,NULL,-1},
3521   { "Toggle Delays      (D)",          ID_TOGGLE_DELAY,NULL,-1},
3522 
3523   { "God mode",                   ID_GOD_MODE,NULL,-1},
3524   { "Clear weapons (z)",          ID_CLEAR_WEAPONS,NULL,-1},
3525   { "Mouse scroll",               ID_MOUSE_SCROLL,&mouse_scrolling,-1},
3526   { "Lock palette windows",       ID_LOCK_PALETTES,&palettes_locked,-1},
3527   { "Raise all foreground",       ID_RAISE_ALL,&raise_all,-1},
3528   { "Toggle object names",        ID_TOGGLE_NAMES,&show_names,-1},
3529 
3530   { NULL,0,NULL,-1},
3531   { "Toggle map        (m)",      ID_TOGGLE_MAP,NULL,-1},
3532 //  { "Shrink to 320x200 (F10)",    ID_SMALL_MODE,NULL,-1},
3533   { "Disable view shifts",        ID_DISABLE_VIEW_SHIFT,&view_shift_disabled,-1},
3534 //  { "Ultra Smooth draw (U)",      ID_INTERPOLATE_DRAW,  &interpolate_draw,'U'},
3535   { "Disable Autolight (A)",      ID_DISABLE_AUTOLIGHT, &disable_autolight,'A'},
3536   { "Show FPS/Obj count",         ID_SHOW_FPS,          &fps_on,-1},
3537 //  { NULL,0,NULL,-1},
3538 //  { "Record demo",                ID_RECORD_DEMO,NULL,-1},
3539 //  { "Play demo",                  ID_PLAY_DEMO,NULL,-1},
3540   { NULL,-1,NULL,-1}
3541 };
3542 
3543 
3544 
3545 // Window Menus
3546 static pmi winmenu[]={
3547           { "Foreground  (f)",    ID_WIN_FORE,    &forew_on,-1},
3548           { "Background  (b)",    ID_WIN_BACK,    &backw_on,-1},
3549           { "Draw layers (L)",    ID_WIN_LAYERS,  &show_menu_on,-1},
3550       { "Lighting    (l)",    ID_WIN_LIGHTING,&ledit_on,-1},
3551       { "Palettes    (p)",    ID_WIN_PALETTES,&pmenu_on,-1},
3552       { "Objects     (o)",    ID_WIN_OBJECTS, &omenu_on,-1},
3553       { "Console     (/)",    ID_WIN_CONSOLE, &commandw_on,-1},
3554       { "Tool Bar    (a)",    ID_WIN_TOOLBAR, &tbw_on,-1},
3555 //      { "Search      (s)",    ID_SEARCH,      &searchw_on,-1},
3556       { "Profile     (P)",    ID_PROFILE,     &profile_on,-1},
3557       { "Save positions",     ID_SAVE_WINDOWS,NULL,-1},
3558       { NULL,-1,NULL,-1}
3559     };
3560 
3561 */
3562 
i_recurse(pmi * first)3563 static pmenu_item *i_recurse(pmi *first)
3564 {
3565   if (first->id==-1)
3566     return NULL;
3567   else
3568     return new pmenu_item(first->id,first->name ? symbol_str(first->name) : 0,first->on_off,first->key,i_recurse(first+1));
3569 }
3570 
make_menu(int x,int y)3571 static pmenu *make_menu(int x, int y)
3572 {
3573   return new pmenu(x,y,
3574          new pmenu_item(symbol_str("file_top"),new psub_menu(i_recurse(filemenu),NULL),
3575      new pmenu_item(symbol_str("edit_top"),new psub_menu(i_recurse(editmenu),NULL),
3576      new pmenu_item(symbol_str("window_top"),new psub_menu(i_recurse(winmenu),NULL),NULL))),screen);
3577 }
3578 
3579 
3580 
toggle_edit_mode()3581 void toggle_edit_mode()
3582 {
3583   dev=dev^EDIT_MODE;
3584   if (dev&EDIT_MODE)
3585   {
3586     wm->set_mouse_shape(cache.img(c_normal)->copy(),1,1);
3587     pal->load();
3588   }
3589   else
3590   {
3591     if (dev&MAP_MODE) dev-=MAP_MODE;                        // no map mode while playing!
3592     wm->set_mouse_shape(cache.img(c_target)->copy(),8,8);
3593   }
3594   if ((dev&EDIT_MODE) && !dev_menu)
3595   {
3596     dev_menu=make_menu(0,yres-wm->font()->height()-5);
3597   }
3598   else if (!(dev&EDIT_MODE) && dev_menu)
3599   {
3600     delete dev_menu;
3601     dev_menu=NULL;
3602   }
3603 }
3604 
3605 
ok_to_scroll()3606 int dev_controll::ok_to_scroll()
3607 {
3608   if (state==DEV_MOVE_LIGHT || state==DEV_MOVE_OBJECT || mouse_scrolling) return 1;
3609   else return 0;
3610 }
3611 
~dev_controll()3612 dev_controll::~dev_controll()
3613 {
3614   for (int i=0; i<total_pals; i++)
3615     delete pal_wins[i];
3616   if (total_pals)
3617     free(pal_wins);
3618 }
3619 
3620 
3621 
~pal_win()3622 pal_win::~pal_win()
3623 {
3624   free(pat);
3625   free(name);
3626 }
3627