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