]> icculus.org git repositories - btb/d2x.git/blob - main/editor/medrobot.c
no checking if obj->id > -1 (it's unsigned)
[btb/d2x.git] / main / editor / medrobot.c
1 /* $Id: medrobot.c,v 1.8 2005-07-25 03:50:07 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.8 2005-07-25 03:50:07 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                 if ( Cur_object_index > -1 ) {
577                         int     behavior = Objects[Cur_object_index].ctype.ai_info.behavior;
578                         if ( !((behavior >= MIN_BEHAVIOR) && (behavior <= MAX_BEHAVIOR))) {
579                                 mprintf((0, "Object #%i behavior id (%i) out of bounds, setting to AIB_NORMAL.\n", Cur_object_index, behavior));
580                                 Objects[Cur_object_index].ctype.ai_info.behavior = AIB_NORMAL;
581                                 behavior = AIB_NORMAL;
582                         }
583                         ui_radio_set_value(InitialMode[behavior - MIN_BEHAVIOR], 1);
584                 }
585         }
586
587         //------------------------------------------------------------
588         // If any of the radio buttons that control the mode are set, then
589         // update the cooresponding AI state.
590         //------------------------------------------------------------
591         for (   i=0; i < NUM_BOXES; i++ )       {
592                 if ( InitialMode[i]->flag == 1 )        
593                         if (Objects[Cur_object_index].ctype.ai_info.behavior != MIN_BEHAVIOR+i) {
594                                 Objects[Cur_object_index].ctype.ai_info.behavior = MIN_BEHAVIOR+i;              // Set the ai_state to the cooresponding radio button
595                                 call_init_ai_object(&Objects[Cur_object_index], MIN_BEHAVIOR+i);
596                         }
597         }
598
599         //------------------------------------------------------------
600         // A simple frame time counter for spinning the objects...
601         //------------------------------------------------------------
602         Temp = timer_get_fixed_seconds();
603         DeltaTime = Temp - Time;
604         Time = Temp;
605
606         //------------------------------------------------------------
607         // Redraw the object in the little 64x64 box
608         //------------------------------------------------------------
609         if (Cur_object_index > -1 )     {
610                 object *obj = &Objects[Cur_object_index];
611
612                 gr_set_current_canvas( RobotViewBox->canvas );
613                 draw_object_picture(obj->id, &angles, obj->type );
614                 angles.h += fixmul(0x1000, DeltaTime );
615         } else {
616                 // no object, so just blank out
617                 gr_set_current_canvas( RobotViewBox->canvas );
618                 gr_clear_canvas( CGREY );
619
620 //              LocalObjectSelectNextInMine();
621         }
622
623         //------------------------------------------------------------
624         // Redraw the contained object in the other little box
625         //------------------------------------------------------------
626         if ((Cur_object_index > -1 ) && (Cur_goody_count > 0))  {
627                 gr_set_current_canvas( ContainsViewBox->canvas );
628                 if ( Cur_goody_id > -1 )
629                         draw_object_picture(Cur_goody_id, &goody_angles, Cur_goody_type);
630                 else
631                         gr_clear_canvas( CGREY );
632                 goody_angles.h += fixmul(0x1000, DeltaTime );
633         } else {
634                 // no object, so just blank out
635                 gr_set_current_canvas( ContainsViewBox->canvas );
636                 gr_clear_canvas( CGREY );
637
638 //              LocalObjectSelectNextInMine();
639         }
640
641         //------------------------------------------------------------
642         // If anything changes in the ui system, redraw all the text that
643         // identifies this robot.
644         //------------------------------------------------------------
645
646         if (ui_button_any_drawn || (old_object != Cur_object_index) )   {
647                 int     i;
648                 char    type_text[STRING_LENGTH+1],id_text[STRING_LENGTH+1];
649
650                 if (Cur_object_index != -1) {
651                         Cur_goody_type = Objects[Cur_object_index].contains_type;
652                         Cur_goody_id = Objects[Cur_object_index].contains_id;
653                         if (Objects[Cur_object_index].contains_count < 0)
654                                 Objects[Cur_object_index].contains_count = 0;
655                         Cur_goody_count = Objects[Cur_object_index].contains_count;
656                 }
657
658                 ui_wprintf_at( MainWindow, GOODY_X, GOODY_Y,    " Type:");
659                 ui_wprintf_at( MainWindow, GOODY_X, GOODY_Y+24, "   ID:");
660                 ui_wprintf_at( MainWindow, GOODY_X, GOODY_Y+48, "Count:");
661
662                 for (i=0; i<STRING_LENGTH; i++)
663                         id_text[i] = ' ';
664                 id_text[i] = 0;
665
666                 switch (Cur_goody_type) {
667                         case OBJ_ROBOT:
668                                 strcpy(type_text, "Robot  ");
669                                 strncpy(id_text, Robot_names[Cur_goody_id], strlen(Robot_names[Cur_goody_id]));
670                                 break;
671                         case OBJ_POWERUP:
672                                 strcpy(type_text, "Powerup");
673                                 strncpy(id_text, Powerup_names[Cur_goody_id], strlen(Powerup_names[Cur_goody_id]));
674                                 break;
675                         default:
676                                 editor_status("Illegal contained object type (%i), changing to powerup.", Cur_goody_type);
677                                 Cur_goody_type = OBJ_POWERUP;
678                                 Cur_goody_id = 0;
679                                 strcpy(type_text, "Powerup");
680                                 strncpy(id_text, Powerup_names[Cur_goody_id], strlen(Powerup_names[Cur_goody_id]));
681                                 break;
682                 }
683
684                 ui_wprintf_at( MainWindow, GOODY_X+108, GOODY_Y, type_text);
685                 ui_wprintf_at( MainWindow, GOODY_X+108, GOODY_Y+24, id_text);
686                 ui_wprintf_at( MainWindow, GOODY_X+108, GOODY_Y+48, "%i", Cur_goody_count);
687
688                 if ( Cur_object_index > -1 )    {
689                         int     id = Objects[Cur_object_index].id;
690                         char    id_text[12];
691                         int     i;
692
693                         for (i=0; i<STRING_LENGTH; i++)
694                                 id_text[i] = ' ';
695                         id_text[i] = 0;
696
697                         strncpy(id_text, Robot_names[id], strlen(Robot_names[id]));
698
699                         ui_wprintf_at( MainWindow, 12,  6, "Robot: %3d ", Cur_object_index );
700                         ui_wprintf_at( MainWindow, 12, 22, "   Id: %3d", id);
701                         ui_wprintf_at( MainWindow, 12, 38, " Name: %8s", id_text);
702
703                 }       else {
704                         ui_wprintf_at( MainWindow, 12,  6, "Robot: none" );
705                         ui_wprintf_at( MainWindow, 12, 22, " Type: ?  "  );
706                         ui_wprintf_at( MainWindow, 12, 38, " Name: ________" );
707                 }
708                 Update_flags |= UF_WORLD_CHANGED;
709         }
710
711         if ( QuitButton->pressed || (last_keypress==KEY_ESC))   {
712                 robot_close_window();
713                 return;
714         }               
715
716         old_object = Cur_object_index;
717 }
718
719 //      --------------------------------------------------------------------------------------------------------------------------
720 #define NUM_MATT_THINGS 2
721
722 #define MATT_LEN                                20
723
724 static UI_WINDOW                                *MattWindow = NULL;
725
726 void object_close_window()
727 {
728         if ( MattWindow!=NULL ) {
729                 ui_close_window( MattWindow );
730                 MattWindow = NULL;
731         }
732
733 }
734
735
736 UI_GADGET_INPUTBOX      *Xtext, *Ytext, *Ztext;
737
738 //-------------------------------------------------------------------------
739 // Called from the editor... does one instance of the object dialog box
740 //-------------------------------------------------------------------------
741 int do_object_dialog()
742 {
743         char    Xmessage[MATT_LEN], Ymessage[MATT_LEN], Zmessage[MATT_LEN];
744         object *obj=&Objects[Cur_object_index];
745
746         if (obj->type == OBJ_ROBOT)             //don't do this for robots
747                 return 0;
748
749         // Only open 1 instance of this window...
750         if ( MattWindow != NULL )
751                 return 0;
752         
753         Cur_goody_count = 0;
754
755         // Open a window with a quit button
756         MattWindow = ui_open_window( TMAPBOX_X+20, TMAPBOX_Y+20, 765-TMAPBOX_X, 545-TMAPBOX_Y, WIN_DIALOG );
757         QuitButton = ui_add_gadget_button( MattWindow, 20, 286, 40, 32, "Done", NULL );
758
759         QuitButton->hotkey = KEY_ENTER;
760
761         // These are the radio buttons for each mode
762         InitialMode[0] = ui_add_gadget_radio( MattWindow, 10, 50, 16, 16, 0, "None" );
763         InitialMode[1] = ui_add_gadget_radio( MattWindow, 80, 50, 16, 16, 0, "Spinning" );
764
765         InitialMode[obj->movement_type == MT_SPINNING?1:0]->flag = 1;
766
767         sprintf(Xmessage,"%.2f",f2fl(obj->mtype.spin_rate.x));
768         sprintf(Ymessage,"%.2f",f2fl(obj->mtype.spin_rate.y));
769         sprintf(Zmessage,"%.2f",f2fl(obj->mtype.spin_rate.z));
770
771         ui_wprintf_at( MattWindow, 10, 132,"&X:" );
772         Xtext = ui_add_gadget_inputbox( MattWindow, 30, 132, MATT_LEN, MATT_LEN, Xmessage );
773
774         ui_wprintf_at( MattWindow, 10, 162,"&Y:" );
775         Ytext = ui_add_gadget_inputbox( MattWindow, 30, 162, MATT_LEN, MATT_LEN, Ymessage );
776
777         ui_wprintf_at( MattWindow, 10, 192,"&Z:" );
778         Ztext = ui_add_gadget_inputbox( MattWindow, 30, 192, MATT_LEN, MATT_LEN, Zmessage );
779
780         ui_gadget_calc_keys(MattWindow);
781
782         MattWindow->keyboard_focus_gadget = (UI_GADGET *) InitialMode[0];
783
784         mprintf((0, "X = %08x, Y = %08x, Z = %08x\n", atoi(Xmessage), atoi(Ymessage), atoi(Zmessage)));
785
786         return 1;
787
788 }
789
790 void do_object_window()
791 {
792         object *obj=&Objects[Cur_object_index];
793
794         if ( MattWindow == NULL ) return;
795
796         //------------------------------------------------------------
797         // Call the ui code..
798         //------------------------------------------------------------
799         ui_button_any_drawn = 0;
800         ui_window_do_gadgets(MattWindow);
801
802
803         if ( QuitButton->pressed || (last_keypress==KEY_ESC))   {
804
805                 if (InitialMode[0]->flag) obj->movement_type = MT_NONE;
806                 if (InitialMode[1]->flag) obj->movement_type = MT_SPINNING;
807
808                 obj->mtype.spin_rate.x = fl2f(atof(Xtext->text));
809                 obj->mtype.spin_rate.y = fl2f(atof(Ytext->text));
810                 obj->mtype.spin_rate.z = fl2f(atof(Ztext->text));
811
812                 object_close_window();
813                 return;
814         }               
815
816         old_object = Cur_object_index;
817 }
818
819 void set_all_modes_to_hover(void)
820 {
821         int     i;
822
823         for (i=0; i<=Highest_object_index; i++)
824                 if (Objects[i].control_type == CT_AI)
825                         Objects[i].ctype.ai_info.behavior = AIB_STILL;
826 }
827