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