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