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