home *** CD-ROM | disk | FTP | other *** search
/ Amiga ACS 1998 #6 / amigaacscoverdisc1998-061998.iso / games / descent / source / main / editor / medrobot.c < prev    next >
Text File  |  1998-06-08  |  28KB  |  932 lines

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