home *** CD-ROM | disk | FTP | other *** search
/ Amiga ACS 1998 #6 / amigaacscoverdisc1998-061998.iso / games / descent / source / main / medwall.c < prev    next >
Text File  |  1998-06-08  |  46KB  |  1,546 lines

  1. /*
  2.  * $Source: f:/miner/source/main/editor/rcs/medwall.c $
  3.  * $Revision: 2.0 $
  4.  * $Author: john $
  5.  * $Date: 1995/02/27 11:35:47 $
  6.  * 
  7.  * Created from version 1.11 of main\wall.c
  8.  * 
  9.  * $Log: medwall.c $
  10.  * Revision 2.0  1995/02/27  11:35:47  john
  11.  * Version 2.0! No anonymous unions, Watcom 10.0, with no need
  12.  * for bitmaps.tbl.
  13.  * 
  14.  * Revision 1.71  1995/02/01  16:30:03  yuan
  15.  * Stabilizing triggers and matcens.
  16.  * 
  17.  * Revision 1.70  1995/01/28  15:28:08  yuan
  18.  * Return proper bug description.
  19.  * 
  20.  * Revision 1.69  1995/01/14  19:18:07  john
  21.  * First version of object paging.
  22.  * 
  23.  * Revision 1.68  1995/01/12  12:10:44  yuan
  24.  * Added delete trigger function
  25.  * 
  26.  * Revision 1.67  1994/11/29  16:51:53  yuan
  27.  * Fixed false bogus trigger info.
  28.  * 
  29.  * Revision 1.66  1994/11/27  23:17:29  matt
  30.  * Made changes for new mprintf calling convention
  31.  * 
  32.  * Revision 1.65  1994/11/15  11:59:42  john
  33.  * Changed timing for door to use fixed seconds instead of milliseconds.
  34.  * 
  35.  * Revision 1.64  1994/11/03  10:41:17  yuan
  36.  * Made walls add whichever the previous type was.
  37.  * 
  38.  * Revision 1.63  1994/10/13  13:14:59  yuan
  39.  * Fixed trigger removal bug.
  40.  * 
  41.  * Revision 1.62  1994/10/07  17:43:39  yuan
  42.  * Make validate walls default to 1.
  43.  * 
  44.  * Revision 1.61  1994/10/03  23:40:20  mike
  45.  * Fix hosedness in walls in group copying.
  46.  * 
  47.  * Revision 1.60  1994/09/29  00:20:36  matt
  48.  * Took out reference to unused external wall type
  49.  * 
  50.  * Revision 1.59  1994/09/28  17:32:24  mike
  51.  * Functions to copy walls withing groups.
  52.  * 
  53.  * Revision 1.58  1994/09/28  13:40:46  yuan
  54.  * Fixed control center trigger bug.
  55.  * 
  56.  * Revision 1.57  1994/09/24  12:41:52  matt
  57.  * Took out references to obsolete constants
  58.  * 
  59.  * Revision 1.56  1994/09/23  18:03:55  yuan
  60.  * Finished wall checking code.
  61.  * 
  62.  * Revision 1.55  1994/09/22  14:35:25  matt
  63.  * Made blastable walls work again
  64.  * 
  65.  * Revision 1.54  1994/09/21  16:46:07  yuan
  66.  * Fixed bug that reset wall slot which was just deleted.
  67.  * 
  68.  * Revision 1.53  1994/09/20  18:31:21  yuan
  69.  * Output right Wallnum
  70.  * 
  71.  * Revision 1.52  1994/09/20  18:23:24  yuan
  72.  * Killed the BOGIFYING WALL DRAGON...
  73.  * 
  74.  * There was a problem with triggers being created that had bogus
  75.  * pointers back to their segments.
  76.  * 
  77.  * Revision 1.51  1994/09/20  11:13:11  yuan
  78.  * Delete all bogus walls when checking walls.
  79.  * 
  80.  * Revision 1.50  1994/09/19  23:31:14  yuan
  81.  * Adding wall checking stuff.
  82.  * 
  83.  * Revision 1.49  1994/09/13  21:11:20  matt
  84.  * Added wclips that use tmap1 instead of tmap2, saving lots of merging
  85.  * 
  86.  * Revision 1.48  1994/09/10  13:32:08  matt
  87.  * Made exploding walls a type of blastable walls.
  88.  * Cleaned up blastable walls, making them tmap2 bitmaps.
  89.  * 
  90.  * Revision 1.47  1994/09/10  09:47:47  yuan
  91.  * Added wall checking function.
  92.  * 
  93.  * Revision 1.46  1994/08/26  14:14:56  yuan
  94.  * Fixed wall clip being set to -2 bug.
  95.  * 
  96.  * Revision 1.45  1994/08/25  21:56:26  mike
  97.  * IS_CHILD stuff.
  98.  * 
  99.  * Revision 1.44  1994/08/19  19:30:27  matt
  100.  * Added informative message if wall is already external when making it so.
  101.  * 
  102.  * Revision 1.43  1994/08/17  11:13:46  matt
  103.  * Changed way external walls work
  104.  * 
  105.  * Revision 1.42  1994/08/15  17:47:29  yuan
  106.  * Added external walls
  107.  * 
  108.  * Revision 1.41  1994/08/05  21:18:09  matt
  109.  * Allow two doors to be linked together
  110.  * 
  111.  * Revision 1.40  1994/08/02  14:18:06  mike
  112.  * Clean up dialog boxes.
  113.  * 
  114.  * Revision 1.39  1994/08/01  11:04:33  yuan
  115.  * New materialization centers.
  116.  * 
  117.  * Revision 1.38  1994/07/22  17:19:11  yuan
  118.  * Working on dialog box for refuel/repair/material/control centers.
  119.  * 
  120.  * Revision 1.37  1994/07/20  17:35:33  yuan
  121.  * Added new gold key.
  122.  * 
  123.  * Revision 1.36  1994/07/19  14:31:44  yuan
  124.  * Fixed keys bug.
  125.  * 
  126.  * Revision 1.35  1994/07/18  15:58:31  yuan
  127.  * Hopefully prevent any "Adam door bombouts"
  128.  * 
  129.  * Revision 1.34  1994/07/18  15:48:40  yuan
  130.  * Made minor cosmetic change.
  131.  * 
  132.  * Revision 1.33  1994/07/15  16:09:22  yuan
  133.  * Error checking
  134.  * 
  135.  * Revision 1.32  1994/07/14  16:47:05  yuan
  136.  * Fixed wall dialog for selected dooranims.
  137.  * 
  138.  * Revision 1.31  1994/07/11  15:09:16  yuan
  139.  * Wall anim filenames stored in wclip structure.
  140.  * 
  141.  * Revision 1.30  1994/07/06  10:56:01  john
  142.  * New structures for hostages.
  143.  * 
  144.  * Revision 1.29  1994/07/01  16:35:54  yuan
  145.  * Added key system
  146.  * 
  147.  * Revision 1.28  1994/06/21  18:50:12  john
  148.  * Made ESC key exit dialog.
  149.  * 
  150.  * Revision 1.27  1994/06/20  22:29:59  yuan
  151.  * Fixed crazy runaway trigger bug that Adam found
  152.  * 
  153.  * Revision 1.26  1994/06/01  15:50:25  yuan
  154.  * Added one more door... Needs to be set by bm.c in the future.
  155.  * 
  156.  * Revision 1.25  1994/05/30  20:22:34  yuan
  157.  * New triggers.
  158.  * 
  159.  * Revision 1.24  1994/05/27  10:34:31  yuan
  160.  * Added new Dialog boxes for Walls and Triggers.
  161.  * 
  162.  * Revision 1.23  1994/05/25  18:08:45  yuan
  163.  * Revamping walls and triggers interface.
  164.  * Wall interface complete, but triggers are still in progress.
  165.  * 
  166.  * Revision 1.22  1994/05/18  18:21:56  yuan
  167.  * Fixed delete segment and walls bug.
  168.  * 
  169.  * Revision 1.21  1994/05/11  18:24:29  yuan
  170.  * Oops.. trigger not triggers..
  171.  * 
  172.  * Revision 1.20  1994/05/11  18:23:53  yuan
  173.  * Fixed trigger not set to -1 bug.
  174.  * 
  175.  */
  176.  
  177.  
  178. #pragma off (unreferenced)
  179. static char rcsid[] = "$Id: medwall.c 2.0 1995/02/27 11:35:47 john Exp $";
  180. #pragma on (unreferenced)
  181.  
  182. #include <stdio.h>
  183. #include <stdlib.h>
  184. #include <math.h>
  185. #include <string.h>
  186.  
  187. #include "medwall.h"
  188. #include "inferno.h"
  189. #include "editor\editor.h"
  190. #include "segment.h"
  191. #include "error.h"
  192. #include "gameseg.h"
  193.  
  194. #include "textures.h"
  195. #include "screens.h"
  196. #include "switch.h"
  197. #include "editor\eswitch.h"
  198.  
  199. #include "texmerge.h"
  200. #include "medrobot.h"
  201. #include "timer.h"
  202. #include "mono.h"
  203. //#include "fuelcen.h"
  204. #include "key.h"
  205. #include "ehostage.h"
  206. #include "centers.h"
  207. #include "piggy.h"
  208.  
  209. //-------------------------------------------------------------------------
  210. // Variables for this module...
  211. //-------------------------------------------------------------------------
  212. static UI_WINDOW                 *MainWindow = NULL;
  213. static UI_GADGET_USERBOX    *WallViewBox;
  214. static UI_GADGET_BUTTON     *QuitButton;
  215. static UI_GADGET_CHECKBOX    *DoorFlag[4];
  216. static UI_GADGET_RADIO        *KeyFlag[4];
  217.  
  218. static int old_wall_num;
  219. static fix Time;
  220. static int framenum=0;
  221. static int Current_door_type=1;
  222.  
  223. typedef struct count_wall {
  224.     short wallnum;
  225.     short    segnum,sidenum;    
  226. } count_wall;
  227.  
  228. //---------------------------------------------------------------------
  229. // Add a wall (removable 2 sided)
  230. int add_wall(segment *seg, short side)
  231. {
  232.     int Connectside;
  233.     segment *csegp;
  234.  
  235.     if (Num_walls < MAX_WALLS-2)
  236.       if (IS_CHILD(seg->children[side])) {
  237.         if (seg->sides[side].wall_num == -1) {
  238.              seg->sides[side].wall_num = Num_walls;
  239.             Num_walls++;
  240.             }
  241.                  
  242.         csegp = &Segments[seg->children[side]];
  243.         Connectside = find_connect_side(seg, csegp);
  244.  
  245.         if (csegp->sides[Connectside].wall_num == -1) {
  246.             csegp->sides[Connectside].wall_num = Num_walls;
  247.             Num_walls++;
  248.             }
  249.         
  250.         create_removable_wall( seg, side, CurrentTexture );
  251.         create_removable_wall( csegp, Connectside, CurrentTexture );
  252.  
  253.         return 1;
  254.         }
  255.  
  256.     return 0;
  257. }
  258.  
  259. int wall_assign_door(int door_type)
  260. {
  261.     int Connectside;
  262.     segment *csegp;
  263.  
  264.     if (Cursegp->sides[Curside].wall_num == -1) {
  265.         editor_status("Cannot assign door. No wall at Curside.");
  266.         return 0;
  267.     }
  268.  
  269.     if (Walls[Cursegp->sides[Curside].wall_num].type != WALL_DOOR  &&  Walls[Cursegp->sides[Curside].wall_num].type != WALL_BLASTABLE) {
  270.         editor_status("Cannot assign door. No door at Curside.");
  271.         return 0;
  272.     }
  273.  
  274.     Current_door_type = door_type;
  275.  
  276.      csegp = &Segments[Cursegp->children[Curside]];
  277.      Connectside = find_connect_side(Cursegp, csegp);
  278.     
  279.      Walls[Cursegp->sides[Curside].wall_num].clip_num = door_type;
  280.       Walls[csegp->sides[Connectside].wall_num].clip_num = door_type;
  281.  
  282.     if (WallAnims[door_type].flags & WCF_TMAP1) {
  283.         Cursegp->sides[Curside].tmap_num = WallAnims[door_type].frames[0];
  284.         csegp->sides[Connectside].tmap_num = WallAnims[door_type].frames[0];
  285.         Cursegp->sides[Curside].tmap_num2 = 0;
  286.         csegp->sides[Connectside].tmap_num2 = 0;
  287.     }
  288.     else {
  289.         Cursegp->sides[Curside].tmap_num2 = WallAnims[door_type].frames[0];
  290.         csegp->sides[Connectside].tmap_num2 = WallAnims[door_type].frames[0];
  291.     }
  292.  
  293.     Update_flags |= UF_WORLD_CHANGED;
  294.     return 1;
  295. }
  296.  
  297. int wall_add_blastable()
  298. {
  299.     return wall_add_to_side(Cursegp, Curside, WALL_BLASTABLE);
  300. }
  301.  
  302. int wall_add_door()
  303. {
  304.     return wall_add_to_side(Cursegp, Curside, WALL_DOOR);
  305. }
  306.  
  307. int wall_add_closed_wall()
  308. {
  309.     return wall_add_to_side(Cursegp, Curside, WALL_CLOSED);
  310. }
  311.  
  312. int wall_add_external_wall()
  313. {
  314.     if (Cursegp->children[Curside] == -2) {
  315.         editor_status( "Wall is already external!" );
  316.         return 1;
  317.     }
  318.  
  319.     if (IS_CHILD(Cursegp->children[Curside])) {
  320.         editor_status( "Cannot add external wall here - seg has children" );
  321.         return 0;
  322.     }
  323.  
  324.     Cursegp->children[Curside] = -2;
  325.  
  326.     return 1;
  327. }
  328.  
  329. int wall_add_illusion()
  330. {
  331.     return wall_add_to_side(Cursegp, Curside, WALL_ILLUSION);
  332. }
  333.  
  334. int wall_lock_door()
  335. {
  336.     return wall_add_door_flag(WALL_DOOR_LOCKED);
  337. }
  338.  
  339. int wall_unlock_door()
  340. {
  341.     return wall_remove_door_flag(WALL_DOOR_LOCKED);
  342. }
  343.  
  344. int wall_automate_door()
  345. {
  346.     return wall_add_door_flag(WALL_DOOR_AUTO);
  347. }
  348.     
  349. int wall_deautomate_door()
  350. {
  351.     return wall_remove_door_flag(WALL_DOOR_AUTO);
  352. }
  353.  
  354. int GotoPrevWall() {
  355.     int current_wall;
  356.  
  357.     if (Cursegp->sides[Curside].wall_num < 0)
  358.         current_wall = Num_walls;
  359.     else
  360.         current_wall = Cursegp->sides[Curside].wall_num;
  361.  
  362.     current_wall--;
  363.     if (current_wall < 0) current_wall = Num_walls-1;
  364.     if (current_wall >= Num_walls) current_wall = Num_walls-1;
  365.  
  366.     if (Walls[current_wall].segnum == -1) {
  367.         mprintf((0, "Trying to goto wall at bogus segnum\n"));
  368.         return 0;
  369.     }
  370.  
  371.     if (Walls[current_wall].sidenum == -1) {
  372.         mprintf((0, "Trying to goto wall at bogus sidenum\n"));
  373.         return 0;
  374.     }
  375.  
  376.     Cursegp = &Segments[Walls[current_wall].segnum];
  377.     Curside = Walls[current_wall].sidenum;
  378.  
  379.     return 1;
  380. }
  381.  
  382.  
  383. int GotoNextWall() {
  384.     int current_wall;
  385.  
  386.     current_wall = Cursegp->sides[Curside].wall_num; // It's ok to be -1 because it will immediately become 0
  387.  
  388.     current_wall++;
  389.  
  390.     if (current_wall >= Num_walls) current_wall = 0;
  391.     if (current_wall < 0) current_wall = 0;
  392.  
  393.     if (Walls[current_wall].segnum == -1) {
  394.         mprintf((0, "Trying to goto wall at bogus segnum\n"));
  395.         return 0;
  396.     }
  397.  
  398.     if (Walls[current_wall].sidenum == -1) {
  399.         mprintf((0, "Trying to goto wall at bogus sidenum\n"));
  400.         return 0;
  401.     }
  402.  
  403.     Cursegp = &Segments[Walls[current_wall].segnum];
  404.     Curside = Walls[current_wall].sidenum;    
  405.  
  406.     return 1;
  407. }
  408.  
  409.  
  410. int PrevWall() {
  411.     int wall_type;
  412.  
  413.     if (Cursegp->sides[Curside].wall_num == -1) {
  414.         editor_status("Cannot assign new wall. No wall on curside.");
  415.         return 0;
  416.     }
  417.  
  418.     wall_type = Walls[Cursegp->sides[Curside].wall_num].clip_num;
  419.  
  420.     if (Walls[Cursegp->sides[Curside].wall_num].type == WALL_DOOR) {
  421.  
  422.          do {
  423.  
  424.             wall_type--;
  425.  
  426.             if (wall_type < 0)
  427.                 wall_type = Num_wall_anims-1;
  428.  
  429.             if (wall_type == Walls[Cursegp->sides[Curside].wall_num].clip_num)
  430.                 Error("Cannot find clip for door."); 
  431.  
  432.         } while (WallAnims[wall_type].num_frames == -1 || WallAnims[wall_type].flags & WCF_BLASTABLE);
  433.  
  434.     }
  435.  
  436.     else if (Walls[Cursegp->sides[Curside].wall_num].type == WALL_BLASTABLE) {
  437.  
  438.          do {
  439.  
  440.             wall_type--;
  441.  
  442.             if (wall_type < 0)
  443.                 wall_type = Num_wall_anims-1;
  444.  
  445.             if (wall_type == Walls[Cursegp->sides[Curside].wall_num].clip_num)
  446.                 Error("Cannot find clip for blastable wall."); 
  447.  
  448.         } while (WallAnims[wall_type].num_frames == -1 || !(WallAnims[wall_type].flags & WCF_BLASTABLE));
  449.  
  450.     }
  451.  
  452.     wall_assign_door(wall_type);
  453.  
  454.     Update_flags |= UF_WORLD_CHANGED;
  455.     return 1;
  456. }
  457.  
  458. int NextWall() {
  459.     int wall_type;
  460.  
  461.     if (Cursegp->sides[Curside].wall_num == -1) {
  462.         editor_status("Cannot assign new wall. No wall on curside.");
  463.         return 0;
  464.     }
  465.  
  466.     wall_type = Walls[Cursegp->sides[Curside].wall_num].clip_num;
  467.  
  468.     if (Walls[Cursegp->sides[Curside].wall_num].type == WALL_DOOR) {
  469.  
  470.          do {
  471.  
  472.             wall_type++;
  473.  
  474.             if (wall_type >= Num_wall_anims) {
  475.                 wall_type = 0;
  476.                 if (Walls[Cursegp->sides[Curside].wall_num].clip_num==-1)
  477.                     Error("Cannot find clip for door."); 
  478.             }
  479.  
  480.         } while (WallAnims[wall_type].num_frames == -1 || WallAnims[wall_type].flags & WCF_BLASTABLE);
  481.  
  482.     }
  483.     else if (Walls[Cursegp->sides[Curside].wall_num].type == WALL_BLASTABLE) {
  484.  
  485.          do {
  486.  
  487.             wall_type++;
  488.  
  489.             if (wall_type >= Num_wall_anims) {
  490.                 wall_type = 0;
  491.                 if (Walls[Cursegp->sides[Curside].wall_num].clip_num==-1)
  492.                     Error("Cannot find clip for blastable wall."); 
  493.             }
  494.  
  495.         } while (WallAnims[wall_type].num_frames == -1 || !(WallAnims[wall_type].flags & WCF_BLASTABLE));
  496.  
  497.     }
  498.  
  499.     wall_assign_door(wall_type);    
  500.  
  501.     Update_flags |= UF_WORLD_CHANGED;
  502.     return 1;
  503.  
  504. }
  505.  
  506. //-------------------------------------------------------------------------
  507. // Called from the editor... does one instance of the wall dialog box
  508. //-------------------------------------------------------------------------
  509. int do_wall_dialog()
  510. {
  511.     int i;
  512.  
  513.     // Only open 1 instance of this window...
  514.     if ( MainWindow != NULL ) return 0;
  515.  
  516.     // Close other windows.    
  517.     close_all_windows();
  518.  
  519.     // Open a window with a quit button
  520.     MainWindow = ui_open_window( TMAPBOX_X+20, TMAPBOX_Y+20, 765-TMAPBOX_X, 545-TMAPBOX_Y, WIN_DIALOG );
  521.     QuitButton = ui_add_gadget_button( MainWindow, 20, 252, 48, 40, "Done", NULL );
  522.  
  523.     // These are the checkboxes for each door flag.
  524.     i = 80;
  525.     DoorFlag[0] = ui_add_gadget_checkbox( MainWindow, 22, i, 16, 16, 0, "Locked" ); i += 24;
  526.     DoorFlag[1] = ui_add_gadget_checkbox( MainWindow, 22, i, 16, 16, 0, "Auto" ); i += 24;
  527.     DoorFlag[2] = ui_add_gadget_checkbox( MainWindow, 22, i, 16, 16, 0, "Illusion OFF" ); i += 24;
  528.  
  529.     KeyFlag[0] = ui_add_gadget_radio( MainWindow, 22, i, 16, 16, 0, "NONE" ); i += 24;
  530.     KeyFlag[1] = ui_add_gadget_radio( MainWindow, 22, i, 16, 16, 0, "Blue" ); i += 24;
  531.     KeyFlag[2] = ui_add_gadget_radio( MainWindow, 22, i, 16, 16, 0, "Red" );  i += 24;
  532.     KeyFlag[3] = ui_add_gadget_radio( MainWindow, 22, i, 16, 16, 0, "Yellow" ); i += 24;
  533.  
  534.     // The little box the wall will appear in.
  535.     WallViewBox = ui_add_gadget_userbox( MainWindow, 155, 5, 64, 64 );
  536.  
  537.     // A bunch of buttons...
  538.     i = 80;
  539.     ui_add_gadget_button( MainWindow,155,i,70, 22, "<< Clip", PrevWall );
  540.     ui_add_gadget_button( MainWindow,155+70,i,70, 22, "Clip >>", NextWall );i += 25;        
  541.     ui_add_gadget_button( MainWindow,155,i,140, 22, "Add Blastable", wall_add_blastable ); i += 25;
  542.     ui_add_gadget_button( MainWindow,155,i,140, 22, "Add Door", wall_add_door  );    i += 25;
  543.     ui_add_gadget_button( MainWindow,155,i,140, 22, "Add Illusory", wall_add_illusion);    i += 25;
  544.     ui_add_gadget_button( MainWindow,155,i,140, 22, "Add Closed Wall", wall_add_closed_wall ); i+=25;
  545. //    ui_add_gadget_button( MainWindow,155,i,140, 22, "Restore All Walls", wall_restore_all );    i += 25;
  546.     ui_add_gadget_button( MainWindow,155,i,70, 22, "<< Prev", GotoPrevWall );
  547.     ui_add_gadget_button( MainWindow,155+70,i,70, 22, "Next >>", GotoNextWall );i += 25;
  548.     ui_add_gadget_button( MainWindow,155,i,140, 22, "Remove Wall", wall_remove ); i += 25;
  549.     ui_add_gadget_button( MainWindow,155,i,140, 22, "Bind to Trigger", bind_wall_to_trigger ); i += 25;
  550.     ui_add_gadget_button( MainWindow,155,i,140, 22, "Bind to Control", bind_wall_to_control_center ); i+=25;
  551.     
  552.     old_wall_num = -2;        // Set to some dummy value so everything works ok on the first frame.
  553.  
  554.     return 1;
  555. }
  556.  
  557. void close_wall_window()
  558. {
  559.     if ( MainWindow!=NULL )    {
  560.         ui_close_window( MainWindow );
  561.         MainWindow = NULL;
  562.     }
  563. }
  564.  
  565. void do_wall_window()
  566. {
  567.     int i;
  568.     byte type;
  569.     fix DeltaTime, Temp;
  570.  
  571.     if ( MainWindow == NULL ) return;
  572.  
  573.     //------------------------------------------------------------
  574.     // Call the ui code..
  575.     //------------------------------------------------------------
  576.     ui_button_any_drawn = 0;
  577.     ui_window_do_gadgets(MainWindow);
  578.  
  579.     //------------------------------------------------------------
  580.     // If we change walls, we need to reset the ui code for all
  581.     // of the checkboxes that control the wall flags.  
  582.     //------------------------------------------------------------
  583.     if (old_wall_num != Cursegp->sides[Curside].wall_num) {
  584.         for (    i=0; i < 3; i++ )    {
  585.             DoorFlag[i]->flag = 0;        // Tells ui that this button isn't checked
  586.             DoorFlag[i]->status = 1;    // Tells ui to redraw button
  587.         }
  588.         for (    i=0; i < 4; i++ )    {
  589.             KeyFlag[i]->flag = 0;        // Tells ui that this button isn't checked
  590.             KeyFlag[i]->status = 1;        // Tells ui to redraw button
  591.         }
  592.  
  593.         if ( Cursegp->sides[Curside].wall_num != -1) {
  594.             if (Walls[Cursegp->sides[Curside].wall_num].flags & WALL_DOOR_LOCKED)            
  595.                 DoorFlag[0]->flag = 1;    // Mark this button as checked
  596.             if (Walls[Cursegp->sides[Curside].wall_num].flags & WALL_DOOR_AUTO)
  597.                 DoorFlag[1]->flag = 1;    // Mark this button as checked
  598.             if (Walls[Cursegp->sides[Curside].wall_num].flags & WALL_ILLUSION_OFF)
  599.                 DoorFlag[2]->flag = 1;    // Mark this button as checked
  600.  
  601.             if (Walls[Cursegp->sides[Curside].wall_num].keys & KEY_NONE)
  602.                 KeyFlag[0]->flag = 1;
  603.             if (Walls[Cursegp->sides[Curside].wall_num].keys & KEY_BLUE)
  604.                 KeyFlag[1]->flag = 1;
  605.             if (Walls[Cursegp->sides[Curside].wall_num].keys & KEY_RED)
  606.                 KeyFlag[2]->flag = 1;
  607.             if (Walls[Cursegp->sides[Curside].wall_num].keys & KEY_GOLD)
  608.                 KeyFlag[3]->flag = 1;
  609.         }
  610.     }
  611.     
  612.     //------------------------------------------------------------
  613.     // If any of the checkboxes that control the wallflags are set, then
  614.     // update the corresponding wall flag.
  615.     //------------------------------------------------------------
  616.  
  617.     if (Walls[Cursegp->sides[Curside].wall_num].type == WALL_DOOR) {
  618.         if ( DoorFlag[0]->flag == 1 )    
  619.             Walls[Cursegp->sides[Curside].wall_num].flags |= WALL_DOOR_LOCKED;
  620.         else
  621.             Walls[Cursegp->sides[Curside].wall_num].flags &= ~WALL_DOOR_LOCKED;
  622.         if ( DoorFlag[1]->flag == 1 )    
  623.             Walls[Cursegp->sides[Curside].wall_num].flags |= WALL_DOOR_AUTO;
  624.         else
  625.             Walls[Cursegp->sides[Curside].wall_num].flags &= ~WALL_DOOR_AUTO;
  626.  
  627.         //------------------------------------------------------------
  628.         // If any of the radio buttons that control the mode are set, then
  629.         // update the corresponding key.
  630.         //------------------------------------------------------------
  631.         for (    i=0; i < 4; i++ )    {
  632.             if ( KeyFlag[i]->flag == 1 ) {
  633.                 Walls[Cursegp->sides[Curside].wall_num].keys = 1<<i;        // Set the ai_state to the cooresponding radio button
  634. //                mprintf((0, "1<<%d = %d\n", i, 1<<i));
  635.             }
  636.         }
  637.     } else {
  638.         for (    i=0; i < 2; i++ )    
  639.             if (DoorFlag[i]->flag == 1) { 
  640.                 DoorFlag[i]->flag = 0;        // Tells ui that this button isn't checked
  641.                 DoorFlag[i]->status = 1;    // Tells ui to redraw button
  642.             }
  643.         for (    i=0; i < 4; i++ )    {
  644.             if ( KeyFlag[i]->flag == 1 ) {
  645.                 KeyFlag[i]->flag = 0;        
  646.                 KeyFlag[i]->status = 1;        
  647.             }
  648.         }
  649.     }
  650.  
  651.     if (Walls[Cursegp->sides[Curside].wall_num].type == WALL_ILLUSION) {
  652.         if ( DoorFlag[2]->flag == 1 )    
  653.             Walls[Cursegp->sides[Curside].wall_num].flags |= WALL_ILLUSION_OFF;
  654.         else
  655.             Walls[Cursegp->sides[Curside].wall_num].flags &= ~WALL_ILLUSION_OFF;
  656.     } else 
  657.         for (    i=2; i < 3; i++ )    
  658.             if (DoorFlag[i]->flag == 1) { 
  659.                 DoorFlag[i]->flag = 0;        // Tells ui that this button isn't checked
  660.                 DoorFlag[i]->status = 1;    // Tells ui to redraw button
  661.             }
  662.  
  663.     //------------------------------------------------------------
  664.     // A simple frame time counter for animating the walls...
  665.     //------------------------------------------------------------
  666.     Temp = timer_get_fixed_seconds();
  667.     DeltaTime = Temp - Time;
  668.  
  669.     //------------------------------------------------------------
  670.     // Draw the wall in the little 64x64 box
  671.     //------------------------------------------------------------
  672.       gr_set_current_canvas( WallViewBox->canvas );
  673.     if (Cursegp->sides[Curside].wall_num != -1) {
  674.         type = Walls[Cursegp->sides[Curside].wall_num].type;
  675.         if ((type == WALL_DOOR) || (type == WALL_BLASTABLE)) {
  676.             if (DeltaTime > ((F1_0*200)/1000)) {
  677.                 framenum++;
  678.                 Time = Temp;
  679.             }
  680.             if (framenum >= WallAnims[Walls[Cursegp->sides[Curside].wall_num].clip_num].num_frames)
  681.                 framenum=0;
  682.             PIGGY_PAGE_IN(Textures[WallAnims[Walls[Cursegp->sides[Curside].wall_num].clip_num].frames[framenum]]);
  683.             gr_ubitmap(0,0, &GameBitmaps[Textures[WallAnims[Walls[Cursegp->sides[Curside].wall_num].clip_num].frames[framenum]].index]);
  684.         } else {
  685.             if (type == WALL_OPEN)
  686.                 gr_clear_canvas( CBLACK );
  687.             else {
  688.                 if (Cursegp->sides[Curside].tmap_num2 > 0)
  689.                     gr_ubitmap(0,0, texmerge_get_cached_bitmap( Cursegp->sides[Curside].tmap_num, Cursegp->sides[Curside].tmap_num2));
  690.                 else    {
  691.                     PIGGY_PAGE_IN(Textures[Cursegp->sides[Curside].tmap_num]);
  692.                     gr_ubitmap(0,0, &GameBitmaps[Textures[Cursegp->sides[Curside].tmap_num].index]);
  693.                 }
  694.             }
  695.         }
  696.     } else
  697.         gr_clear_canvas( CGREY );
  698.  
  699.     //------------------------------------------------------------
  700.     // If anything changes in the ui system, redraw all the text that
  701.     // identifies this wall.
  702.     //------------------------------------------------------------
  703.     if (ui_button_any_drawn || (old_wall_num != Cursegp->sides[Curside].wall_num) )    {
  704.         if ( Cursegp->sides[Curside].wall_num > -1 )    {
  705.             ui_wprintf_at( MainWindow, 12, 6, "Wall: %d    ", Cursegp->sides[Curside].wall_num);
  706.             switch (Walls[Cursegp->sides[Curside].wall_num].type) {
  707.                 case WALL_NORMAL:
  708.                     ui_wprintf_at( MainWindow, 12, 23, " Type: Normal   " );
  709.                     break;
  710.                 case WALL_BLASTABLE:
  711.                     ui_wprintf_at( MainWindow, 12, 23, " Type: Blastable" );
  712.                     break;
  713.                 case WALL_DOOR:
  714.                     ui_wprintf_at( MainWindow, 12, 23, " Type: Door     " );
  715.                     ui_wprintf_at( MainWindow, 223, 6, "%s", WallAnims[Walls[Cursegp->sides[Curside].wall_num].clip_num].filename);
  716.                     break;
  717.                 case WALL_ILLUSION:
  718.                     ui_wprintf_at( MainWindow, 12, 23, " Type: Illusion " );
  719.                     break;
  720.                 case WALL_OPEN:
  721.                     ui_wprintf_at( MainWindow, 12, 23, " Type: Open     " );
  722.                     break;
  723.                 case WALL_CLOSED:
  724.                     ui_wprintf_at( MainWindow, 12, 23, " Type: Closed   " );
  725.                     break;
  726.                 default:
  727.                     ui_wprintf_at( MainWindow, 12, 23, " Type: Unknown  " );
  728.                     break;
  729.             }            
  730.             if (Walls[Cursegp->sides[Curside].wall_num].type != WALL_DOOR)
  731.                     ui_wprintf_at( MainWindow, 223, 6, "            " );
  732.  
  733.             ui_wprintf_at( MainWindow, 12, 40, " Clip: %d   ", Walls[Cursegp->sides[Curside].wall_num].clip_num );
  734.             ui_wprintf_at( MainWindow, 12, 57, " Trigger: %d  ", Walls[Cursegp->sides[Curside].wall_num].trigger );
  735.         }    else {
  736.             ui_wprintf_at( MainWindow, 12, 6, "Wall: none ");
  737.             ui_wprintf_at( MainWindow, 12, 23, " Type: none ");
  738.             ui_wprintf_at( MainWindow, 12, 40, " Clip: none   ");
  739.             ui_wprintf_at( MainWindow, 12, 57, " Trigger: none  ");
  740.         }
  741.         Update_flags |= UF_WORLD_CHANGED;
  742.     }
  743.     if ( QuitButton->pressed || (last_keypress==KEY_ESC) )    {
  744.         close_wall_window();
  745.         return;
  746.     }        
  747.  
  748.     old_wall_num = Cursegp->sides[Curside].wall_num;
  749. }
  750.  
  751.  
  752. //---------------------------------------------------------------------
  753. // Restore all walls to original status (closed doors, repaired walls)
  754. int wall_restore_all()
  755. {
  756.     int i, j;
  757.     int wall_num;
  758.  
  759.     for (i=0;i<Num_walls;i++) {
  760.         if (Walls[i].flags & WALL_BLASTED) {
  761.             Walls[i].hps = WALL_HPS;
  762.             Walls[i].flags &= ~WALL_BLASTED;
  763.         }
  764.         if (Walls[i].flags & WALL_DOOR_OPENED)
  765.             Walls[i].flags &= ~WALL_DOOR_OPENED;
  766.         if (Walls[i].flags & WALL_DOOR_OPENING)
  767.             Walls[i].flags &= ~WALL_DOOR_OPENING;
  768.     }
  769.  
  770.     for (i=0;i<Num_open_doors;i++)
  771.         wall_close_door(i);
  772.  
  773.     for (i=0;i<Num_segments;i++)
  774.         for (j=0;j<MAX_SIDES_PER_SEGMENT;j++) {
  775.             wall_num = Segments[i].sides[j].wall_num;
  776.             if (wall_num != -1)
  777.                 if ((Walls[wall_num].type == WALL_BLASTABLE) ||
  778.                      (Walls[wall_num].type == WALL_DOOR))
  779.                     Segments[i].sides[j].tmap_num2 = WallAnims[Walls[wall_num].clip_num].frames[0];
  780.          }
  781.  
  782.     for (i=0;i<Num_triggers;i++)
  783.         Triggers[i].flags |= TRIGGER_ON;
  784.     
  785.     Update_flags |= UF_GAME_VIEW_CHANGED;
  786.  
  787.     return 1;
  788. }
  789.  
  790.  
  791. //---------------------------------------------------------------------
  792. //    Delete a specific wall.
  793. int wall_delete_bogus(short wall_num)
  794. {
  795.     int w;
  796.     int seg, side;
  797.  
  798.     if ((Walls[wall_num].segnum != -1) && (Walls[wall_num].sidenum != -1)) {
  799.         mprintf((0,"WALL IS NOT BOGUS.\n"));
  800.         return 0;
  801.     }
  802.  
  803.     // Delete bogus wall and slide all above walls down one slot
  804.     for (w=wall_num; w<Num_walls; w++) {
  805.         Walls[w] = Walls[w+1];
  806.     }
  807.         
  808.     Num_walls--;
  809.  
  810.     for (seg=0;seg<=Highest_segment_index;seg++)
  811.         if (Segments[seg].segnum != -1)
  812.         for (side=0;side<MAX_SIDES_PER_SEGMENT;side++)
  813.             if    (Segments[seg].sides[side].wall_num > wall_num)
  814.                 Segments[seg].sides[side].wall_num--;
  815.  
  816.     mprintf((0,"BOGUS WALL DELETED!!!!\n"));
  817.  
  818.     return 1;
  819. }
  820.  
  821.  
  822. //---------------------------------------------------------------------
  823. //    Remove a specific side.
  824. int wall_remove_side(segment *seg, short side)
  825. {
  826.     int Connectside;
  827.     segment *csegp;
  828.     int lower_wallnum;
  829.     int w, s, t, l, t1;
  830.  
  831.     if (IS_CHILD(seg->children[side]) && IS_CHILD(seg->sides[side].wall_num)) {
  832.         csegp = &Segments[seg->children[side]];
  833.         Connectside = find_connect_side(seg, csegp);
  834.  
  835.         remove_trigger(seg, side);
  836.         remove_trigger(csegp, Connectside);
  837.  
  838.         // Remove walls 'wall_num' and connecting side 'wall_num'
  839.         //  from Walls array.  
  840.          lower_wallnum = seg->sides[side].wall_num;
  841.         if (csegp->sides[Connectside].wall_num < lower_wallnum)
  842.              lower_wallnum = csegp->sides[Connectside].wall_num;
  843.  
  844.         if (Walls[lower_wallnum].linked_wall != -1)
  845.             Walls[Walls[lower_wallnum].linked_wall].linked_wall = -1;
  846.         if (Walls[lower_wallnum+1].linked_wall != -1)
  847.             Walls[Walls[lower_wallnum+1].linked_wall].linked_wall = -1;
  848.  
  849.         for (w=lower_wallnum;w<Num_walls-2;w++)
  850.             Walls[w] = Walls[w+2];
  851.  
  852.         Num_walls -= 2;
  853.  
  854.         for (s=0;s<=Highest_segment_index;s++)
  855.             if (Segments[s].segnum != -1)
  856.             for (w=0;w<MAX_SIDES_PER_SEGMENT;w++)
  857.                 if    (Segments[s].sides[w].wall_num > lower_wallnum+1)
  858.                     Segments[s].sides[w].wall_num -= 2;
  859.  
  860.         // Destroy any links to the deleted wall.
  861.         for (t=0;t<Num_triggers;t++)
  862.             for (l=0;l<Triggers[t].num_links;l++)
  863.                 if ((Triggers[t].seg[l] == seg-Segments) && (Triggers[t].side[l] == side)) {
  864.                     for (t1=0;t1<Triggers[t].num_links-1;t1++) {
  865.                         Triggers[t].seg[t1] = Triggers[t].seg[t1+1];
  866.                         Triggers[t].side[t1] = Triggers[t].side[t1+1];
  867.                     }
  868.                     Triggers[t].num_links--;    
  869.                 }
  870.  
  871.         // Destroy control center links as well.
  872.         for (l=0;l<ControlCenterTriggers.num_links;l++)
  873.             if ((ControlCenterTriggers.seg[l] == seg-Segments) && (ControlCenterTriggers.side[l] == side)) {
  874.                 for (t1=0;t1<ControlCenterTriggers.num_links-1;t1++) {
  875.                     ControlCenterTriggers.seg[t1] = ControlCenterTriggers.seg[t1+1];
  876.                     ControlCenterTriggers.side[t1] = ControlCenterTriggers.side[t1+1];
  877.                 }
  878.                 ControlCenterTriggers.num_links--;    
  879.             }
  880.  
  881.         seg->sides[side].wall_num = -1;
  882.         csegp->sides[Connectside].wall_num = -1;
  883.  
  884.         Update_flags |= UF_WORLD_CHANGED;
  885.         return 1;
  886.     }
  887.  
  888.     editor_status( "Can't remove wall.  No wall present.");
  889.     return 0;
  890. }
  891.  
  892. //---------------------------------------------------------------------
  893. //    Remove a special wall.
  894. int wall_remove()
  895. {
  896.     return wall_remove_side(Cursegp, Curside);
  897. }
  898.  
  899. //---------------------------------------------------------------------
  900. // Add a wall to curside
  901. int wall_add_to_side(segment *segp, int side, byte type)
  902. {
  903.     int connectside;
  904.     segment *csegp;
  905.  
  906.     if (add_wall(segp, side)) {
  907.         csegp = &Segments[segp->children[side]];
  908.         connectside = find_connect_side(segp, csegp);
  909.  
  910.         Walls[segp->sides[side].wall_num].segnum = segp-Segments;
  911.         Walls[csegp->sides[connectside].wall_num].segnum = csegp-Segments;
  912.  
  913.         Walls[segp->sides[side].wall_num].sidenum = side;
  914.         Walls[csegp->sides[connectside].wall_num].sidenum = connectside;
  915.  
  916.           Walls[segp->sides[side].wall_num].flags = 0;
  917.         Walls[csegp->sides[connectside].wall_num].flags = 0;
  918.  
  919.           Walls[segp->sides[side].wall_num].type = type;
  920.         Walls[csegp->sides[connectside].wall_num].type = type;
  921.  
  922. //        Walls[segp->sides[side].wall_num].trigger = -1;
  923. //        Walls[csegp->sides[connectside].wall_num].trigger = -1;
  924.  
  925.         Walls[segp->sides[side].wall_num].clip_num = -1;
  926.         Walls[csegp->sides[connectside].wall_num].clip_num = -1;
  927.  
  928.         Walls[segp->sides[side].wall_num].keys = KEY_NONE;
  929.         Walls[csegp->sides[connectside].wall_num].keys = KEY_NONE;
  930.  
  931.         if (type == WALL_BLASTABLE) {
  932.               Walls[segp->sides[side].wall_num].hps = WALL_HPS;
  933.             Walls[csegp->sides[connectside].wall_num].hps = WALL_HPS;
  934.             
  935.               //Walls[segp->sides[side].wall_num].clip_num = 0;
  936.             //Walls[csegp->sides[connectside].wall_num].clip_num = 0;
  937.             }    
  938.  
  939.         if (type != WALL_DOOR) {
  940.             segp->sides[side].tmap_num2 = 0;
  941.             csegp->sides[connectside].tmap_num2 = 0;
  942.             }
  943.  
  944.         if (type == WALL_DOOR) {
  945.               Walls[segp->sides[side].wall_num].flags |= WALL_DOOR_AUTO;
  946.             Walls[csegp->sides[connectside].wall_num].flags |= WALL_DOOR_AUTO;
  947.  
  948.             Walls[segp->sides[side].wall_num].clip_num = Current_door_type;
  949.             Walls[csegp->sides[connectside].wall_num].clip_num = Current_door_type;
  950.         }
  951.  
  952.         //Update_flags |= UF_WORLD_CHANGED;
  953.         //return 1;
  954.  
  955. //        return NextWall();        //assign a clip num
  956.         return wall_assign_door(Current_door_type);
  957.  
  958.     } else {
  959.         editor_status( "Cannot add wall here, no children" );
  960.         return 0;
  961.     }
  962. }
  963.  
  964.  
  965. //---------------------------------------------------------------------
  966. // Add a wall to markedside
  967. int wall_add_to_markedside(byte type)
  968. {
  969.     int Connectside;
  970.     segment *csegp;
  971.  
  972.     if (add_wall(Markedsegp, Markedside)) {
  973.         int    wall_num, cwall_num;
  974.         csegp = &Segments[Markedsegp->children[Markedside]];
  975.  
  976.         Connectside = find_connect_side(Markedsegp, csegp);
  977.  
  978.         wall_num = Markedsegp->sides[Markedside].wall_num;
  979.         cwall_num = csegp->sides[Connectside].wall_num;
  980.  
  981.         Walls[wall_num].segnum = Markedsegp-Segments;
  982.         Walls[cwall_num].segnum = csegp-Segments;
  983.  
  984.         Walls[wall_num].sidenum = Markedside;
  985.         Walls[cwall_num].sidenum = Connectside;
  986.  
  987.           Walls[wall_num].flags = 0;
  988.         Walls[cwall_num].flags = 0;
  989.  
  990.           Walls[wall_num].type = type;
  991.         Walls[cwall_num].type = type;
  992.  
  993.         Walls[wall_num].trigger = -1;
  994.         Walls[cwall_num].trigger = -1;
  995.  
  996.         Walls[wall_num].clip_num = -1;
  997.         Walls[cwall_num].clip_num = -1;
  998.  
  999.         Walls[wall_num].keys = KEY_NONE;
  1000.         Walls[cwall_num].keys = KEY_NONE;
  1001.  
  1002.         if (type == WALL_BLASTABLE) {
  1003.               Walls[wall_num].hps = WALL_HPS;
  1004.             Walls[cwall_num].hps = WALL_HPS;
  1005.             
  1006.               Walls[wall_num].clip_num = 0;
  1007.             Walls[cwall_num].clip_num = 0;
  1008.             }    
  1009.  
  1010.         if (type != WALL_DOOR) {
  1011.             Markedsegp->sides[Markedside].tmap_num2 = 0;
  1012.             csegp->sides[Connectside].tmap_num2 = 0;
  1013.             }
  1014.  
  1015.         Update_flags |= UF_WORLD_CHANGED;
  1016.         return 1;
  1017.     } else {
  1018.         editor_status( "Cannot add wall here, no children" );
  1019.         return 0;
  1020.     }
  1021. }
  1022.  
  1023.  
  1024. int wall_add_door_flag(byte flag)
  1025. {
  1026.     int Connectside;
  1027.     segment *csegp;
  1028.  
  1029.     if (Cursegp->sides[Curside].wall_num == -1)
  1030.         {
  1031.         editor_status("Cannot change flag. No wall at Curside.");
  1032.         return 0;
  1033.         }
  1034.  
  1035.     if (Walls[Cursegp->sides[Curside].wall_num].type != WALL_DOOR)
  1036.         {
  1037.         editor_status("Cannot change flag. No door at Curside.");
  1038.         return 0;
  1039.         }
  1040.  
  1041.      csegp = &Segments[Cursegp->children[Curside]];
  1042.      Connectside = find_connect_side(Cursegp, csegp);
  1043.  
  1044.      Walls[Cursegp->sides[Curside].wall_num].flags |= flag;
  1045.       Walls[csegp->sides[Connectside].wall_num].flags |= flag;
  1046.  
  1047.     Update_flags |= UF_ED_STATE_CHANGED;
  1048.     return 1;
  1049. }
  1050.  
  1051. int wall_remove_door_flag(byte flag)
  1052. {
  1053.     int Connectside;
  1054.     segment *csegp;
  1055.  
  1056.     if (Cursegp->sides[Curside].wall_num == -1)
  1057.         {
  1058.         editor_status("Cannot change flag. No wall at Curside.");
  1059.         return 0;
  1060.         }
  1061.  
  1062.     if (Walls[Cursegp->sides[Curside].wall_num].type != WALL_DOOR)
  1063.         {
  1064.         editor_status("Cannot change flag. No door at Curside.");
  1065.         return 0;
  1066.         }
  1067.  
  1068.      csegp = &Segments[Cursegp->children[Curside]];
  1069.      Connectside = find_connect_side(Cursegp, csegp);
  1070.  
  1071.      Walls[Cursegp->sides[Curside].wall_num].flags &= ~flag;
  1072.       Walls[csegp->sides[Connectside].wall_num].flags &= ~flag;
  1073.  
  1074.     Update_flags |= UF_ED_STATE_CHANGED;
  1075.     return 1;
  1076. }
  1077.  
  1078.  
  1079. int bind_wall_to_control_center() {
  1080.  
  1081.     int link_num;
  1082.     int i;
  1083.  
  1084.     if (Cursegp->sides[Curside].wall_num == -1) {
  1085.         editor_status("No wall at Curside.");
  1086.         return 0;
  1087.     }
  1088.  
  1089.     link_num = ControlCenterTriggers.num_links;
  1090.     for (i=0;i<link_num;i++)
  1091.         if ((Cursegp-Segments == ControlCenterTriggers.seg[i]) && (Curside == ControlCenterTriggers.side[i])) {
  1092.             editor_status("Curside already bound to Control Center.");
  1093.             return 0;
  1094.         }
  1095.  
  1096.     // Error checking completed, actual binding begins
  1097.     ControlCenterTriggers.seg[link_num] = Cursegp - Segments;
  1098.     ControlCenterTriggers.side[link_num] = Curside;
  1099.     ControlCenterTriggers.num_links++;
  1100.  
  1101.     mprintf((0, "seg %d:side %d linked to control center link_num %d\n",
  1102.                 ControlCenterTriggers.seg[link_num], ControlCenterTriggers.side[link_num], link_num)); 
  1103.  
  1104.     editor_status("Wall linked to control center");
  1105.  
  1106.     return 1;
  1107. }
  1108.  
  1109. //link two doors, curseg/curside and markedseg/markedside
  1110. wall_link_doors()
  1111. {
  1112.     wall *w1=NULL,*w2=NULL;
  1113.  
  1114.     if (Cursegp->sides[Curside].wall_num != -1)
  1115.         w1 = &Walls[Cursegp->sides[Curside].wall_num];
  1116.  
  1117.     if (Markedsegp->sides[Markedside].wall_num != -1)
  1118.         w2 = &Walls[Markedsegp->sides[Markedside].wall_num];
  1119.  
  1120.     if (!w1 || w1->type != WALL_DOOR) {
  1121.         editor_status("Curseg/curside is not a door");
  1122.         return 0;
  1123.     }
  1124.  
  1125.     if (!w2 || w2->type != WALL_DOOR) {
  1126.         editor_status("Markedseg/markedside is not a door");
  1127.         return 0;
  1128.     }
  1129.  
  1130.     if (w1->linked_wall != -1)
  1131.         editor_status("Curseg/curside is already linked");
  1132.  
  1133.     if (w2->linked_wall != -1)
  1134.         editor_status("Markedseg/markedside is already linked");
  1135.  
  1136.     w1->linked_wall = w2-Walls;
  1137.     w2->linked_wall = w1-Walls;
  1138.  
  1139.     return 1;
  1140. }
  1141.  
  1142. wall_unlink_door()
  1143. {
  1144.     wall *w1=NULL;
  1145.  
  1146.     if (Cursegp->sides[Curside].wall_num != -1)
  1147.         w1 = &Walls[Cursegp->sides[Curside].wall_num];
  1148.  
  1149.     if (!w1 || w1->type != WALL_DOOR) {
  1150.         editor_status("Curseg/curside is not a door");
  1151.         return 0;
  1152.     }
  1153.  
  1154.     if (w1->linked_wall == -1)
  1155.         editor_status("Curseg/curside is not linked");
  1156.  
  1157.     Assert(Walls[w1->linked_wall].linked_wall == w1-Walls);
  1158.  
  1159.     Walls[w1->linked_wall].linked_wall = -1;
  1160.     w1->linked_wall = -1;
  1161.  
  1162.     return 1;
  1163.  
  1164. }
  1165.  
  1166. #define    DIAGNOSTIC_MESSAGE_MAX                150
  1167.  
  1168. int check_walls() 
  1169. {
  1170.     int w, seg, side, wall_count, trigger_count;
  1171.     int w1, w2, t, l;
  1172.     count_wall CountedWalls[MAX_WALLS];
  1173.     char Message[DIAGNOSTIC_MESSAGE_MAX];
  1174.     int matcen_num;
  1175.  
  1176.     wall_count = 0;
  1177.     for (seg=0;seg<=Highest_segment_index;seg++) 
  1178.         if (Segments[seg].segnum != -1) {
  1179.             // Check fuelcenters
  1180.             matcen_num = Segments[seg].matcen_num;
  1181.             if (matcen_num == 0)
  1182.                 if (RobotCenters[0].segnum != seg) {
  1183.                     mprintf((0,"Fixing Matcen 0\n"));
  1184.                      Segments[seg].matcen_num = -1;
  1185.                 }
  1186.     
  1187.             if (matcen_num > -1)
  1188.                 if (RobotCenters[matcen_num].segnum != seg) {
  1189.                     mprintf((0,"Matcen [%d] (seg %d) doesn't point back to correct segment %d\n", matcen_num, RobotCenters[matcen_num].segnum, seg));
  1190.                     mprintf((0,"Fixing....\n"));
  1191.                     RobotCenters[matcen_num].segnum = seg;
  1192.                 }
  1193.     
  1194.             for (side=0;side<MAX_SIDES_PER_SEGMENT;side++)
  1195.                 if (Segments[seg].sides[side].wall_num != -1) {
  1196.                     CountedWalls[wall_count].wallnum = Segments[seg].sides[side].wall_num;
  1197.                     CountedWalls[wall_count].segnum = seg;
  1198.                     CountedWalls[wall_count].sidenum = side;
  1199.     
  1200.                     // Check if segnum is bogus
  1201.                     if (Walls[Segments[seg].sides[side].wall_num].segnum == -1) {
  1202.                         mprintf((0, "Wall %d at seg:side %d:%d is BOGUS\n", Segments[seg].sides[side].wall_num, seg, side));
  1203.                     }
  1204.     
  1205.                     if (Walls[Segments[seg].sides[side].wall_num].type == WALL_NORMAL) {
  1206.                         mprintf((0, "Wall %d at seg:side %d:%d is NORMAL (BAD)\n", Segments[seg].sides[side].wall_num, seg, side));
  1207.                     }
  1208.     
  1209.                     wall_count++;
  1210.                 }
  1211.         }
  1212.  
  1213.     mprintf((0,"Wall Count = %d\n", wall_count));
  1214.     
  1215.     if (wall_count != Num_walls) {
  1216.         sprintf( Message, "Num_walls is bogus\nDo you wish to correct it?\n");
  1217.         if (MessageBox( -2, -2, 2, Message, "Yes", "No" )==1) {
  1218.             Num_walls = wall_count;
  1219.             editor_status("Num_walls set to %d\n", Num_walls);
  1220.         }
  1221.     }
  1222.  
  1223.     // Check validity of Walls array.
  1224.     for (w=0; w<Num_walls; w++) {
  1225.         if ((Walls[CountedWalls[w].wallnum].segnum != CountedWalls[w].segnum) ||
  1226.             (Walls[CountedWalls[w].wallnum].sidenum != CountedWalls[w].sidenum)) {
  1227.             mprintf((0,"Unmatched walls on wall_num %d\n", CountedWalls[w].wallnum));
  1228.             sprintf( Message, "Unmatched wall detected\nDo you wish to correct it?\n");
  1229.             if (MessageBox( -2, -2, 2, Message, "Yes", "No" )==1) {
  1230.                 Walls[CountedWalls[w].wallnum].segnum = CountedWalls[w].segnum;
  1231.                 Walls[CountedWalls[w].wallnum].sidenum = CountedWalls[w].sidenum;
  1232.             }
  1233.         }
  1234.  
  1235.         if (CountedWalls[w].wallnum >= Num_walls)
  1236.             mprintf((0,"wallnum %d in Segments exceeds Num_walls!\n", CountedWalls[w].wallnum));
  1237.  
  1238.         if (Walls[w].segnum == -1) {
  1239.             mprintf((0, "Wall[%d] is BOGUS\n", w));
  1240.             for (seg=0;seg<=Highest_segment_index;seg++) 
  1241.                 for (side=0;side<MAX_SIDES_PER_SEGMENT;side++)
  1242.                     if (Segments[seg].sides[side].wall_num == w) {
  1243.                         mprintf((0, " BOGUS WALL found at seg:side %d:%d\n", seg, side));
  1244.                     } 
  1245.         }                
  1246.     }
  1247.  
  1248.     trigger_count = 0;
  1249.     for (w1=0; w1<wall_count; w1++) {
  1250.         for (w2=w1+1; w2<wall_count; w2++) 
  1251.             if (CountedWalls[w1].wallnum == CountedWalls[w2].wallnum) {
  1252.                 mprintf((0, "Duplicate Walls %d and %d. Wallnum=%d. ", w1, w2, CountedWalls[w1].wallnum));
  1253.                 mprintf((0, "Seg1:sides1 %d:%d  ", CountedWalls[w1].segnum, CountedWalls[w1].sidenum));
  1254.                 mprintf((0, "Seg2:sides2 %d:%d\n", CountedWalls[w2].segnum, CountedWalls[w2].sidenum));
  1255.             }
  1256.         if (Walls[w1].trigger != -1) trigger_count++;
  1257.     }
  1258.  
  1259.     if (trigger_count != Num_triggers) {
  1260.         sprintf( Message, "Num_triggers is bogus\nDo you wish to correct it?\n");
  1261.         if (MessageBox( -2, -2, 2, Message, "Yes", "No" )==1) {
  1262.             Num_triggers = trigger_count;
  1263.             editor_status("Num_triggers set to %d\n", Num_triggers);
  1264.         }
  1265.     }
  1266.  
  1267.     mprintf((0,"Trigger Count = %d\n", trigger_count));
  1268.  
  1269.     for (t=0; t<trigger_count; t++) {
  1270.         if (Triggers[t].flags & TRIGGER_MATCEN)
  1271.             if (Triggers[t].num_links < 1) 
  1272.                 mprintf((0,"No valid links on Matcen Trigger %d\n", t));
  1273.             else
  1274.                 for (l=0;l<Triggers[t].num_links;l++) {
  1275.                     if (!Segments[Triggers[t].seg[l]].special & SEGMENT_IS_ROBOTMAKER)
  1276.                         mprintf((0,"Bogus Matcen trigger detected on Trigger %d, No matcen at seg %d\n", t, Triggers[t].seg[l]));
  1277.                 }
  1278.  
  1279.         if (Triggers[t].flags & TRIGGER_EXIT)
  1280.             if (Triggers[t].num_links != 0)
  1281.                 mprintf((0,"Bogus links detected on Exit Trigger %d\n", t));
  1282.  
  1283.         if (Triggers[t].flags & TRIGGER_CONTROL_DOORS)
  1284.             for (l=0;l<Triggers[t].num_links;l++) {
  1285.                 if (Segments[Triggers[t].seg[l]].sides[Triggers[t].side[l]].wall_num == -1) {
  1286.                     mprintf((0,"Bogus Link detected on Door Control Trigger %d, link %d\n", t, l));
  1287.                     mprintf((0,"Bogus Link at seg %d, side %d\n", Triggers[t].seg[l], Triggers[t].side[l]));
  1288.                 }
  1289.             }
  1290.     }
  1291.  
  1292.     for (l=0;l<ControlCenterTriggers.num_links;l++)
  1293.         if (Segments[ControlCenterTriggers.seg[l]].sides[ControlCenterTriggers.side[l]].wall_num == -1) {
  1294.             mprintf((0,"Bogus Link detected on Control Center Trigger, link %d\n", l));
  1295.             mprintf((0,"Bogus Link at seg %d, side %d\n", Triggers[t].seg[l], Triggers[t].side[l]));
  1296.         }
  1297.  
  1298.     return 1;
  1299.  
  1300. }
  1301.  
  1302.  
  1303. int delete_all_walls() 
  1304. {
  1305.     char Message[DIAGNOSTIC_MESSAGE_MAX];
  1306.     int seg, side;
  1307.  
  1308.     sprintf( Message, "Are you sure that walls are hosed so\n badly that you want them ALL GONE!?\n");
  1309.     if (MessageBox( -2, -2, 2, Message, "YES!", "No" )==1) {
  1310.         for (seg=0;seg<=Highest_segment_index;seg++)
  1311.             for (side=0;side<MAX_SIDES_PER_SEGMENT;side++)
  1312.                 Segments[seg].sides[side].wall_num = -1;
  1313.         Num_walls=0;
  1314.         Num_triggers=0;
  1315.  
  1316.         return 1;
  1317.     }
  1318.  
  1319.     return 0;
  1320. }
  1321.  
  1322. int delete_all_triggers()
  1323. {
  1324.     char Message[DIAGNOSTIC_MESSAGE_MAX];
  1325.     int w;
  1326.  
  1327.     sprintf( Message, "Are you sure that triggers are hosed so\n badly that you want them ALL GONE!?\n");
  1328.     if (MessageBox( -2, -2, 2, Message, "YES!", "No" )==1) {
  1329.  
  1330.         for (w=0; w<Num_walls; w++)
  1331.             Walls[w].trigger=-1;
  1332.         Num_triggers=0;
  1333.  
  1334.         return 1;
  1335.     }
  1336.  
  1337.     return 0;
  1338. }
  1339.  
  1340. int dump_walls_info() 
  1341. {
  1342.     int w; 
  1343.     FILE *fp;
  1344.  
  1345.     fp = fopen("WALL.OUT", "wt");
  1346.  
  1347.     fprintf(fp, "Num_walls %d\n", Num_walls);
  1348.  
  1349.     for (w=0; w<Num_walls; w++) {
  1350.  
  1351.         fprintf(fp, "WALL #%d\n", w);
  1352.         fprintf(fp, "  seg: %d\n", Walls[w].segnum);
  1353.         fprintf(fp, "  sidenum: %d\n", Walls[w].sidenum);
  1354.     
  1355.         switch (Walls[w].type) {
  1356.             case WALL_NORMAL:
  1357.                 fprintf(fp, "  type: NORMAL\n");
  1358.                 break;
  1359.             case WALL_BLASTABLE:
  1360.                 fprintf(fp, "  type: BLASTABLE\n");
  1361.                 break;
  1362.             case WALL_DOOR:
  1363.                 fprintf(fp, "  type: DOOR\n");
  1364.                 break;
  1365.             case WALL_ILLUSION:
  1366.                 fprintf(fp, "  type: ILLUSION\n");
  1367.                 break;
  1368.             case WALL_OPEN:
  1369.                 fprintf(fp, "  type: OPEN\n");
  1370.                 break;
  1371.             case WALL_CLOSED:
  1372.                 fprintf(fp, "  type: CLOSED\n");
  1373.                 break;
  1374.             default:
  1375.                 fprintf(fp, "  type: ILLEGAL!!!!! <-----------------\n");
  1376.                 break;
  1377.         }
  1378.     
  1379.         fprintf(fp, "  flags:\n");
  1380.  
  1381.         if (Walls[w].flags & WALL_BLASTED)
  1382.             fprintf(fp, "   BLASTED\n");
  1383.         if (Walls[w].flags & WALL_DOOR_OPENED)
  1384.             fprintf(fp, "   DOOR_OPENED <----------------- BAD!!!\n");
  1385.         if (Walls[w].flags & WALL_DOOR_OPENING)
  1386.             fprintf(fp, "   DOOR_OPENING <---------------- BAD!!!\n");
  1387.         if (Walls[w].flags & WALL_DOOR_LOCKED)
  1388.             fprintf(fp, "   DOOR_LOCKED\n");
  1389.         if (Walls[w].flags & WALL_DOOR_AUTO)
  1390.             fprintf(fp, "   DOOR_AUTO\n");
  1391.         if (Walls[w].flags & WALL_ILLUSION_OFF)
  1392.             fprintf(fp, "   ILLUSION_OFF <---------------- OUTDATED\n");
  1393.         //if (Walls[w].flags & WALL_FUELCEN)
  1394.         //    fprintf(fp, "   FUELCEN <--------------------- OUTDATED\n");
  1395.  
  1396.         fprintf(fp, "  trigger: %d\n", Walls[w].trigger);
  1397.         fprintf(fp, "  clip_num: %d\n", Walls[w].clip_num);
  1398.  
  1399.         switch (Walls[w].keys) {
  1400.             case KEY_NONE:
  1401.                 fprintf(fp, "    key: NONE\n");
  1402.                 break;
  1403.             case KEY_BLUE:
  1404.                 fprintf(fp, "    key: BLUE\n");
  1405.                 break;
  1406.             case KEY_RED:
  1407.                 fprintf(fp, "    key: RED\n");
  1408.                 break;
  1409.             case KEY_GOLD:
  1410.                 fprintf(fp, "    key: NONE\n");
  1411.                 break;
  1412.             default:
  1413.                 fprintf(fp, "  key: ILLEGAL!!!!!! <-----------------\n");
  1414.                 break;
  1415.         }
  1416.  
  1417.         fprintf(fp, "  linked_wall %d\n", Walls[w].linked_wall);
  1418.     }
  1419.     
  1420.     fclose(fp);
  1421.     return 1;
  1422. }
  1423.  
  1424. // ------------------------------------------------------------------------------------------------
  1425. void copy_old_wall_data_to_new(int owall, int nwall)
  1426. {
  1427.     Walls[nwall].flags = Walls[owall].flags;
  1428.     Walls[nwall].type = Walls[owall].type;
  1429.     Walls[nwall].clip_num = Walls[owall].clip_num;
  1430.     Walls[nwall].keys = Walls[owall].keys;
  1431.     Walls[nwall].hps = Walls[owall].hps;
  1432.     Walls[nwall].state = Walls[owall].state;
  1433.     Walls[nwall].linked_wall = -1;
  1434.  
  1435.     Walls[nwall].trigger = -1;
  1436.  
  1437.     if (Walls[owall].trigger != -1) {
  1438.         editor_status("Warning: Trigger not copied in group copy.");
  1439.     }
  1440. }
  1441.  
  1442. //typedef struct trigger {
  1443. //    byte        type;
  1444. //    short        flags;
  1445. //    fix        value;
  1446. //    fix        time;
  1447. //    byte        link_num;
  1448. //    short     num_links;
  1449. //    short     seg[MAX_WALLS_PER_LINK];
  1450. //    short        side[MAX_WALLS_PER_LINK];
  1451. //    } trigger;
  1452.  
  1453.  
  1454. // ------------------------------------------------------------------------------------------------
  1455. void copy_group_walls(int old_group, int new_group)
  1456. {
  1457.     int    i,j,old_seg, new_seg;
  1458.  
  1459.     for (i=0; i<GroupList[old_group].num_segments; i++) {
  1460.         old_seg = GroupList[old_group].segments[i];
  1461.         new_seg = GroupList[new_group].segments[i];
  1462.  
  1463.         for (j=0; j<MAX_SIDES_PER_SEGMENT; j++) {
  1464.             if (Segments[old_seg].sides[j].wall_num != -1) {
  1465.                 mprintf((0, "Going to add wall to seg:side = %i:%i\n", new_seg, j));
  1466.                 Segments[new_seg].sides[j].wall_num = Num_walls;
  1467.                 copy_old_wall_data_to_new(Segments[old_seg].sides[j].wall_num, Num_walls);
  1468.                 Walls[Num_walls].segnum = new_seg;
  1469.                 Walls[Num_walls].sidenum = j;
  1470.                 Num_walls++;
  1471.                 Assert(Num_walls < MAX_WALLS);
  1472.             }
  1473.         }
  1474.     }
  1475. }
  1476.  
  1477. int    Validate_walls=1;
  1478.  
  1479. //    --------------------------------------------------------------------------------------------------------
  1480. //    This function should be in medwall.c.
  1481. //    Make sure all wall/segment connections are valid.
  1482. void check_wall_validity(void)
  1483. {
  1484.     int    i, j;
  1485.     int    segnum, sidenum, wall_num;
  1486.     byte    wall_flags[MAX_WALLS];
  1487.  
  1488.     if (!Validate_walls)
  1489.         return;
  1490.  
  1491.     for (i=0; i<Num_walls; i++) {
  1492.         segnum = Walls[i].segnum;
  1493.         sidenum = Walls[i].sidenum;
  1494.  
  1495.         if (Segments[segnum].sides[sidenum].wall_num != i) {
  1496.             if (!Validate_walls)
  1497.                 return;
  1498.             Int3();        //    Error! Your mine has been invalidated!
  1499.                             // Do not continue!  Do not save!
  1500.                             //    Remember your last action and Contact Mike!
  1501.                             //    To continue, set the variable Validate_walls to 1 by doing:
  1502.                             //        /Validate_walls = 1
  1503.                             //    Then do the usual /eip++;g
  1504.  
  1505.         }
  1506.     }
  1507.  
  1508.     for (i=0; i<MAX_WALLS; i++)
  1509.         wall_flags[i] = 0;
  1510.  
  1511.     for (i=0; i<=Highest_segment_index; i++) {
  1512.         if (Segments[i].segnum != -1)
  1513.             for (j=0; j<MAX_SIDES_PER_SEGMENT; j++) {
  1514.                 // Check walls
  1515.                 wall_num = Segments[i].sides[j].wall_num;
  1516.                 if (wall_num != -1) {
  1517.                     if (wall_flags[wall_num] != 0) {
  1518.                         if (!Validate_walls)
  1519.                             return;
  1520.                         Int3();        //    Error! Your mine has been invalidated!
  1521.                                         // Do not continue!  Do not save!
  1522.                                         //    Remember your last action and Contact Mike!
  1523.                                         //    To continue, set the variable Validate_walls to 1 by doing:
  1524.                                         //        /Validate_walls = 1
  1525.                                         //    Then do the usual /eip++;g
  1526.                     }
  1527.  
  1528.                     if ((Walls[wall_num].segnum != i) || (Walls[wall_num].sidenum != j)) {
  1529.                         if (!Validate_walls)
  1530.                             return;
  1531.                         Int3();        //    Error! Your mine has been invalidated!
  1532.                                         // Do not continue!  Do not save!
  1533.                                         //    Remember your last action and Contact Mike!
  1534.                                         //    To continue, set the variable Validate_walls to 1 by doing:
  1535.                                         //        /Validate_walls = 1
  1536.                                         //    Then do the usual /eip++;g
  1537.                     }
  1538.  
  1539.                     wall_flags[wall_num] = 1;
  1540.                 }
  1541.             }
  1542.  
  1543.     }
  1544. }
  1545.  
  1546.