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