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.
14 * $Source: /cvs/cvsroot/d2x/main/editor/medwall.c,v $
17 * $Date: 2004-12-19 13:54:27 $
19 * Created from version 1.11 of main\wall.c
21 * $Log: not supported by cvs2svn $
22 * Revision 1.2 2003/03/09 06:34:09 donut
23 * change byte typedef to sbyte to avoid conflict with win32 byte which is unsigned
25 * Revision 1.1.1.1 1999/06/14 22:04:04 donut
26 * Import of d1x 1.37 source.
28 * Revision 2.0 1995/02/27 11:35:47 john
29 * Version 2.0! No anonymous unions, Watcom 10.0, with no need
32 * Revision 1.71 1995/02/01 16:30:03 yuan
33 * Stabilizing triggers and matcens.
35 * Revision 1.70 1995/01/28 15:28:08 yuan
36 * Return proper bug description.
38 * Revision 1.69 1995/01/14 19:18:07 john
39 * First version of object paging.
41 * Revision 1.68 1995/01/12 12:10:44 yuan
42 * Added delete trigger function
44 * Revision 1.67 1994/11/29 16:51:53 yuan
45 * Fixed false bogus trigger info.
47 * Revision 1.66 1994/11/27 23:17:29 matt
48 * Made changes for new mprintf calling convention
50 * Revision 1.65 1994/11/15 11:59:42 john
51 * Changed timing for door to use fixed seconds instead of milliseconds.
53 * Revision 1.64 1994/11/03 10:41:17 yuan
54 * Made walls add whichever the previous type was.
56 * Revision 1.63 1994/10/13 13:14:59 yuan
57 * Fixed trigger removal bug.
59 * Revision 1.62 1994/10/07 17:43:39 yuan
60 * Make validate walls default to 1.
62 * Revision 1.61 1994/10/03 23:40:20 mike
63 * Fix hosedness in walls in group copying.
65 * Revision 1.60 1994/09/29 00:20:36 matt
66 * Took out reference to unused external wall type
68 * Revision 1.59 1994/09/28 17:32:24 mike
69 * Functions to copy walls withing groups.
71 * Revision 1.58 1994/09/28 13:40:46 yuan
72 * Fixed control center trigger bug.
74 * Revision 1.57 1994/09/24 12:41:52 matt
75 * Took out references to obsolete constants
77 * Revision 1.56 1994/09/23 18:03:55 yuan
78 * Finished wall checking code.
80 * Revision 1.55 1994/09/22 14:35:25 matt
81 * Made blastable walls work again
83 * Revision 1.54 1994/09/21 16:46:07 yuan
84 * Fixed bug that reset wall slot which was just deleted.
86 * Revision 1.53 1994/09/20 18:31:21 yuan
87 * Output right Wallnum
89 * Revision 1.52 1994/09/20 18:23:24 yuan
90 * Killed the BOGIFYING WALL DRAGON...
92 * There was a problem with triggers being created that had bogus
93 * pointers back to their segments.
95 * Revision 1.51 1994/09/20 11:13:11 yuan
96 * Delete all bogus walls when checking walls.
98 * Revision 1.50 1994/09/19 23:31:14 yuan
99 * Adding wall checking stuff.
101 * Revision 1.49 1994/09/13 21:11:20 matt
102 * Added wclips that use tmap1 instead of tmap2, saving lots of merging
104 * Revision 1.48 1994/09/10 13:32:08 matt
105 * Made exploding walls a type of blastable walls.
106 * Cleaned up blastable walls, making them tmap2 bitmaps.
108 * Revision 1.47 1994/09/10 09:47:47 yuan
109 * Added wall checking function.
111 * Revision 1.46 1994/08/26 14:14:56 yuan
112 * Fixed wall clip being set to -2 bug.
114 * Revision 1.45 1994/08/25 21:56:26 mike
117 * Revision 1.44 1994/08/19 19:30:27 matt
118 * Added informative message if wall is already external when making it so.
120 * Revision 1.43 1994/08/17 11:13:46 matt
121 * Changed way external walls work
123 * Revision 1.42 1994/08/15 17:47:29 yuan
124 * Added external walls
126 * Revision 1.41 1994/08/05 21:18:09 matt
127 * Allow two doors to be linked together
129 * Revision 1.40 1994/08/02 14:18:06 mike
130 * Clean up dialog boxes.
132 * Revision 1.39 1994/08/01 11:04:33 yuan
133 * New materialization centers.
135 * Revision 1.38 1994/07/22 17:19:11 yuan
136 * Working on dialog box for refuel/repair/material/control centers.
138 * Revision 1.37 1994/07/20 17:35:33 yuan
139 * Added new gold key.
141 * Revision 1.36 1994/07/19 14:31:44 yuan
144 * Revision 1.35 1994/07/18 15:58:31 yuan
145 * Hopefully prevent any "Adam door bombouts"
147 * Revision 1.34 1994/07/18 15:48:40 yuan
148 * Made minor cosmetic change.
150 * Revision 1.33 1994/07/15 16:09:22 yuan
153 * Revision 1.32 1994/07/14 16:47:05 yuan
154 * Fixed wall dialog for selected dooranims.
156 * Revision 1.31 1994/07/11 15:09:16 yuan
157 * Wall anim filenames stored in wclip structure.
159 * Revision 1.30 1994/07/06 10:56:01 john
160 * New structures for hostages.
162 * Revision 1.29 1994/07/01 16:35:54 yuan
165 * Revision 1.28 1994/06/21 18:50:12 john
166 * Made ESC key exit dialog.
168 * Revision 1.27 1994/06/20 22:29:59 yuan
169 * Fixed crazy runaway trigger bug that Adam found
171 * Revision 1.26 1994/06/01 15:50:25 yuan
172 * Added one more door... Needs to be set by bm.c in the future.
174 * Revision 1.25 1994/05/30 20:22:34 yuan
177 * Revision 1.24 1994/05/27 10:34:31 yuan
178 * Added new Dialog boxes for Walls and Triggers.
180 * Revision 1.23 1994/05/25 18:08:45 yuan
181 * Revamping walls and triggers interface.
182 * Wall interface complete, but triggers are still in progress.
184 * Revision 1.22 1994/05/18 18:21:56 yuan
185 * Fixed delete segment and walls bug.
187 * Revision 1.21 1994/05/11 18:24:29 yuan
188 * Oops.. trigger not triggers..
190 * Revision 1.20 1994/05/11 18:23:53 yuan
191 * Fixed trigger not set to -1 bug.
197 static char rcsid[] = "$Id: medwall.c,v 1.1 2004-12-19 13:54:27 btb Exp $";
205 #include "editor/medwall.h"
207 #include "editor/editor.h"
212 #include "textures.h"
215 #include "editor/eswitch.h"
217 #include "texmerge.h"
218 #include "medrobot.h"
221 //#include "fuelcen.h"
223 #include "ehostage.h"
227 int wall_add_door_flag(sbyte flag);
228 int wall_add_to_side(segment *segp, int side, sbyte type);
229 int wall_remove_door_flag(sbyte flag);
230 //-------------------------------------------------------------------------
231 // Variables for this module...
232 //-------------------------------------------------------------------------
233 static UI_WINDOW *MainWindow = NULL;
234 static UI_GADGET_USERBOX *WallViewBox;
235 static UI_GADGET_BUTTON *QuitButton;
236 static UI_GADGET_CHECKBOX *DoorFlag[4];
237 static UI_GADGET_RADIO *KeyFlag[4];
239 static int old_wall_num;
241 static int framenum=0;
242 static int Current_door_type=1;
244 typedef struct count_wall {
246 short segnum,sidenum;
249 //---------------------------------------------------------------------
250 // Add a wall (removable 2 sided)
251 int add_wall(segment *seg, short side)
256 if (Num_walls < MAX_WALLS-2)
257 if (IS_CHILD(seg->children[side])) {
258 if (seg->sides[side].wall_num == -1) {
259 seg->sides[side].wall_num = Num_walls;
263 csegp = &Segments[seg->children[side]];
264 Connectside = find_connect_side(seg, csegp);
266 if (csegp->sides[Connectside].wall_num == -1) {
267 csegp->sides[Connectside].wall_num = Num_walls;
271 create_removable_wall( seg, side, CurrentTexture );
272 create_removable_wall( csegp, Connectside, CurrentTexture );
280 int wall_assign_door(int door_type)
285 if (Cursegp->sides[Curside].wall_num == -1) {
286 editor_status("Cannot assign door. No wall at Curside.");
290 if (Walls[Cursegp->sides[Curside].wall_num].type != WALL_DOOR && Walls[Cursegp->sides[Curside].wall_num].type != WALL_BLASTABLE) {
291 editor_status("Cannot assign door. No door at Curside.");
295 Current_door_type = door_type;
297 csegp = &Segments[Cursegp->children[Curside]];
298 Connectside = find_connect_side(Cursegp, csegp);
300 Walls[Cursegp->sides[Curside].wall_num].clip_num = door_type;
301 Walls[csegp->sides[Connectside].wall_num].clip_num = door_type;
303 if (WallAnims[door_type].flags & WCF_TMAP1) {
304 Cursegp->sides[Curside].tmap_num = WallAnims[door_type].frames[0];
305 csegp->sides[Connectside].tmap_num = WallAnims[door_type].frames[0];
306 Cursegp->sides[Curside].tmap_num2 = 0;
307 csegp->sides[Connectside].tmap_num2 = 0;
310 Cursegp->sides[Curside].tmap_num2 = WallAnims[door_type].frames[0];
311 csegp->sides[Connectside].tmap_num2 = WallAnims[door_type].frames[0];
314 Update_flags |= UF_WORLD_CHANGED;
318 int wall_add_blastable()
320 return wall_add_to_side(Cursegp, Curside, WALL_BLASTABLE);
325 return wall_add_to_side(Cursegp, Curside, WALL_DOOR);
328 int wall_add_closed_wall()
330 return wall_add_to_side(Cursegp, Curside, WALL_CLOSED);
333 int wall_add_external_wall()
335 if (Cursegp->children[Curside] == -2) {
336 editor_status( "Wall is already external!" );
340 if (IS_CHILD(Cursegp->children[Curside])) {
341 editor_status( "Cannot add external wall here - seg has children" );
345 Cursegp->children[Curside] = -2;
350 int wall_add_illusion()
352 return wall_add_to_side(Cursegp, Curside, WALL_ILLUSION);
357 return wall_add_door_flag(WALL_DOOR_LOCKED);
360 int wall_unlock_door()
362 return wall_remove_door_flag(WALL_DOOR_LOCKED);
365 int wall_automate_door()
367 return wall_add_door_flag(WALL_DOOR_AUTO);
370 int wall_deautomate_door()
372 return wall_remove_door_flag(WALL_DOOR_AUTO);
378 if (Cursegp->sides[Curside].wall_num < 0)
379 current_wall = Num_walls;
381 current_wall = Cursegp->sides[Curside].wall_num;
384 if (current_wall < 0) current_wall = Num_walls-1;
385 if (current_wall >= Num_walls) current_wall = Num_walls-1;
387 if (Walls[current_wall].segnum == -1) {
388 mprintf((0, "Trying to goto wall at bogus segnum\n"));
392 if (Walls[current_wall].sidenum == -1) {
393 mprintf((0, "Trying to goto wall at bogus sidenum\n"));
397 Cursegp = &Segments[Walls[current_wall].segnum];
398 Curside = Walls[current_wall].sidenum;
407 current_wall = Cursegp->sides[Curside].wall_num; // It's ok to be -1 because it will immediately become 0
411 if (current_wall >= Num_walls) current_wall = 0;
412 if (current_wall < 0) current_wall = 0;
414 if (Walls[current_wall].segnum == -1) {
415 mprintf((0, "Trying to goto wall at bogus segnum\n"));
419 if (Walls[current_wall].sidenum == -1) {
420 mprintf((0, "Trying to goto wall at bogus sidenum\n"));
424 Cursegp = &Segments[Walls[current_wall].segnum];
425 Curside = Walls[current_wall].sidenum;
434 if (Cursegp->sides[Curside].wall_num == -1) {
435 editor_status("Cannot assign new wall. No wall on curside.");
439 wall_type = Walls[Cursegp->sides[Curside].wall_num].clip_num;
441 if (Walls[Cursegp->sides[Curside].wall_num].type == WALL_DOOR) {
448 wall_type = Num_wall_anims-1;
450 if (wall_type == Walls[Cursegp->sides[Curside].wall_num].clip_num)
451 Error("Cannot find clip for door.");
453 } while (WallAnims[wall_type].num_frames == -1 || WallAnims[wall_type].flags & WCF_BLASTABLE);
457 else if (Walls[Cursegp->sides[Curside].wall_num].type == WALL_BLASTABLE) {
464 wall_type = Num_wall_anims-1;
466 if (wall_type == Walls[Cursegp->sides[Curside].wall_num].clip_num)
467 Error("Cannot find clip for blastable wall.");
469 } while (WallAnims[wall_type].num_frames == -1 || !(WallAnims[wall_type].flags & WCF_BLASTABLE));
473 wall_assign_door(wall_type);
475 Update_flags |= UF_WORLD_CHANGED;
482 if (Cursegp->sides[Curside].wall_num == -1) {
483 editor_status("Cannot assign new wall. No wall on curside.");
487 wall_type = Walls[Cursegp->sides[Curside].wall_num].clip_num;
489 if (Walls[Cursegp->sides[Curside].wall_num].type == WALL_DOOR) {
495 if (wall_type >= Num_wall_anims) {
497 if (Walls[Cursegp->sides[Curside].wall_num].clip_num==-1)
498 Error("Cannot find clip for door.");
501 } while (WallAnims[wall_type].num_frames == -1 || WallAnims[wall_type].flags & WCF_BLASTABLE);
504 else if (Walls[Cursegp->sides[Curside].wall_num].type == WALL_BLASTABLE) {
510 if (wall_type >= Num_wall_anims) {
512 if (Walls[Cursegp->sides[Curside].wall_num].clip_num==-1)
513 Error("Cannot find clip for blastable wall.");
516 } while (WallAnims[wall_type].num_frames == -1 || !(WallAnims[wall_type].flags & WCF_BLASTABLE));
520 wall_assign_door(wall_type);
522 Update_flags |= UF_WORLD_CHANGED;
527 //-------------------------------------------------------------------------
528 // Called from the editor... does one instance of the wall dialog box
529 //-------------------------------------------------------------------------
534 // Only open 1 instance of this window...
535 if ( MainWindow != NULL ) return 0;
537 // Close other windows.
540 // Open a window with a quit button
541 MainWindow = ui_open_window( TMAPBOX_X+20, TMAPBOX_Y+20, 765-TMAPBOX_X, 545-TMAPBOX_Y, WIN_DIALOG );
542 QuitButton = ui_add_gadget_button( MainWindow, 20, 252, 48, 40, "Done", NULL );
544 // These are the checkboxes for each door flag.
546 DoorFlag[0] = ui_add_gadget_checkbox( MainWindow, 22, i, 16, 16, 0, "Locked" ); i += 24;
547 DoorFlag[1] = ui_add_gadget_checkbox( MainWindow, 22, i, 16, 16, 0, "Auto" ); i += 24;
548 DoorFlag[2] = ui_add_gadget_checkbox( MainWindow, 22, i, 16, 16, 0, "Illusion OFF" ); i += 24;
550 KeyFlag[0] = ui_add_gadget_radio( MainWindow, 22, i, 16, 16, 0, "NONE" ); i += 24;
551 KeyFlag[1] = ui_add_gadget_radio( MainWindow, 22, i, 16, 16, 0, "Blue" ); i += 24;
552 KeyFlag[2] = ui_add_gadget_radio( MainWindow, 22, i, 16, 16, 0, "Red" ); i += 24;
553 KeyFlag[3] = ui_add_gadget_radio( MainWindow, 22, i, 16, 16, 0, "Yellow" ); i += 24;
555 // The little box the wall will appear in.
556 WallViewBox = ui_add_gadget_userbox( MainWindow, 155, 5, 64, 64 );
558 // A bunch of buttons...
560 ui_add_gadget_button( MainWindow,155,i,70, 22, "<< Clip", PrevWall );
561 ui_add_gadget_button( MainWindow,155+70,i,70, 22, "Clip >>", NextWall );i += 25;
562 ui_add_gadget_button( MainWindow,155,i,140, 22, "Add Blastable", wall_add_blastable ); i += 25;
563 ui_add_gadget_button( MainWindow,155,i,140, 22, "Add Door", wall_add_door ); i += 25;
564 ui_add_gadget_button( MainWindow,155,i,140, 22, "Add Illusory", wall_add_illusion); i += 25;
565 ui_add_gadget_button( MainWindow,155,i,140, 22, "Add Closed Wall", wall_add_closed_wall ); i+=25;
566 // ui_add_gadget_button( MainWindow,155,i,140, 22, "Restore All Walls", wall_restore_all ); i += 25;
567 ui_add_gadget_button( MainWindow,155,i,70, 22, "<< Prev", GotoPrevWall );
568 ui_add_gadget_button( MainWindow,155+70,i,70, 22, "Next >>", GotoNextWall );i += 25;
569 ui_add_gadget_button( MainWindow,155,i,140, 22, "Remove Wall", wall_remove ); i += 25;
570 ui_add_gadget_button( MainWindow,155,i,140, 22, "Bind to Trigger", bind_wall_to_trigger ); i += 25;
571 ui_add_gadget_button( MainWindow,155,i,140, 22, "Bind to Control", bind_wall_to_control_center ); i+=25;
573 old_wall_num = -2; // Set to some dummy value so everything works ok on the first frame.
578 void close_wall_window()
580 if ( MainWindow!=NULL ) {
581 ui_close_window( MainWindow );
586 void do_wall_window()
592 if ( MainWindow == NULL ) return;
594 //------------------------------------------------------------
595 // Call the ui code..
596 //------------------------------------------------------------
597 ui_button_any_drawn = 0;
598 ui_window_do_gadgets(MainWindow);
600 //------------------------------------------------------------
601 // If we change walls, we need to reset the ui code for all
602 // of the checkboxes that control the wall flags.
603 //------------------------------------------------------------
604 if (old_wall_num != Cursegp->sides[Curside].wall_num) {
605 for ( i=0; i < 3; i++ ) {
606 DoorFlag[i]->flag = 0; // Tells ui that this button isn't checked
607 DoorFlag[i]->status = 1; // Tells ui to redraw button
609 for ( i=0; i < 4; i++ ) {
610 KeyFlag[i]->flag = 0; // Tells ui that this button isn't checked
611 KeyFlag[i]->status = 1; // Tells ui to redraw button
614 if ( Cursegp->sides[Curside].wall_num != -1) {
615 if (Walls[Cursegp->sides[Curside].wall_num].flags & WALL_DOOR_LOCKED)
616 DoorFlag[0]->flag = 1; // Mark this button as checked
617 if (Walls[Cursegp->sides[Curside].wall_num].flags & WALL_DOOR_AUTO)
618 DoorFlag[1]->flag = 1; // Mark this button as checked
619 if (Walls[Cursegp->sides[Curside].wall_num].flags & WALL_ILLUSION_OFF)
620 DoorFlag[2]->flag = 1; // Mark this button as checked
622 if (Walls[Cursegp->sides[Curside].wall_num].keys & KEY_NONE)
623 KeyFlag[0]->flag = 1;
624 if (Walls[Cursegp->sides[Curside].wall_num].keys & KEY_BLUE)
625 KeyFlag[1]->flag = 1;
626 if (Walls[Cursegp->sides[Curside].wall_num].keys & KEY_RED)
627 KeyFlag[2]->flag = 1;
628 if (Walls[Cursegp->sides[Curside].wall_num].keys & KEY_GOLD)
629 KeyFlag[3]->flag = 1;
633 //------------------------------------------------------------
634 // If any of the checkboxes that control the wallflags are set, then
635 // update the corresponding wall flag.
636 //------------------------------------------------------------
638 if (Walls[Cursegp->sides[Curside].wall_num].type == WALL_DOOR) {
639 if ( DoorFlag[0]->flag == 1 )
640 Walls[Cursegp->sides[Curside].wall_num].flags |= WALL_DOOR_LOCKED;
642 Walls[Cursegp->sides[Curside].wall_num].flags &= ~WALL_DOOR_LOCKED;
643 if ( DoorFlag[1]->flag == 1 )
644 Walls[Cursegp->sides[Curside].wall_num].flags |= WALL_DOOR_AUTO;
646 Walls[Cursegp->sides[Curside].wall_num].flags &= ~WALL_DOOR_AUTO;
648 //------------------------------------------------------------
649 // If any of the radio buttons that control the mode are set, then
650 // update the corresponding key.
651 //------------------------------------------------------------
652 for ( i=0; i < 4; i++ ) {
653 if ( KeyFlag[i]->flag == 1 ) {
654 Walls[Cursegp->sides[Curside].wall_num].keys = 1<<i; // Set the ai_state to the cooresponding radio button
655 // mprintf((0, "1<<%d = %d\n", i, 1<<i));
659 for ( i=0; i < 2; i++ )
660 if (DoorFlag[i]->flag == 1) {
661 DoorFlag[i]->flag = 0; // Tells ui that this button isn't checked
662 DoorFlag[i]->status = 1; // Tells ui to redraw button
664 for ( i=0; i < 4; i++ ) {
665 if ( KeyFlag[i]->flag == 1 ) {
666 KeyFlag[i]->flag = 0;
667 KeyFlag[i]->status = 1;
672 if (Walls[Cursegp->sides[Curside].wall_num].type == WALL_ILLUSION) {
673 if ( DoorFlag[2]->flag == 1 )
674 Walls[Cursegp->sides[Curside].wall_num].flags |= WALL_ILLUSION_OFF;
676 Walls[Cursegp->sides[Curside].wall_num].flags &= ~WALL_ILLUSION_OFF;
678 for ( i=2; i < 3; i++ )
679 if (DoorFlag[i]->flag == 1) {
680 DoorFlag[i]->flag = 0; // Tells ui that this button isn't checked
681 DoorFlag[i]->status = 1; // Tells ui to redraw button
684 //------------------------------------------------------------
685 // A simple frame time counter for animating the walls...
686 //------------------------------------------------------------
687 Temp = timer_get_fixed_seconds();
688 DeltaTime = Temp - Time;
690 //------------------------------------------------------------
691 // Draw the wall in the little 64x64 box
692 //------------------------------------------------------------
693 gr_set_current_canvas( WallViewBox->canvas );
694 if (Cursegp->sides[Curside].wall_num != -1) {
695 type = Walls[Cursegp->sides[Curside].wall_num].type;
696 if ((type == WALL_DOOR) || (type == WALL_BLASTABLE)) {
697 if (DeltaTime > ((F1_0*200)/1000)) {
701 if (framenum >= WallAnims[Walls[Cursegp->sides[Curside].wall_num].clip_num].num_frames)
703 PIGGY_PAGE_IN(Textures[WallAnims[Walls[Cursegp->sides[Curside].wall_num].clip_num].frames[framenum]]);
704 gr_ubitmap(0,0, &GameBitmaps[Textures[WallAnims[Walls[Cursegp->sides[Curside].wall_num].clip_num].frames[framenum]].index]);
706 if (type == WALL_OPEN)
707 gr_clear_canvas( CBLACK );
709 if (Cursegp->sides[Curside].tmap_num2 > 0)
710 gr_ubitmap(0,0, texmerge_get_cached_bitmap( Cursegp->sides[Curside].tmap_num, Cursegp->sides[Curside].tmap_num2));
712 PIGGY_PAGE_IN(Textures[Cursegp->sides[Curside].tmap_num]);
713 gr_ubitmap(0,0, &GameBitmaps[Textures[Cursegp->sides[Curside].tmap_num].index]);
718 gr_clear_canvas( CGREY );
720 //------------------------------------------------------------
721 // If anything changes in the ui system, redraw all the text that
722 // identifies this wall.
723 //------------------------------------------------------------
724 if (ui_button_any_drawn || (old_wall_num != Cursegp->sides[Curside].wall_num) ) {
725 if ( Cursegp->sides[Curside].wall_num > -1 ) {
726 ui_wprintf_at( MainWindow, 12, 6, "Wall: %d ", Cursegp->sides[Curside].wall_num);
727 switch (Walls[Cursegp->sides[Curside].wall_num].type) {
729 ui_wprintf_at( MainWindow, 12, 23, " Type: Normal " );
732 ui_wprintf_at( MainWindow, 12, 23, " Type: Blastable" );
735 ui_wprintf_at( MainWindow, 12, 23, " Type: Door " );
736 ui_wprintf_at( MainWindow, 223, 6, "%s", WallAnims[Walls[Cursegp->sides[Curside].wall_num].clip_num].filename);
739 ui_wprintf_at( MainWindow, 12, 23, " Type: Illusion " );
742 ui_wprintf_at( MainWindow, 12, 23, " Type: Open " );
745 ui_wprintf_at( MainWindow, 12, 23, " Type: Closed " );
748 ui_wprintf_at( MainWindow, 12, 23, " Type: Unknown " );
751 if (Walls[Cursegp->sides[Curside].wall_num].type != WALL_DOOR)
752 ui_wprintf_at( MainWindow, 223, 6, " " );
754 ui_wprintf_at( MainWindow, 12, 40, " Clip: %d ", Walls[Cursegp->sides[Curside].wall_num].clip_num );
755 ui_wprintf_at( MainWindow, 12, 57, " Trigger: %d ", Walls[Cursegp->sides[Curside].wall_num].trigger );
757 ui_wprintf_at( MainWindow, 12, 6, "Wall: none ");
758 ui_wprintf_at( MainWindow, 12, 23, " Type: none ");
759 ui_wprintf_at( MainWindow, 12, 40, " Clip: none ");
760 ui_wprintf_at( MainWindow, 12, 57, " Trigger: none ");
762 Update_flags |= UF_WORLD_CHANGED;
764 if ( QuitButton->pressed || (last_keypress==KEY_ESC) ) {
769 old_wall_num = Cursegp->sides[Curside].wall_num;
773 //---------------------------------------------------------------------
774 // Restore all walls to original status (closed doors, repaired walls)
775 int wall_restore_all()
780 for (i=0;i<Num_walls;i++) {
781 if (Walls[i].flags & WALL_BLASTED) {
782 Walls[i].hps = WALL_HPS;
783 Walls[i].flags &= ~WALL_BLASTED;
785 if (Walls[i].flags & WALL_DOOR_OPENED)
786 Walls[i].flags &= ~WALL_DOOR_OPENED;
787 if (Walls[i].flags & WALL_DOOR_OPENING)
788 Walls[i].flags &= ~WALL_DOOR_OPENING;
791 for (i=0;i<Num_open_doors;i++)
794 for (i=0;i<Num_segments;i++)
795 for (j=0;j<MAX_SIDES_PER_SEGMENT;j++) {
796 wall_num = Segments[i].sides[j].wall_num;
798 if ((Walls[wall_num].type == WALL_BLASTABLE) ||
799 (Walls[wall_num].type == WALL_DOOR))
800 Segments[i].sides[j].tmap_num2 = WallAnims[Walls[wall_num].clip_num].frames[0];
803 for (i=0;i<Num_triggers;i++)
804 Triggers[i].flags |= TRIGGER_ON;
806 Update_flags |= UF_GAME_VIEW_CHANGED;
812 //---------------------------------------------------------------------
813 // Delete a specific wall.
814 int wall_delete_bogus(short wall_num)
819 if ((Walls[wall_num].segnum != -1) && (Walls[wall_num].sidenum != -1)) {
820 mprintf((0,"WALL IS NOT BOGUS.\n"));
824 // Delete bogus wall and slide all above walls down one slot
825 for (w=wall_num; w<Num_walls; w++) {
826 Walls[w] = Walls[w+1];
831 for (seg=0;seg<=Highest_segment_index;seg++)
832 if (Segments[seg].segnum != -1)
833 for (side=0;side<MAX_SIDES_PER_SEGMENT;side++)
834 if (Segments[seg].sides[side].wall_num > wall_num)
835 Segments[seg].sides[side].wall_num--;
837 mprintf((0,"BOGUS WALL DELETED!!!!\n"));
843 //---------------------------------------------------------------------
844 // Remove a specific side.
845 int wall_remove_side(segment *seg, short side)
852 if (IS_CHILD(seg->children[side]) && IS_CHILD(seg->sides[side].wall_num)) {
853 csegp = &Segments[seg->children[side]];
854 Connectside = find_connect_side(seg, csegp);
856 remove_trigger(seg, side);
857 remove_trigger(csegp, Connectside);
859 // Remove walls 'wall_num' and connecting side 'wall_num'
861 lower_wallnum = seg->sides[side].wall_num;
862 if (csegp->sides[Connectside].wall_num < lower_wallnum)
863 lower_wallnum = csegp->sides[Connectside].wall_num;
865 if (Walls[lower_wallnum].linked_wall != -1)
866 Walls[Walls[lower_wallnum].linked_wall].linked_wall = -1;
867 if (Walls[lower_wallnum+1].linked_wall != -1)
868 Walls[Walls[lower_wallnum+1].linked_wall].linked_wall = -1;
870 for (w=lower_wallnum;w<Num_walls-2;w++)
871 Walls[w] = Walls[w+2];
875 for (s=0;s<=Highest_segment_index;s++)
876 if (Segments[s].segnum != -1)
877 for (w=0;w<MAX_SIDES_PER_SEGMENT;w++)
878 if (Segments[s].sides[w].wall_num > lower_wallnum+1)
879 Segments[s].sides[w].wall_num -= 2;
881 // Destroy any links to the deleted wall.
882 for (t=0;t<Num_triggers;t++)
883 for (l=0;l<Triggers[t].num_links;l++)
884 if ((Triggers[t].seg[l] == seg-Segments) && (Triggers[t].side[l] == side)) {
885 for (t1=0;t1<Triggers[t].num_links-1;t1++) {
886 Triggers[t].seg[t1] = Triggers[t].seg[t1+1];
887 Triggers[t].side[t1] = Triggers[t].side[t1+1];
889 Triggers[t].num_links--;
892 // Destroy control center links as well.
893 for (l=0;l<ControlCenterTriggers.num_links;l++)
894 if ((ControlCenterTriggers.seg[l] == seg-Segments) && (ControlCenterTriggers.side[l] == side)) {
895 for (t1=0;t1<ControlCenterTriggers.num_links-1;t1++) {
896 ControlCenterTriggers.seg[t1] = ControlCenterTriggers.seg[t1+1];
897 ControlCenterTriggers.side[t1] = ControlCenterTriggers.side[t1+1];
899 ControlCenterTriggers.num_links--;
902 seg->sides[side].wall_num = -1;
903 csegp->sides[Connectside].wall_num = -1;
905 Update_flags |= UF_WORLD_CHANGED;
909 editor_status( "Can't remove wall. No wall present.");
913 //---------------------------------------------------------------------
914 // Remove a special wall.
917 return wall_remove_side(Cursegp, Curside);
920 //---------------------------------------------------------------------
921 // Add a wall to curside
922 int wall_add_to_side(segment *segp, int side, sbyte type)
927 if (add_wall(segp, side)) {
928 csegp = &Segments[segp->children[side]];
929 connectside = find_connect_side(segp, csegp);
931 Walls[segp->sides[side].wall_num].segnum = segp-Segments;
932 Walls[csegp->sides[connectside].wall_num].segnum = csegp-Segments;
934 Walls[segp->sides[side].wall_num].sidenum = side;
935 Walls[csegp->sides[connectside].wall_num].sidenum = connectside;
937 Walls[segp->sides[side].wall_num].flags = 0;
938 Walls[csegp->sides[connectside].wall_num].flags = 0;
940 Walls[segp->sides[side].wall_num].type = type;
941 Walls[csegp->sides[connectside].wall_num].type = type;
943 // Walls[segp->sides[side].wall_num].trigger = -1;
944 // Walls[csegp->sides[connectside].wall_num].trigger = -1;
946 Walls[segp->sides[side].wall_num].clip_num = -1;
947 Walls[csegp->sides[connectside].wall_num].clip_num = -1;
949 Walls[segp->sides[side].wall_num].keys = KEY_NONE;
950 Walls[csegp->sides[connectside].wall_num].keys = KEY_NONE;
952 if (type == WALL_BLASTABLE) {
953 Walls[segp->sides[side].wall_num].hps = WALL_HPS;
954 Walls[csegp->sides[connectside].wall_num].hps = WALL_HPS;
956 //Walls[segp->sides[side].wall_num].clip_num = 0;
957 //Walls[csegp->sides[connectside].wall_num].clip_num = 0;
960 if (type != WALL_DOOR) {
961 segp->sides[side].tmap_num2 = 0;
962 csegp->sides[connectside].tmap_num2 = 0;
965 if (type == WALL_DOOR) {
966 Walls[segp->sides[side].wall_num].flags |= WALL_DOOR_AUTO;
967 Walls[csegp->sides[connectside].wall_num].flags |= WALL_DOOR_AUTO;
969 Walls[segp->sides[side].wall_num].clip_num = Current_door_type;
970 Walls[csegp->sides[connectside].wall_num].clip_num = Current_door_type;
973 //Update_flags |= UF_WORLD_CHANGED;
976 // return NextWall(); //assign a clip num
977 return wall_assign_door(Current_door_type);
980 editor_status( "Cannot add wall here, no children" );
986 //---------------------------------------------------------------------
987 // Add a wall to markedside
988 int wall_add_to_markedside(sbyte type)
993 if (add_wall(Markedsegp, Markedside)) {
994 int wall_num, cwall_num;
995 csegp = &Segments[Markedsegp->children[Markedside]];
997 Connectside = find_connect_side(Markedsegp, csegp);
999 wall_num = Markedsegp->sides[Markedside].wall_num;
1000 cwall_num = csegp->sides[Connectside].wall_num;
1002 Walls[wall_num].segnum = Markedsegp-Segments;
1003 Walls[cwall_num].segnum = csegp-Segments;
1005 Walls[wall_num].sidenum = Markedside;
1006 Walls[cwall_num].sidenum = Connectside;
1008 Walls[wall_num].flags = 0;
1009 Walls[cwall_num].flags = 0;
1011 Walls[wall_num].type = type;
1012 Walls[cwall_num].type = type;
1014 Walls[wall_num].trigger = -1;
1015 Walls[cwall_num].trigger = -1;
1017 Walls[wall_num].clip_num = -1;
1018 Walls[cwall_num].clip_num = -1;
1020 Walls[wall_num].keys = KEY_NONE;
1021 Walls[cwall_num].keys = KEY_NONE;
1023 if (type == WALL_BLASTABLE) {
1024 Walls[wall_num].hps = WALL_HPS;
1025 Walls[cwall_num].hps = WALL_HPS;
1027 Walls[wall_num].clip_num = 0;
1028 Walls[cwall_num].clip_num = 0;
1031 if (type != WALL_DOOR) {
1032 Markedsegp->sides[Markedside].tmap_num2 = 0;
1033 csegp->sides[Connectside].tmap_num2 = 0;
1036 Update_flags |= UF_WORLD_CHANGED;
1039 editor_status( "Cannot add wall here, no children" );
1045 int wall_add_door_flag(sbyte flag)
1050 if (Cursegp->sides[Curside].wall_num == -1)
1052 editor_status("Cannot change flag. No wall at Curside.");
1056 if (Walls[Cursegp->sides[Curside].wall_num].type != WALL_DOOR)
1058 editor_status("Cannot change flag. No door at Curside.");
1062 csegp = &Segments[Cursegp->children[Curside]];
1063 Connectside = find_connect_side(Cursegp, csegp);
1065 Walls[Cursegp->sides[Curside].wall_num].flags |= flag;
1066 Walls[csegp->sides[Connectside].wall_num].flags |= flag;
1068 Update_flags |= UF_ED_STATE_CHANGED;
1072 int wall_remove_door_flag(sbyte flag)
1077 if (Cursegp->sides[Curside].wall_num == -1)
1079 editor_status("Cannot change flag. No wall at Curside.");
1083 if (Walls[Cursegp->sides[Curside].wall_num].type != WALL_DOOR)
1085 editor_status("Cannot change flag. No door at Curside.");
1089 csegp = &Segments[Cursegp->children[Curside]];
1090 Connectside = find_connect_side(Cursegp, csegp);
1092 Walls[Cursegp->sides[Curside].wall_num].flags &= ~flag;
1093 Walls[csegp->sides[Connectside].wall_num].flags &= ~flag;
1095 Update_flags |= UF_ED_STATE_CHANGED;
1100 int bind_wall_to_control_center() {
1105 if (Cursegp->sides[Curside].wall_num == -1) {
1106 editor_status("No wall at Curside.");
1110 link_num = ControlCenterTriggers.num_links;
1111 for (i=0;i<link_num;i++)
1112 if ((Cursegp-Segments == ControlCenterTriggers.seg[i]) && (Curside == ControlCenterTriggers.side[i])) {
1113 editor_status("Curside already bound to Control Center.");
1117 // Error checking completed, actual binding begins
1118 ControlCenterTriggers.seg[link_num] = Cursegp - Segments;
1119 ControlCenterTriggers.side[link_num] = Curside;
1120 ControlCenterTriggers.num_links++;
1122 mprintf((0, "seg %d:side %d linked to control center link_num %d\n",
1123 ControlCenterTriggers.seg[link_num], ControlCenterTriggers.side[link_num], link_num));
1125 editor_status("Wall linked to control center");
1130 //link two doors, curseg/curside and markedseg/markedside
1131 int wall_link_doors()
1133 wall *w1=NULL,*w2=NULL;
1135 if (Cursegp->sides[Curside].wall_num != -1)
1136 w1 = &Walls[Cursegp->sides[Curside].wall_num];
1138 if (Markedsegp->sides[Markedside].wall_num != -1)
1139 w2 = &Walls[Markedsegp->sides[Markedside].wall_num];
1141 if (!w1 || w1->type != WALL_DOOR) {
1142 editor_status("Curseg/curside is not a door");
1146 if (!w2 || w2->type != WALL_DOOR) {
1147 editor_status("Markedseg/markedside is not a door");
1151 if (w1->linked_wall != -1)
1152 editor_status("Curseg/curside is already linked");
1154 if (w2->linked_wall != -1)
1155 editor_status("Markedseg/markedside is already linked");
1157 w1->linked_wall = w2-Walls;
1158 w2->linked_wall = w1-Walls;
1163 int wall_unlink_door()
1167 if (Cursegp->sides[Curside].wall_num != -1)
1168 w1 = &Walls[Cursegp->sides[Curside].wall_num];
1170 if (!w1 || w1->type != WALL_DOOR) {
1171 editor_status("Curseg/curside is not a door");
1175 if (w1->linked_wall == -1)
1176 editor_status("Curseg/curside is not linked");
1178 Assert(Walls[w1->linked_wall].linked_wall == w1-Walls);
1180 Walls[w1->linked_wall].linked_wall = -1;
1181 w1->linked_wall = -1;
1187 #define DIAGNOSTIC_MESSAGE_MAX 150
1191 int w, seg, side, wall_count, trigger_count;
1193 count_wall CountedWalls[MAX_WALLS];
1194 char Message[DIAGNOSTIC_MESSAGE_MAX];
1198 for (seg=0;seg<=Highest_segment_index;seg++)
1199 if (Segments[seg].segnum != -1) {
1200 // Check fuelcenters
1201 matcen_num = Segments[seg].matcen_num;
1202 if (matcen_num == 0)
1203 if (RobotCenters[0].segnum != seg) {
1204 mprintf((0,"Fixing Matcen 0\n"));
1205 Segments[seg].matcen_num = -1;
1208 if (matcen_num > -1)
1209 if (RobotCenters[matcen_num].segnum != seg) {
1210 mprintf((0,"Matcen [%d] (seg %d) doesn't point back to correct segment %d\n", matcen_num, RobotCenters[matcen_num].segnum, seg));
1211 mprintf((0,"Fixing....\n"));
1212 RobotCenters[matcen_num].segnum = seg;
1215 for (side=0;side<MAX_SIDES_PER_SEGMENT;side++)
1216 if (Segments[seg].sides[side].wall_num != -1) {
1217 CountedWalls[wall_count].wallnum = Segments[seg].sides[side].wall_num;
1218 CountedWalls[wall_count].segnum = seg;
1219 CountedWalls[wall_count].sidenum = side;
1221 // Check if segnum is bogus
1222 if (Walls[Segments[seg].sides[side].wall_num].segnum == -1) {
1223 mprintf((0, "Wall %d at seg:side %d:%d is BOGUS\n", Segments[seg].sides[side].wall_num, seg, side));
1226 if (Walls[Segments[seg].sides[side].wall_num].type == WALL_NORMAL) {
1227 mprintf((0, "Wall %d at seg:side %d:%d is NORMAL (BAD)\n", Segments[seg].sides[side].wall_num, seg, side));
1234 mprintf((0,"Wall Count = %d\n", wall_count));
1236 if (wall_count != Num_walls) {
1237 sprintf( Message, "Num_walls is bogus\nDo you wish to correct it?\n");
1238 if (MessageBox( -2, -2, 2, Message, "Yes", "No" )==1) {
1239 Num_walls = wall_count;
1240 editor_status("Num_walls set to %d\n", Num_walls);
1244 // Check validity of Walls array.
1245 for (w=0; w<Num_walls; w++) {
1246 if ((Walls[CountedWalls[w].wallnum].segnum != CountedWalls[w].segnum) ||
1247 (Walls[CountedWalls[w].wallnum].sidenum != CountedWalls[w].sidenum)) {
1248 mprintf((0,"Unmatched walls on wall_num %d\n", CountedWalls[w].wallnum));
1249 sprintf( Message, "Unmatched wall detected\nDo you wish to correct it?\n");
1250 if (MessageBox( -2, -2, 2, Message, "Yes", "No" )==1) {
1251 Walls[CountedWalls[w].wallnum].segnum = CountedWalls[w].segnum;
1252 Walls[CountedWalls[w].wallnum].sidenum = CountedWalls[w].sidenum;
1256 if (CountedWalls[w].wallnum >= Num_walls)
1257 mprintf((0,"wallnum %d in Segments exceeds Num_walls!\n", CountedWalls[w].wallnum));
1259 if (Walls[w].segnum == -1) {
1260 mprintf((0, "Wall[%d] is BOGUS\n", w));
1261 for (seg=0;seg<=Highest_segment_index;seg++)
1262 for (side=0;side<MAX_SIDES_PER_SEGMENT;side++)
1263 if (Segments[seg].sides[side].wall_num == w) {
1264 mprintf((0, " BOGUS WALL found at seg:side %d:%d\n", seg, side));
1270 for (w1=0; w1<wall_count; w1++) {
1271 for (w2=w1+1; w2<wall_count; w2++)
1272 if (CountedWalls[w1].wallnum == CountedWalls[w2].wallnum) {
1273 mprintf((0, "Duplicate Walls %d and %d. Wallnum=%d. ", w1, w2, CountedWalls[w1].wallnum));
1274 mprintf((0, "Seg1:sides1 %d:%d ", CountedWalls[w1].segnum, CountedWalls[w1].sidenum));
1275 mprintf((0, "Seg2:sides2 %d:%d\n", CountedWalls[w2].segnum, CountedWalls[w2].sidenum));
1277 if (Walls[w1].trigger != -1) trigger_count++;
1280 if (trigger_count != Num_triggers) {
1281 sprintf( Message, "Num_triggers is bogus\nDo you wish to correct it?\n");
1282 if (MessageBox( -2, -2, 2, Message, "Yes", "No" )==1) {
1283 Num_triggers = trigger_count;
1284 editor_status("Num_triggers set to %d\n", Num_triggers);
1288 mprintf((0,"Trigger Count = %d\n", trigger_count));
1290 for (t=0; t<trigger_count; t++) {
1291 if (Triggers[t].flags & TRIGGER_MATCEN)
1293 if (Triggers[t].num_links < 1)
1294 mprintf((0,"No valid links on Matcen Trigger %d\n", t));
1296 for (l=0;l<Triggers[t].num_links;l++) {
1297 if (!Segments[Triggers[t].seg[l]].special & SEGMENT_IS_ROBOTMAKER)
1298 mprintf((0,"Bogus Matcen trigger detected on Trigger %d, No matcen at seg %d\n", t, Triggers[t].seg[l]));
1302 if (Triggers[t].flags & TRIGGER_EXIT)
1303 if (Triggers[t].num_links != 0)
1304 mprintf((0,"Bogus links detected on Exit Trigger %d\n", t));
1306 if (Triggers[t].flags & TRIGGER_CONTROL_DOORS)
1307 for (l=0;l<Triggers[t].num_links;l++) {
1308 if (Segments[Triggers[t].seg[l]].sides[Triggers[t].side[l]].wall_num == -1) {
1309 mprintf((0,"Bogus Link detected on Door Control Trigger %d, link %d\n", t, l));
1310 mprintf((0,"Bogus Link at seg %d, side %d\n", Triggers[t].seg[l], Triggers[t].side[l]));
1315 for (l=0;l<ControlCenterTriggers.num_links;l++)
1316 if (Segments[ControlCenterTriggers.seg[l]].sides[ControlCenterTriggers.side[l]].wall_num == -1) {
1317 mprintf((0,"Bogus Link detected on Control Center Trigger, link %d\n", l));
1318 mprintf((0,"Bogus Link at seg %d, side %d\n", Triggers[t].seg[l], Triggers[t].side[l]));
1326 int delete_all_walls()
1328 char Message[DIAGNOSTIC_MESSAGE_MAX];
1331 sprintf( Message, "Are you sure that walls are hosed so\n badly that you want them ALL GONE!?\n");
1332 if (MessageBox( -2, -2, 2, Message, "YES!", "No" )==1) {
1333 for (seg=0;seg<=Highest_segment_index;seg++)
1334 for (side=0;side<MAX_SIDES_PER_SEGMENT;side++)
1335 Segments[seg].sides[side].wall_num = -1;
1345 int delete_all_triggers()
1347 char Message[DIAGNOSTIC_MESSAGE_MAX];
1350 sprintf( Message, "Are you sure that triggers are hosed so\n badly that you want them ALL GONE!?\n");
1351 if (MessageBox( -2, -2, 2, Message, "YES!", "No" )==1) {
1353 for (w=0; w<Num_walls; w++)
1354 Walls[w].trigger=-1;
1363 int dump_walls_info()
1368 fp = fopen("WALL.OUT", "wt");
1370 fprintf(fp, "Num_walls %d\n", Num_walls);
1372 for (w=0; w<Num_walls; w++) {
1374 fprintf(fp, "WALL #%d\n", w);
1375 fprintf(fp, " seg: %d\n", Walls[w].segnum);
1376 fprintf(fp, " sidenum: %d\n", Walls[w].sidenum);
1378 switch (Walls[w].type) {
1380 fprintf(fp, " type: NORMAL\n");
1382 case WALL_BLASTABLE:
1383 fprintf(fp, " type: BLASTABLE\n");
1386 fprintf(fp, " type: DOOR\n");
1389 fprintf(fp, " type: ILLUSION\n");
1392 fprintf(fp, " type: OPEN\n");
1395 fprintf(fp, " type: CLOSED\n");
1398 fprintf(fp, " type: ILLEGAL!!!!! <-----------------\n");
1402 fprintf(fp, " flags:\n");
1404 if (Walls[w].flags & WALL_BLASTED)
1405 fprintf(fp, " BLASTED\n");
1406 if (Walls[w].flags & WALL_DOOR_OPENED)
1407 fprintf(fp, " DOOR_OPENED <----------------- BAD!!!\n");
1408 if (Walls[w].flags & WALL_DOOR_OPENING)
1409 fprintf(fp, " DOOR_OPENING <---------------- BAD!!!\n");
1410 if (Walls[w].flags & WALL_DOOR_LOCKED)
1411 fprintf(fp, " DOOR_LOCKED\n");
1412 if (Walls[w].flags & WALL_DOOR_AUTO)
1413 fprintf(fp, " DOOR_AUTO\n");
1414 if (Walls[w].flags & WALL_ILLUSION_OFF)
1415 fprintf(fp, " ILLUSION_OFF <---------------- OUTDATED\n");
1416 //if (Walls[w].flags & WALL_FUELCEN)
1417 // fprintf(fp, " FUELCEN <--------------------- OUTDATED\n");
1419 fprintf(fp, " trigger: %d\n", Walls[w].trigger);
1420 fprintf(fp, " clip_num: %d\n", Walls[w].clip_num);
1422 switch (Walls[w].keys) {
1424 fprintf(fp, " key: NONE\n");
1427 fprintf(fp, " key: BLUE\n");
1430 fprintf(fp, " key: RED\n");
1433 fprintf(fp, " key: NONE\n");
1436 fprintf(fp, " key: ILLEGAL!!!!!! <-----------------\n");
1440 fprintf(fp, " linked_wall %d\n", Walls[w].linked_wall);
1447 // ------------------------------------------------------------------------------------------------
1448 void copy_old_wall_data_to_new(int owall, int nwall)
1450 Walls[nwall].flags = Walls[owall].flags;
1451 Walls[nwall].type = Walls[owall].type;
1452 Walls[nwall].clip_num = Walls[owall].clip_num;
1453 Walls[nwall].keys = Walls[owall].keys;
1454 Walls[nwall].hps = Walls[owall].hps;
1455 Walls[nwall].state = Walls[owall].state;
1456 Walls[nwall].linked_wall = -1;
1458 Walls[nwall].trigger = -1;
1460 if (Walls[owall].trigger != -1) {
1461 editor_status("Warning: Trigger not copied in group copy.");
1465 //typedef struct trigger {
1472 // short seg[MAX_WALLS_PER_LINK];
1473 // short side[MAX_WALLS_PER_LINK];
1477 // ------------------------------------------------------------------------------------------------
1478 void copy_group_walls(int old_group, int new_group)
1480 int i,j,old_seg, new_seg;
1482 for (i=0; i<GroupList[old_group].num_segments; i++) {
1483 old_seg = GroupList[old_group].segments[i];
1484 new_seg = GroupList[new_group].segments[i];
1486 for (j=0; j<MAX_SIDES_PER_SEGMENT; j++) {
1487 if (Segments[old_seg].sides[j].wall_num != -1) {
1488 mprintf((0, "Going to add wall to seg:side = %i:%i\n", new_seg, j));
1489 Segments[new_seg].sides[j].wall_num = Num_walls;
1490 copy_old_wall_data_to_new(Segments[old_seg].sides[j].wall_num, Num_walls);
1491 Walls[Num_walls].segnum = new_seg;
1492 Walls[Num_walls].sidenum = j;
1494 Assert(Num_walls < MAX_WALLS);
1500 int Validate_walls=1;
1502 // --------------------------------------------------------------------------------------------------------
1503 // This function should be in medwall.c.
1504 // Make sure all wall/segment connections are valid.
1505 void check_wall_validity(void)
1508 int segnum, sidenum, wall_num;
1509 sbyte wall_flags[MAX_WALLS];
1511 if (!Validate_walls)
1514 for (i=0; i<Num_walls; i++) {
1515 segnum = Walls[i].segnum;
1516 sidenum = Walls[i].sidenum;
1518 if (Segments[segnum].sides[sidenum].wall_num != i) {
1519 if (!Validate_walls)
1521 Int3(); // Error! Your mine has been invalidated!
1522 // Do not continue! Do not save!
1523 // Remember your last action and Contact Mike!
1524 // To continue, set the variable Validate_walls to 1 by doing:
1525 // /Validate_walls = 1
1526 // Then do the usual /eip++;g
1531 for (i=0; i<MAX_WALLS; i++)
1534 for (i=0; i<=Highest_segment_index; i++) {
1535 if (Segments[i].segnum != -1)
1536 for (j=0; j<MAX_SIDES_PER_SEGMENT; j++) {
1538 wall_num = Segments[i].sides[j].wall_num;
1539 if (wall_num != -1) {
1540 if (wall_flags[wall_num] != 0) {
1541 if (!Validate_walls)
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
1551 if ((Walls[wall_num].segnum != i) || (Walls[wall_num].sidenum != j)) {
1552 if (!Validate_walls)
1554 Int3(); // Error! Your mine has been invalidated!
1555 // Do not continue! Do not save!
1556 // Remember your last action and Contact Mike!
1557 // To continue, set the variable Validate_walls to 1 by doing:
1558 // /Validate_walls = 1
1559 // Then do the usual /eip++;g
1562 wall_flags[wall_num] = 1;