]> icculus.org git repositories - btb/d2x.git/blob - main/editor/medrobot.c
remove rcs tags
[btb/d2x.git] / main / editor / medrobot.c
1 /*
2 THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
3 SOFTWARE CORPORATION ("PARALLAX").  PARALLAX, IN DISTRIBUTING THE CODE TO
4 END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A
5 ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS
6 IN USING, DISPLAYING,  AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS
7 SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE
8 FREE PURPOSES.  IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE
9 CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES.  THE END-USER UNDERSTANDS
10 AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE.
11 COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION.  ALL RIGHTS RESERVED.
12 */
13
14 /*
15  *
16  * Dialog box to edit robot properties.
17  *
18  */
19
20 #ifdef HAVE_CONFIG_H
21 #include "conf.h"
22 #endif
23
24 #include <stdlib.h>
25 #include <stdio.h>
26 #ifdef __MSDOS__
27 #include <conio.h>
28 #include <direct.h>
29 #include <dos.h>
30 #endif
31 #include <math.h>
32 #include <string.h>
33
34 #include "screens.h"
35 #include "inferno.h"
36 #include "segment.h"
37 #include "editor.h"
38
39 #include "timer.h"
40 #include "objpage.h"
41 #include "fix.h"
42 #include "mono.h"
43 #include "error.h"
44 #include "kdefs.h"
45 #include        "object.h"
46 #include "polyobj.h"
47 #include "game.h"
48 #include "powerup.h"
49 #include "ai.h"
50 #include "hostage.h"
51 #include "eobject.h"
52 #include "medwall.h"
53 #include "eswitch.h"
54 #include "ehostage.h"
55 #include "key.h"
56 #include "centers.h"
57 #include "bm.h"
58
59 #define NUM_BOXES               6                       //      Number of boxes, AI modes
60
61 int GoodyNextID();
62 int GoodyPrevID();
63 void robot_close_window();
64 //-------------------------------------------------------------------------
65 // Variables for this module...
66 //-------------------------------------------------------------------------
67 static UI_WINDOW                                *MainWindow = NULL;
68 static UI_GADGET_USERBOX        *RobotViewBox;
69 static UI_GADGET_USERBOX        *ContainsViewBox;
70 static UI_GADGET_BUTTON         *QuitButton;
71 static UI_GADGET_RADIO          *InitialMode[NUM_BOXES];
72
73 static int old_object;
74 static fix Time;
75 static vms_angvec angles={0,0,0}, goody_angles={0,0,0};
76
77 void call_init_ai_object(object *objp, int behavior)
78 {
79         int     hide_segment;
80
81         if (behavior == AIB_STATION)
82                 hide_segment = SEGMENT_NUMBER(Cursegp);
83         else {
84                 if (Markedsegp != NULL)
85                         hide_segment = SEGMENT_NUMBER(Markedsegp);
86                 else
87                         hide_segment = SEGMENT_NUMBER(Cursegp);
88         }
89
90         mprintf((0, "Initializing AI object with hide segment = %i\n", hide_segment));
91         init_ai_object(OBJECT_NUMBER(objp), behavior, hide_segment);
92
93         if (behavior == AIB_STATION) {
94                 int     cseg, mseg;
95
96                 cseg = 0;
97                 mseg = 0;
98
99                 if (Cursegp != NULL)
100                         cseg = SEGMENT_NUMBER(Cursegp);
101
102                 if (Markedsegp != NULL) {
103                         mseg = SEGMENT_NUMBER(Markedsegp);
104                 }
105
106                 //objp->ctype.ai_info.follow_path_start_seg = SEGMENT_NUMBER(Cursegp);
107                 //objp->ctype.ai_info.follow_path_end_seg = SEGMENT_NUMBER(Markedsegp);
108         }
109 }
110
111 //-------------------------------------------------------------------------
112 // Called when user presses "Next Type" button.  This only works for polygon
113 // objects and it just selects the next polygon model for the current object.
114 //-------------------------------------------------------------------------
115 int RobotNextType()
116 {
117         if (Cur_object_index > -1 )     {
118                 if ( Objects[Cur_object_index].type == OBJ_ROBOT )      {
119                         object * obj = &Objects[Cur_object_index];
120                         obj->id++;
121                         if (obj->id >= N_robot_types )
122                                 obj->id = 0;
123
124                         //Set polygon-object-specific data
125                         obj->rtype.pobj_info.model_num = Robot_info[obj->id].model_num;
126                         obj->rtype.pobj_info.subobj_flags = 0;
127                         //set Physics info
128                         obj->mtype.phys_info.flags |= (PF_LEVELLING);
129                         obj->shields = Robot_info[obj->id].strength;
130                         call_init_ai_object(obj, AIB_NORMAL);
131
132                         Cur_object_id = obj->id;
133                 }
134         }
135         Update_flags |= UF_WORLD_CHANGED;
136         return 1;
137 }
138
139 //-------------------------------------------------------------------------
140 // Called when user presses "Prev Type" button.  This only works for polygon
141 // objects and it just selects the prev polygon model for the current object.
142 //-------------------------------------------------------------------------
143 int RobotPrevType()
144 {
145         if (Cur_object_index > -1 )     {
146                 if ( Objects[Cur_object_index].type == OBJ_ROBOT )      {
147                         object * obj = &Objects[Cur_object_index];
148                         if (obj->id == 0 ) 
149                                 obj->id = N_robot_types-1;
150                         else
151                                 obj->id--;
152
153                         //Set polygon-object-specific data
154                         obj->rtype.pobj_info.model_num = Robot_info[obj->id].model_num;
155                         obj->rtype.pobj_info.subobj_flags = 0;
156                         //set Physics info
157                         obj->mtype.phys_info.flags |= (PF_LEVELLING);
158                         obj->shields = Robot_info[obj->id].strength;
159                         call_init_ai_object(obj, AIB_NORMAL);
160
161                         Cur_object_id = obj->id;
162                 }
163         }
164         Update_flags |= UF_WORLD_CHANGED;
165         return 1;
166 }
167
168 //-------------------------------------------------------------------------
169 // Dummy function for Mike to write.
170 //-------------------------------------------------------------------------
171 int med_set_ai_path()
172 {
173         mprintf( (0, "med-set-ai-path called -- it does nothing, paths automatically set!\n" ));
174
175         return 1;
176 }
177
178 // #define OBJ_NONE             255     //unused object
179 // #define OBJ_WALL             0               //A wall... not really an object, but used for collisions
180 // #define OBJ_FIREBALL 1               //a fireball, part of an explosion
181 // #define OBJ_ROBOT            2               //an evil enemy
182 // #define OBJ_HOSTAGE  3               //a hostage you need to rescue
183 // #define OBJ_PLAYER   4               //the player on the console
184 // #define OBJ_WEAPON   5               //a laser, missile, etc
185 // #define OBJ_CAMERA   6               //a camera to slew around with
186 // #define OBJ_POWERUP  7               //a powerup you can pick up
187 // #define OBJ_DEBRIS   8               //a piece of robot
188 // #define OBJ_CNTRLCEN 9               //the control center
189 // #define OBJ_FLARE            10              //the control center
190 // #define MAX_OBJECT_TYPES     11
191
192
193 #define GOODY_TYPE_MAX  MAX_OBJECT_TYPES
194 #define GOODY_X 6
195 #define GOODY_Y 132
196
197 //#define       GOODY_ID_MAX_ROBOT      6
198 //#define       GOODY_ID_MAX_POWERUP    9
199 #define GOODY_COUNT_MAX 4
200
201 int             Cur_goody_type = OBJ_POWERUP;
202 int             Cur_goody_id = 0;
203 int             Cur_goody_count = 0;
204
205 void update_goody_info(void)
206 {
207         if (Cur_object_index > -1 )     {
208                 if ( Objects[Cur_object_index].type == OBJ_ROBOT )      {
209                         object * obj = &Objects[Cur_object_index];
210
211                         obj->contains_type = Cur_goody_type;
212                         obj->contains_id = Cur_goody_id;
213                         obj->contains_count = Cur_goody_count;
214                 }
215         }
216 }
217
218 // #define OBJ_WALL             0               //A wall... not really an object, but used for collisions
219 // #define OBJ_FIREBALL 1               //a fireball, part of an explosion
220 // #define OBJ_ROBOT            2               //an evil enemy
221 // #define OBJ_HOSTAGE  3               //a hostage you need to rescue
222 // #define OBJ_PLAYER   4               //the player on the console
223 // #define OBJ_WEAPON   5               //a laser, missile, etc
224 // #define OBJ_CAMERA   6               //a camera to slew around with
225 // #define OBJ_POWERUP  7               //a powerup you can pick up
226 // #define OBJ_DEBRIS   8               //a piece of robot
227 // #define OBJ_CNTRLCEN 9               //the control center
228 // #define OBJ_FLARE            10              //the control center
229 // #define MAX_OBJECT_TYPES     11
230
231
232 int GoodyNextType()
233 {
234         Cur_goody_type++;
235         while (!((Cur_goody_type == OBJ_ROBOT) || (Cur_goody_type == OBJ_POWERUP))) {
236                 if (Cur_goody_type > GOODY_TYPE_MAX)
237                         Cur_goody_type=0;
238                 else
239                         Cur_goody_type++;
240         }
241
242         GoodyNextID();
243         GoodyPrevID();
244
245         update_goody_info();
246         return 1;
247 }
248
249 int GoodyPrevType()
250 {
251         Cur_goody_type--;
252         while (!((Cur_goody_type == OBJ_ROBOT) || (Cur_goody_type == OBJ_POWERUP))) {
253                 if (Cur_goody_type < 0)
254                         Cur_goody_type = GOODY_TYPE_MAX;
255                 else
256                         Cur_goody_type--;
257         }
258
259         GoodyNextID();
260         GoodyPrevID();
261
262         update_goody_info();
263         return 1;
264 }
265
266 int GoodyNextID()
267 {
268         Cur_goody_id++;
269         if (Cur_goody_type == OBJ_ROBOT) {
270                 if (Cur_goody_id >= N_robot_types)
271                         Cur_goody_id=0;
272         } else {
273                 if (Cur_goody_id >= N_powerup_types)
274                         Cur_goody_id=0;
275         }
276
277         update_goody_info();
278         return 1;
279 }
280
281 int GoodyPrevID()
282 {
283         Cur_goody_id--;
284         if (Cur_goody_type == OBJ_ROBOT) {
285                 if (Cur_goody_id < 0)
286                         Cur_goody_id = N_robot_types-1;
287         } else {
288                 if (Cur_goody_id < 0)
289                         Cur_goody_id = N_powerup_types-1;
290         }
291
292         update_goody_info();
293         return 1;
294 }
295
296 int GoodyNextCount()
297 {
298         Cur_goody_count++;
299         if (Cur_goody_count > GOODY_COUNT_MAX)
300                 Cur_goody_count=0;
301
302         update_goody_info();
303         return 1;
304 }
305
306 int GoodyPrevCount()
307 {
308         Cur_goody_count--;
309         if (Cur_goody_count < 0)
310                 Cur_goody_count=GOODY_COUNT_MAX;
311
312         update_goody_info();
313         return 1;
314 }
315
316 int is_legal_type(int the_type)
317 {
318         return (the_type == OBJ_ROBOT) || (the_type == OBJ_CLUTTER);
319 }
320
321 int is_legal_type_for_this_window(int objnum)
322 {
323         if (objnum == -1)
324                 return 1;
325         else
326                 return is_legal_type(Objects[objnum].type);
327 }
328
329 int LocalObjectSelectNextinSegment(void)
330 {
331         int     rval, first_obj;
332
333         rval = ObjectSelectNextinSegment();
334         first_obj = Cur_object_index;
335
336         if (Cur_object_index != -1) {
337                 while (!is_legal_type_for_this_window(Cur_object_index)) {
338                         //mprintf((0, "Skipping object #%i of type %i\n", Cur_object_index, Objects[Cur_object_index].type));
339                         rval = ObjectSelectNextinSegment();
340                         if (first_obj == Cur_object_index)
341                                 break;
342                 }
343
344                 Cur_goody_type = Objects[Cur_object_index].contains_type;
345                 Cur_goody_id = Objects[Cur_object_index].contains_id;
346                 if (Objects[Cur_object_index].contains_count < 0)
347                         Objects[Cur_object_index].contains_count = 0;
348                 Cur_goody_count = Objects[Cur_object_index].contains_count;
349         }
350
351         if (Cur_object_index != first_obj)
352                 set_view_target_from_segment(Cursegp);
353
354         return rval;
355 }
356
357 int LocalObjectSelectNextinMine(void)
358 {
359         int     rval, first_obj;
360
361         rval = ObjectSelectNextInMine();
362
363         first_obj = Cur_object_index;
364
365         if (Cur_object_index != -1) {
366                 while (!is_legal_type_for_this_window(Cur_object_index)) {
367                         //mprintf((0, "Skipping object #%i of type %i\n", Cur_object_index, Objects[Cur_object_index].type));
368                         ObjectSelectNextInMine();
369                         if (Cur_object_index == first_obj)
370                                 break;
371                 }
372
373                 Cur_goody_type = Objects[Cur_object_index].contains_type;
374                 Cur_goody_id = Objects[Cur_object_index].contains_id;
375                 if (Objects[Cur_object_index].contains_count < 0)
376                         Objects[Cur_object_index].contains_count = 0;
377                 Cur_goody_count = Objects[Cur_object_index].contains_count;
378         }
379
380         if (Cur_object_index != first_obj)
381                 set_view_target_from_segment(Cursegp);
382
383         return rval;
384 }
385
386 int LocalObjectSelectPrevinMine(void)
387 {
388         int     rval, first_obj;
389
390         rval = ObjectSelectPrevInMine();
391
392         first_obj = Cur_object_index;
393
394         if (Cur_object_index != -1) {
395                 while (!is_legal_type_for_this_window(Cur_object_index)) {
396                         //mprintf((0, "Skipping object #%i of type %i\n", Cur_object_index, Objects[Cur_object_index].type));
397                         ObjectSelectPrevInMine();
398                         if (first_obj == Cur_object_index)
399                                 break;
400                 }
401
402                 Cur_goody_type = Objects[Cur_object_index].contains_type;
403                 Cur_goody_id = Objects[Cur_object_index].contains_id;
404                 if (Objects[Cur_object_index].contains_count < 0)
405                         Objects[Cur_object_index].contains_count = 0;
406                 Cur_goody_count = Objects[Cur_object_index].contains_count;
407         }
408
409         if (Cur_object_index != first_obj)
410                 set_view_target_from_segment(Cursegp);
411
412         return rval;
413 }
414
415 int LocalObjectDelete(void)
416 {
417         int     rval;
418
419         rval = ObjectDelete();
420
421         if (Cur_object_index != -1) {
422                 Cur_goody_type = Objects[Cur_object_index].contains_type;
423                 Cur_goody_id = Objects[Cur_object_index].contains_id;
424                 Cur_goody_count = Objects[Cur_object_index].contains_count;
425         }
426
427         set_view_target_from_segment(Cursegp);
428
429         return rval;
430 }
431
432 int LocalObjectPlaceObject(void)
433 {
434         int     rval;
435
436         Cur_goody_count = 0;
437
438         if (Cur_object_type != OBJ_ROBOT)
439         {
440                 Cur_object_type = OBJ_ROBOT;
441                 Cur_object_id = 3;      // class 1 drone
442                 Num_object_subtypes = N_robot_types;
443         }
444
445         rval = ObjectPlaceObject();
446         if (rval == -1)
447                 return -1;
448
449         Objects[Cur_object_index].contains_type = Cur_goody_type;
450         Objects[Cur_object_index].contains_id = Cur_goody_id;
451         Objects[Cur_object_index].contains_count = Cur_goody_count;
452
453         set_view_target_from_segment(Cursegp);
454
455         return rval;
456 }
457
458 void close_all_windows(void)
459 {
460         close_trigger_window();
461         close_wall_window();
462         close_centers_window();
463         hostage_close_window();
464         robot_close_window();
465 }
466
467
468 //-------------------------------------------------------------------------
469 // Called from the editor... does one instance of the robot dialog box
470 //-------------------------------------------------------------------------
471 int do_robot_dialog()
472 {
473         int i;
474
475         // Only open 1 instance of this window...
476         if ( MainWindow != NULL ) return 0;
477         
478         // Close other windows
479         close_all_windows();
480         Cur_goody_count = 0;
481
482         // Open a window with a quit button
483         MainWindow = ui_open_window( TMAPBOX_X+20, TMAPBOX_Y+20, 765-TMAPBOX_X, 545-TMAPBOX_Y, WIN_DIALOG );
484         QuitButton = ui_add_gadget_button( MainWindow, 20, 286, 40, 32, "Done", NULL );
485
486         ui_add_gadget_button( MainWindow, GOODY_X+50, GOODY_Y-3, 25, 22, "<<", GoodyPrevType );
487         ui_add_gadget_button( MainWindow, GOODY_X+80, GOODY_Y-3, 25, 22, ">>", GoodyNextType );
488
489         ui_add_gadget_button( MainWindow, GOODY_X+50, GOODY_Y+21, 25, 22, "<<", GoodyPrevID );
490         ui_add_gadget_button( MainWindow, GOODY_X+80, GOODY_Y+21, 25, 22, ">>", GoodyNextID );
491
492         ui_add_gadget_button( MainWindow, GOODY_X+50, GOODY_Y+45, 25, 22, "<<", GoodyPrevCount );
493         ui_add_gadget_button( MainWindow, GOODY_X+80, GOODY_Y+45, 25, 22, ">>", GoodyNextCount );
494
495         InitialMode[0] = ui_add_gadget_radio( MainWindow,  6, 58, 16, 16, 0, "Hover" );
496         InitialMode[1] = ui_add_gadget_radio( MainWindow, 76, 58, 16, 16, 0, "Normal" );
497         InitialMode[2] = ui_add_gadget_radio( MainWindow,  6, 78, 16, 16, 0, "(hide)" );
498         InitialMode[3] = ui_add_gadget_radio( MainWindow, 76, 78, 16, 16, 0, "Avoid" );
499         InitialMode[4] = ui_add_gadget_radio( MainWindow,  6, 98, 16, 16, 0, "Follow" );
500         InitialMode[5] = ui_add_gadget_radio( MainWindow, 76, 98, 16, 16, 0, "Station" );
501
502         // The little box the robots will spin in.
503         RobotViewBox = ui_add_gadget_userbox( MainWindow,155, 5, 150, 125 );
504
505         // The little box the robots will spin in.
506         ContainsViewBox = ui_add_gadget_userbox( MainWindow,10, 202, 100, 80 );
507
508         // A bunch of buttons...
509         i = 135;
510         ui_add_gadget_button( MainWindow,190,i,53, 26, "<<Typ",                         RobotPrevType );
511         ui_add_gadget_button( MainWindow,247,i,53, 26, "Typ>>",                         RobotNextType );                                                        i += 29;                
512         ui_add_gadget_button( MainWindow,190,i,110, 26, "Next in Seg", LocalObjectSelectNextinSegment );        i += 29;                
513
514         ui_add_gadget_button( MainWindow,190,i,53, 26, "<<Obj",                 LocalObjectSelectPrevinMine );
515         ui_add_gadget_button( MainWindow,247,i,53, 26, ">>Obj",                 LocalObjectSelectNextinMine );          i += 29;                
516
517         ui_add_gadget_button( MainWindow,190,i,110, 26, "Delete",               LocalObjectDelete );                                            i += 29;                
518         ui_add_gadget_button( MainWindow,190,i,110, 26, "Create New",   LocalObjectPlaceObject );                               i += 29;                
519         ui_add_gadget_button( MainWindow,190,i,110, 26, "Set Path",     med_set_ai_path );
520         
521         Time = timer_get_fixed_seconds();
522
523         old_object = -2;                // Set to some dummy value so everything works ok on the first frame.
524
525         if ( Cur_object_index == -1 )
526                 LocalObjectSelectNextinMine();
527
528         return 1;
529
530 }
531
532 void robot_close_window()
533 {
534         if ( MainWindow!=NULL ) {
535                 ui_close_window( MainWindow );
536                 MainWindow = NULL;
537         }
538
539 }
540
541 #define STRING_LENGTH   8
542
543 void do_robot_window()
544 {
545         int     i;
546         fix     DeltaTime, Temp;
547         int     first_object_index;
548
549         if ( MainWindow == NULL ) return;
550
551         first_object_index = Cur_object_index;
552         while (!is_legal_type_for_this_window(Cur_object_index)) {
553                 LocalObjectSelectNextinMine();
554                 if (first_object_index == Cur_object_index) {
555                         break;
556                 }
557         }
558
559         //------------------------------------------------------------
560         // Call the ui code..
561         //------------------------------------------------------------
562         ui_button_any_drawn = 0;
563         ui_window_do_gadgets(MainWindow);
564
565         //------------------------------------------------------------
566         // If we change objects, we need to reset the ui code for all
567         // of the radio buttons that control the ai mode.  Also makes
568         // the current AI mode button be flagged as pressed down.
569         //------------------------------------------------------------
570         if (old_object != Cur_object_index )    {
571                 if ( Cur_object_index > -1 ) {
572                         int     behavior = Objects[Cur_object_index].ctype.ai_info.behavior;
573                         if ( !((behavior >= MIN_BEHAVIOR) && (behavior <= MAX_BEHAVIOR))) {
574                                 mprintf((0, "Object #%i behavior id (%i) out of bounds, setting to AIB_NORMAL.\n", Cur_object_index, behavior));
575                                 Objects[Cur_object_index].ctype.ai_info.behavior = AIB_NORMAL;
576                                 behavior = AIB_NORMAL;
577                         }
578                         ui_radio_set_value(InitialMode[behavior - MIN_BEHAVIOR], 1);
579                 }
580         }
581
582         //------------------------------------------------------------
583         // If any of the radio buttons that control the mode are set, then
584         // update the cooresponding AI state.
585         //------------------------------------------------------------
586         for (   i=0; i < NUM_BOXES; i++ )       {
587                 if ( InitialMode[i]->flag == 1 )        
588                         if (Objects[Cur_object_index].ctype.ai_info.behavior != MIN_BEHAVIOR+i) {
589                                 Objects[Cur_object_index].ctype.ai_info.behavior = MIN_BEHAVIOR+i;              // Set the ai_state to the cooresponding radio button
590                                 call_init_ai_object(&Objects[Cur_object_index], MIN_BEHAVIOR+i);
591                         }
592         }
593
594         //------------------------------------------------------------
595         // A simple frame time counter for spinning the objects...
596         //------------------------------------------------------------
597         Temp = timer_get_fixed_seconds();
598         DeltaTime = Temp - Time;
599         Time = Temp;
600
601         //------------------------------------------------------------
602         // Redraw the object in the little 64x64 box
603         //------------------------------------------------------------
604         if (Cur_object_index > -1 )     {
605                 object *obj = &Objects[Cur_object_index];
606
607                 gr_set_current_canvas( RobotViewBox->canvas );
608                 draw_object_picture(obj->id, &angles, obj->type );
609                 angles.h += fixmul(0x1000, DeltaTime );
610         } else {
611                 // no object, so just blank out
612                 gr_set_current_canvas( RobotViewBox->canvas );
613                 gr_clear_canvas( CGREY );
614
615 //              LocalObjectSelectNextInMine();
616         }
617
618         //------------------------------------------------------------
619         // Redraw the contained object in the other little box
620         //------------------------------------------------------------
621         if ((Cur_object_index > -1 ) && (Cur_goody_count > 0))  {
622                 gr_set_current_canvas( ContainsViewBox->canvas );
623                 if ( Cur_goody_id > -1 )
624                         draw_object_picture(Cur_goody_id, &goody_angles, Cur_goody_type);
625                 else
626                         gr_clear_canvas( CGREY );
627                 goody_angles.h += fixmul(0x1000, DeltaTime );
628         } else {
629                 // no object, so just blank out
630                 gr_set_current_canvas( ContainsViewBox->canvas );
631                 gr_clear_canvas( CGREY );
632
633 //              LocalObjectSelectNextInMine();
634         }
635
636         //------------------------------------------------------------
637         // If anything changes in the ui system, redraw all the text that
638         // identifies this robot.
639         //------------------------------------------------------------
640
641         if (ui_button_any_drawn || (old_object != Cur_object_index) )   {
642                 int     i;
643                 char    type_text[STRING_LENGTH+1],id_text[STRING_LENGTH+1];
644
645                 if (Cur_object_index != -1) {
646                         Cur_goody_type = Objects[Cur_object_index].contains_type;
647                         Cur_goody_id = Objects[Cur_object_index].contains_id;
648                         if (Objects[Cur_object_index].contains_count < 0)
649                                 Objects[Cur_object_index].contains_count = 0;
650                         Cur_goody_count = Objects[Cur_object_index].contains_count;
651                 }
652
653                 ui_wprintf_at( MainWindow, GOODY_X, GOODY_Y,    " Type:");
654                 ui_wprintf_at( MainWindow, GOODY_X, GOODY_Y+24, "   ID:");
655                 ui_wprintf_at( MainWindow, GOODY_X, GOODY_Y+48, "Count:");
656
657                 for (i=0; i<STRING_LENGTH; i++)
658                         id_text[i] = ' ';
659                 id_text[i] = 0;
660
661                 switch (Cur_goody_type) {
662                         case OBJ_ROBOT:
663                                 strcpy(type_text, "Robot  ");
664                                 strncpy(id_text, Robot_names[Cur_goody_id], strlen(Robot_names[Cur_goody_id]));
665                                 break;
666                         case OBJ_POWERUP:
667                                 strcpy(type_text, "Powerup");
668                                 strncpy(id_text, Powerup_names[Cur_goody_id], strlen(Powerup_names[Cur_goody_id]));
669                                 break;
670                         default:
671                                 editor_status("Illegal contained object type (%i), changing to powerup.", Cur_goody_type);
672                                 Cur_goody_type = OBJ_POWERUP;
673                                 Cur_goody_id = 0;
674                                 strcpy(type_text, "Powerup");
675                                 strncpy(id_text, Powerup_names[Cur_goody_id], strlen(Powerup_names[Cur_goody_id]));
676                                 break;
677                 }
678
679                 ui_wprintf_at( MainWindow, GOODY_X+108, GOODY_Y, type_text);
680                 ui_wprintf_at( MainWindow, GOODY_X+108, GOODY_Y+24, id_text);
681                 ui_wprintf_at( MainWindow, GOODY_X+108, GOODY_Y+48, "%i", Cur_goody_count);
682
683                 if ( Cur_object_index > -1 )    {
684                         int     id = Objects[Cur_object_index].id;
685                         char    id_text[12];
686                         int     i;
687
688                         for (i=0; i<STRING_LENGTH; i++)
689                                 id_text[i] = ' ';
690                         id_text[i] = 0;
691
692                         strncpy(id_text, Robot_names[id], strlen(Robot_names[id]));
693
694                         ui_wprintf_at( MainWindow, 12,  6, "Robot: %3d ", Cur_object_index );
695                         ui_wprintf_at( MainWindow, 12, 22, "   Id: %3d", id);
696                         ui_wprintf_at( MainWindow, 12, 38, " Name: %8s", id_text);
697
698                 }       else {
699                         ui_wprintf_at( MainWindow, 12,  6, "Robot: none" );
700                         ui_wprintf_at( MainWindow, 12, 22, " Type: ?  "  );
701                         ui_wprintf_at( MainWindow, 12, 38, " Name: ________" );
702                 }
703                 Update_flags |= UF_WORLD_CHANGED;
704         }
705
706         if ( QuitButton->pressed || (last_keypress==KEY_ESC))   {
707                 robot_close_window();
708                 return;
709         }               
710
711         old_object = Cur_object_index;
712 }
713
714 //      --------------------------------------------------------------------------------------------------------------------------
715 #define NUM_MATT_THINGS 2
716
717 #define MATT_LEN                                20
718
719 static UI_WINDOW                                *MattWindow = NULL;
720
721 void object_close_window()
722 {
723         if ( MattWindow!=NULL ) {
724                 ui_close_window( MattWindow );
725                 MattWindow = NULL;
726         }
727
728 }
729
730
731 UI_GADGET_INPUTBOX      *Xtext, *Ytext, *Ztext;
732
733 //-------------------------------------------------------------------------
734 // Called from the editor... does one instance of the object dialog box
735 //-------------------------------------------------------------------------
736 int do_object_dialog()
737 {
738         char    Xmessage[MATT_LEN], Ymessage[MATT_LEN], Zmessage[MATT_LEN];
739         object *obj=&Objects[Cur_object_index];
740
741         if (obj->type == OBJ_ROBOT)             //don't do this for robots
742                 return 0;
743
744         // Only open 1 instance of this window...
745         if ( MattWindow != NULL )
746                 return 0;
747         
748         Cur_goody_count = 0;
749
750         // Open a window with a quit button
751         MattWindow = ui_open_window( TMAPBOX_X+20, TMAPBOX_Y+20, 765-TMAPBOX_X, 545-TMAPBOX_Y, WIN_DIALOG );
752         QuitButton = ui_add_gadget_button( MattWindow, 20, 286, 40, 32, "Done", NULL );
753
754         QuitButton->hotkey = KEY_ENTER;
755
756         // These are the radio buttons for each mode
757         InitialMode[0] = ui_add_gadget_radio( MattWindow, 10, 50, 16, 16, 0, "None" );
758         InitialMode[1] = ui_add_gadget_radio( MattWindow, 80, 50, 16, 16, 0, "Spinning" );
759
760         InitialMode[obj->movement_type == MT_SPINNING?1:0]->flag = 1;
761
762         sprintf(Xmessage,"%.2f",f2fl(obj->mtype.spin_rate.x));
763         sprintf(Ymessage,"%.2f",f2fl(obj->mtype.spin_rate.y));
764         sprintf(Zmessage,"%.2f",f2fl(obj->mtype.spin_rate.z));
765
766         ui_wprintf_at( MattWindow, 10, 132,"&X:" );
767         Xtext = ui_add_gadget_inputbox( MattWindow, 30, 132, MATT_LEN, MATT_LEN, Xmessage );
768
769         ui_wprintf_at( MattWindow, 10, 162,"&Y:" );
770         Ytext = ui_add_gadget_inputbox( MattWindow, 30, 162, MATT_LEN, MATT_LEN, Ymessage );
771
772         ui_wprintf_at( MattWindow, 10, 192,"&Z:" );
773         Ztext = ui_add_gadget_inputbox( MattWindow, 30, 192, MATT_LEN, MATT_LEN, Zmessage );
774
775         ui_gadget_calc_keys(MattWindow);
776
777         MattWindow->keyboard_focus_gadget = (UI_GADGET *) InitialMode[0];
778
779         mprintf((0, "X = %08x, Y = %08x, Z = %08x\n", atoi(Xmessage), atoi(Ymessage), atoi(Zmessage)));
780
781         return 1;
782
783 }
784
785 void do_object_window()
786 {
787         object *obj=&Objects[Cur_object_index];
788
789         if ( MattWindow == NULL ) return;
790
791         //------------------------------------------------------------
792         // Call the ui code..
793         //------------------------------------------------------------
794         ui_button_any_drawn = 0;
795         ui_window_do_gadgets(MattWindow);
796
797
798         if ( QuitButton->pressed || (last_keypress==KEY_ESC))   {
799
800                 if (InitialMode[0]->flag) obj->movement_type = MT_NONE;
801                 if (InitialMode[1]->flag) obj->movement_type = MT_SPINNING;
802
803                 obj->mtype.spin_rate.x = fl2f(atof(Xtext->text));
804                 obj->mtype.spin_rate.y = fl2f(atof(Ytext->text));
805                 obj->mtype.spin_rate.z = fl2f(atof(Ztext->text));
806
807                 object_close_window();
808                 return;
809         }               
810
811         old_object = Cur_object_index;
812 }
813
814 void set_all_modes_to_hover(void)
815 {
816         int     i;
817
818         for (i=0; i<=Highest_object_index; i++)
819                 if (Objects[i].control_type == CT_AI)
820                         Objects[i].ctype.ai_info.behavior = AIB_STILL;
821 }
822