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