1 //-------------------------------------------------------------------------
2 /*
3 Copyright (C) 1996, 2005 - 3D Realms Entertainment
4
5 This file is NOT part of Shadow Warrior version 1.2
6 However, it is either an older version of a file that is, or is
7 some test code written during the development of Shadow Warrior.
8 This file is provided purely for educational interest.
9
10 Shadow Warrior is free software; you can redistribute it and/or
11 modify it under the terms of the GNU General Public License
12 as published by the Free Software Foundation; either version 2
13 of the License, or (at your option) any later version.
14
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
18
19 See the GNU General Public License for more details.
20
21 You should have received a copy of the GNU General Public License
22 along with this program; if not, write to the Free Software
23 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
24
25 Prepared for public release: 03/28/2005 - Charlie Wiederhold, 3D Realms
26 */
27 //-------------------------------------------------------------------------
28
29 #include "build.h"
30 #include "editor.h"
31
32 #include "keys.h"
33 #include "names2.h"
34 #include "game.h"
35
36
37 extern int posx, posy, posz;
38 extern short cursectnum;
39 extern short ang;
40 extern int horiz;
41 extern int qsetmode;
42
43 BOOL FindCeilingView(short match, LONGp x, LONGp y, LONG z, SHORTp sectnum);
44 BOOL FindFloorView(short match, LONGp x, LONGp y, LONG z, SHORTp sectnum);
45 short ViewSectorInScene(short cursectnum, short type, short level);
46 void Message(char *string, char color);
47
48
49 void
_Assert(char * expr,char * strFile,unsigned uLine)50 _Assert(char *expr, char *strFile, unsigned uLine)
51 {
52 printf(ds, "Assertion failed: %s %s, line %u\n", expr, strFile, uLine);
53 //DSPRINTF(ds, "Assertion failed: %s %s, line %u", expr, strFile, uLine);
54 MONO_PRINT(ds);
55 exit(0);
56 }
57
58 ////////////////////////////////////////////////////////////////////
59 //
60 // FLOOR ABOVE FLOOR
61 //
62 ////////////////////////////////////////////////////////////////////
63
64
65 #define ZMAX 400
66 typedef struct
67 {
68 LONG zval[ZMAX];
69 SHORT sectnum[ZMAX];
70 SHORT pic[ZMAX];
71 SHORT slope[ZMAX];
72 SHORT zcount;
73 } SAVE, *SAVEp;
74
75 SAVE save;
76
77 BOOL FAF_DebugView = 0;
78 BOOL FAFon = 0;
79 BOOL FAF_DontMoveSectors = FALSE;
80
81 short bak_searchsector, bak_searchwall, bak_searchstat;
82 extern short searchsector, searchwall, searchstat, searchit;
83
84 VOID SetupBuildFAF(VOID);
85 VOID ResetBuildFAF(VOID);
86
ToggleFAF(void)87 void ToggleFAF(void)
88 {
89 if (keystatus[KEYSC_3])
90 {
91 keystatus[KEYSC_3] = FALSE;
92
93 FLIP(FAFon, 1);
94 if (FAFon)
95 {
96 SetupBuildFAF();
97 }
98 else
99 {
100 ResetBuildFAF();
101 }
102 }
103
104 if (FAFon && qsetmode == 200)
105 {
106 DrawOverlapRoom(posx, posy, posz, ang, horiz, cursectnum);
107
108 // make it so that you can edit both areas in 3D
109 // back up vars after the first drawrooms
110 bak_searchsector = searchsector;
111 bak_searchwall = searchwall;
112 bak_searchstat = searchstat;
113 searchit = 2;
114 }
115
116 if (FAFon && qsetmode == 200 && keystatus[KEYSC_4])
117 {
118 short match;
119 int tx,ty,tz;
120 short tsectnum;
121 short i;
122 keystatus[KEYSC_4] = FALSE;
123
124 tx = posx;
125 ty = posy;
126 tz = posz;
127 tsectnum = cursectnum;
128
129 save.zcount = 0;
130
131 if (sector[cursectnum].ceilingpicnum == FAF_MIRROR_PIC)
132 {
133 match = ViewSectorInScene(tsectnum, VIEW_THRU_CEILING, VIEW_LEVEL1);
134
135 FAF_DontMoveSectors = TRUE;
136 FindCeilingView(match, &tx, &ty, tz, &tsectnum);
137 FAF_DontMoveSectors = FALSE;
138
139 posx = tx;
140 posy = ty;
141 cursectnum = tsectnum;
142 posz = sector[cursectnum].floorz - Z(20);
143 }
144 else
145 if (sector[cursectnum].floorpicnum == FAF_MIRROR_PIC)
146 {
147 match = ViewSectorInScene(tsectnum, VIEW_THRU_FLOOR, VIEW_LEVEL2);
148
149 FAF_DontMoveSectors = TRUE;
150 FindFloorView(match, &tx, &ty, tz, &tsectnum);
151 FAF_DontMoveSectors = FALSE;
152
153 posx = tx;
154 posy = ty;
155 cursectnum = tsectnum;
156 posz = sector[cursectnum].ceilingz + Z(20);
157 }
158 }
159
160
161 }
162
163
FAF_AfterDrawRooms(void)164 void FAF_AfterDrawRooms(void)
165 {
166 // make it so that you can edit both areas in 3D
167 // if your cursor is in the FAF_MIRROR_PIC area use the vars from the first
168 // drawrooms instead
169 if ((searchstat == 1 && sector[searchsector].ceilingpicnum == FAF_MIRROR_PIC) ||
170 (searchstat == 2 && sector[searchsector].floorpicnum == FAF_MIRROR_PIC))
171 {
172 searchsector = bak_searchsector;
173 searchwall = bak_searchwall;
174 searchstat = bak_searchstat;
175 }
176 }
177
178 VOID
SetupBuildFAF(VOID)179 SetupBuildFAF(VOID)
180 {
181 short i, nexti;
182 SPRITEp sp,vc_sp,vf_sp,vl_sp;
183 short SpriteNum, NextSprite;
184 short vc,nextvc,vf,nextvf,l,nextl;
185 int zdiff;
186
187 // move every sprite to the correct list
188 TRAVERSE_SPRITE_STAT(headspritestat[STAT_DEFAULT], SpriteNum, NextSprite)
189 {
190 sp = &sprite[SpriteNum];
191
192 if (sp->picnum != ST1)
193 continue;
194
195 switch (sp->hitag)
196 {
197 case VIEW_THRU_CEILING:
198 case VIEW_THRU_FLOOR:
199 {
200 int i,nexti;
201 // make sure there is only one set per level of these
202 TRAVERSE_SPRITE_STAT(headspritestat[STAT_FAF], i, nexti)
203 {
204 if (sprite[i].hitag == sp->hitag && sprite[i].lotag == sp->lotag)
205 {
206 sprintf(ds,"Two VIEW_THRU_ tags with same match found on level\n1: x %d, y %d \n2: x %d, y %d", sp->x, sp->y, sprite[i].x, sprite[i].y);
207 Message(ds,0);
208 }
209 }
210
211 changespritestat(SpriteNum, STAT_FAF);
212 break;
213 }
214
215 case VIEW_LEVEL1:
216 case VIEW_LEVEL2:
217 case VIEW_LEVEL3:
218 case VIEW_LEVEL4:
219 case VIEW_LEVEL5:
220 case VIEW_LEVEL6:
221 {
222 changespritestat(SpriteNum, STAT_FAF);
223 break;
224 }
225 }
226 }
227
228 TRAVERSE_SPRITE_STAT(headspritestat[STAT_FAF], i, nexti)
229 {
230 sp = &sprite[i];
231
232 if (sector[sp->sectnum].ceilingpicnum == FAF_PLACE_MIRROR_PIC)
233 {
234 sector[sp->sectnum].ceilingpicnum = FAF_MIRROR_PIC;
235 if (sector[sp->sectnum].floorz == sector[sp->sectnum].ceilingz)
236 {
237 sprintf(ds, "Mirror used for non-connect area. Use tile 342. Sect %d, x %d, y %d\n", sp->sectnum, wall[sector[sp->sectnum].wallptr].x, wall[sector[sp->sectnum].wallptr].y);
238 Message(ds,0);
239 }
240 }
241
242 if (sector[sp->sectnum].floorpicnum == FAF_PLACE_MIRROR_PIC)
243 {
244 sector[sp->sectnum].floorpicnum = FAF_MIRROR_PIC;
245 if (sector[sp->sectnum].floorz == sector[sp->sectnum].ceilingz)
246 {
247 sprintf(ds, "Mirror used for non-connect area. Use tile 342. Sect %d, x %d, y %d\n", sp->sectnum, wall[sector[sp->sectnum].wallptr].x, wall[sector[sp->sectnum].wallptr].y);
248 Message(ds,0);
249 }
250 }
251
252 if (sector[sp->sectnum].ceilingpicnum == FAF_PLACE_MIRROR_PIC+1)
253 sector[sp->sectnum].ceilingpicnum = FAF_MIRROR_PIC+1;
254
255 if (sector[sp->sectnum].floorpicnum == FAF_PLACE_MIRROR_PIC+1)
256 sector[sp->sectnum].floorpicnum = FAF_MIRROR_PIC+1;
257 }
258
259
260 for (i = 0; i < numwalls; i++)
261 {
262 if (wall[i].picnum == FAF_PLACE_MIRROR_PIC)
263 wall[i].picnum = FAF_MIRROR_PIC;
264
265 if (wall[i].picnum == FAF_PLACE_MIRROR_PIC+1)
266 wall[i].picnum = FAF_MIRROR_PIC+1;
267 }
268
269 #if 0
270 // check ceiling and floor heights
271 TRAVERSE_SPRITE_STAT(headspritestat[STAT_FAF], vc, nextvc)
272 {
273 vc_sp = &sprite[vc];
274
275 if (vc_sp->hitag == VIEW_THRU_CEILING)
276 {
277 TRAVERSE_SPRITE_STAT(headspritestat[STAT_FAF], vf, nextvf)
278 {
279 vf_sp = &sprite[vf];
280
281 if (vf_sp->hitag == VIEW_THRU_FLOOR && vf_sp->lotag == vc_sp->lotag)
282 {
283 zdiff = labs(sector[vc_sp->sectnum].ceilingz - sector[vf_sp->sectnum].floorz);
284
285 //DSPRINTF(ds,"zdiff %d",zdiff);
286 MONO_PRINT(ds);
287
288 TRAVERSE_SPRITE_STAT(headspritestat[STAT_FAF], l, nextl)
289 {
290 vl_sp = &sprite[l];
291
292 if (vl_sp->hitag == VIEW_LEVEL1)
293 {
294 if (sector[vl_sp->sectnum].ceilingz < sector[vc_sp->sectnum].ceilingz + zdiff)
295 {
296 sprintf(ds,"Sector %d (x %d, y %d) ceiling z to close to VIEW_THRU_CEILING z",
297 vl_sp->sectnum, wall[sector[vl_sp->sectnum].wallptr].x, wall[sector[vl_sp->sectnum].wallptr].y);
298 Message(ds,0);
299 }
300 }
301 else
302 if (vl_sp->hitag == VIEW_LEVEL2)
303 {
304 if (sector[vl_sp->sectnum].floorz > sector[vf_sp->sectnum].floorz + zdiff)
305 {
306 sprintf(ds,"Sector %d (x %d, y %d)floor z to close to VIEW_THRU_FLOOR z",
307 vl_sp->sectnum, wall[sector[vl_sp->sectnum].wallptr].x, wall[sector[vl_sp->sectnum].wallptr].y);
308 Message(ds,0);
309 }
310 }
311 }
312 }
313 }
314 }
315 }
316 #endif
317
318 }
319
320 VOID
ResetBuildFAF(VOID)321 ResetBuildFAF(VOID)
322 {
323 short i, nexti;
324 SPRITEp sp;
325
326 TRAVERSE_SPRITE_STAT(headspritestat[STAT_FAF], i, nexti)
327 {
328 sp = &sprite[i];
329
330 if (sector[sp->sectnum].ceilingpicnum == FAF_MIRROR_PIC)
331 sector[sp->sectnum].ceilingpicnum = FAF_PLACE_MIRROR_PIC;
332
333 if (sector[sp->sectnum].floorpicnum == FAF_MIRROR_PIC)
334 sector[sp->sectnum].floorpicnum = FAF_PLACE_MIRROR_PIC;
335
336 if (sector[sp->sectnum].ceilingpicnum == FAF_MIRROR_PIC+1)
337 sector[sp->sectnum].ceilingpicnum = FAF_PLACE_MIRROR_PIC+1;
338
339 if (sector[sp->sectnum].floorpicnum == FAF_MIRROR_PIC+1)
340 sector[sp->sectnum].floorpicnum = FAF_PLACE_MIRROR_PIC+1;
341 }
342
343 for (i = 0; i < numwalls; i++)
344 {
345 if (wall[i].picnum == FAF_MIRROR_PIC)
346 wall[i].picnum = FAF_PLACE_MIRROR_PIC;
347
348 if (wall[i].picnum == FAF_MIRROR_PIC+1)
349 wall[i].picnum = FAF_PLACE_MIRROR_PIC+1;
350 }
351
352 TRAVERSE_SPRITE_STAT(headspritestat[STAT_FAF], i, nexti)
353 {
354 changespritestat(i, STAT_DEFAULT);
355 }
356 }
357
358
359 BOOL
PicInView(short tile_num,BOOL reset)360 PicInView(short tile_num, BOOL reset)
361 {
362 if (TEST(gotpic[tile_num >> 3], 1 << (tile_num & 7)))
363 {
364 if (reset)
365 RESET(gotpic[tile_num >> 3], 1 << (tile_num & 7));
366
367 return (TRUE);
368 }
369
370 return (FALSE);
371 }
372
373 void
GetUpperLowerSector(short match,int x,int y,short * upper,short * lower)374 GetUpperLowerSector(short match, int x, int y, short *upper, short *lower)
375 {
376 int i, j;
377 short sectorlist[16];
378 short sln = 0;
379 short SpriteNum, Next;
380 SPRITEp sp;
381
382 // didn't find it yet so test ALL sectors
383 if (sln < 2)
384 {
385 sln = 0;
386 for (i = numsectors - 1; i >= 0; i--)
387 {
388 if (inside(x, y, (short) i) == 1)
389 {
390 BOOL found = FALSE;
391
392 TRAVERSE_SPRITE_SECT(headspritesect[i], SpriteNum, Next)
393 {
394 sp = &sprite[SpriteNum];
395
396 if (sp->statnum == STAT_FAF &&
397 (sp->hitag >= VIEW_LEVEL1 && sp->hitag <= VIEW_LEVEL6)
398 && sp->lotag == match)
399 {
400 found = TRUE;
401 }
402 }
403
404 if (!found)
405 continue;
406
407 sectorlist[sln] = i;
408 sln++;
409 }
410 }
411 }
412
413 if (sln == 0)
414 {
415 *upper = -1;
416 *lower = -1;
417 return;
418 }
419
420 // Map rooms have NOT been dragged on top of each other
421 if (sln == 1)
422 {
423 *lower = sectorlist[0];
424 *upper = sectorlist[0];
425 return;
426 }
427 else
428 // Map rooms HAVE been dragged on top of each other
429 if (sln > 2)
430 {
431 // try again moving the x,y pos around until you only get two sectors
432 GetUpperLowerSector(match, x - 1, y, upper, lower);
433 }
434
435 if (sln == 2)
436 {
437 if (sector[sectorlist[0]].floorz < sector[sectorlist[1]].floorz)
438 {
439 // swap
440 // make sectorlist[0] the LOW sector
441 short hold;
442
443 hold = sectorlist[0];
444 sectorlist[0] = sectorlist[1];
445 sectorlist[1] = hold;
446 }
447
448 *lower = sectorlist[0];
449 *upper = sectorlist[1];
450 }
451 }
452
453 BOOL
FindCeilingView(short match,LONGp x,LONGp y,LONG z,SHORTp sectnum)454 FindCeilingView(short match, LONGp x, LONGp y, LONG z, SHORTp sectnum)
455 {
456 int xoff = 0;
457 int yoff = 0;
458 short i, nexti;
459 SPRITEp sp = NULL;
460 short top_sprite = -1;
461 int pix_diff;
462 int newz;
463
464 save.zcount = 0;
465
466 // Search Stat List For closest ceiling view sprite
467 // Get the match, xoff, yoff from this point
468 TRAVERSE_SPRITE_STAT(headspritestat[STAT_FAF], i, nexti)
469 {
470 sp = &sprite[i];
471
472 if (sp->hitag == VIEW_THRU_CEILING && sp->lotag == match)
473 {
474 xoff = *x - sp->x;
475 yoff = *y - sp->y;
476
477 break;
478 }
479 }
480
481 TRAVERSE_SPRITE_STAT(headspritestat[STAT_FAF], i, nexti)
482 {
483 sp = &sprite[i];
484
485 if (sp->lotag == match)
486 {
487 // determine x,y position
488 if (sp->hitag == VIEW_THRU_FLOOR)
489 {
490 short upper, lower;
491
492 *x = sp->x + xoff;
493 *y = sp->y + yoff;
494
495 // get new sector
496 GetUpperLowerSector(match, *x, *y, &upper, &lower);
497 *sectnum = upper;
498 break;
499 }
500 }
501 }
502
503 if (*sectnum < 0)
504 return(FALSE);
505
506 ASSERT(sp);
507 ASSERT(sp->hitag == VIEW_THRU_FLOOR);
508
509 if (FAF_DontMoveSectors)
510 return(TRUE);
511
512 pix_diff = labs(z - sector[sp->sectnum].floorz) >> 8;
513 newz = sector[sp->sectnum].floorz + ((pix_diff / 128) + 1) * Z(128);
514
515 TRAVERSE_SPRITE_STAT(headspritestat[STAT_FAF], i, nexti)
516 {
517 sp = &sprite[i];
518
519 if (sp->lotag == match)
520 {
521 // move lower levels ceilings up for the correct view
522 if (sp->hitag == VIEW_LEVEL2)
523 {
524 // save it off
525 save.sectnum[save.zcount] = sp->sectnum;
526 save.zval[save.zcount] = sector[sp->sectnum].floorz;
527 save.pic[save.zcount] = sector[sp->sectnum].floorpicnum;
528 save.slope[save.zcount] = sector[sp->sectnum].floorheinum;
529
530 sector[sp->sectnum].floorz = newz;
531 sector[sp->sectnum].floorpicnum = FAF_MIRROR_PIC+1;
532 sector[sp->sectnum].floorheinum = 0;
533
534 save.zcount++;
535 ASSERT(save.zcount < ZMAX);
536 }
537 }
538 }
539
540 return (TRUE);
541 }
542
543 BOOL
FindFloorView(short match,LONGp x,LONGp y,LONG z,SHORTp sectnum)544 FindFloorView(short match, LONGp x, LONGp y, LONG z, SHORTp sectnum)
545 {
546 int xoff = 0;
547 int yoff = 0;
548 short i, nexti;
549 SPRITEp sp = NULL;
550 int newz;
551 int pix_diff;
552
553 save.zcount = 0;
554
555 // Search Stat List For closest ceiling view sprite
556 // Get the match, xoff, yoff from this point
557 TRAVERSE_SPRITE_STAT(headspritestat[STAT_FAF], i, nexti)
558 {
559 sp = &sprite[i];
560
561 if (sp->hitag == VIEW_THRU_FLOOR && sp->lotag == match)
562 {
563 xoff = *x - sp->x;
564 yoff = *y - sp->y;
565
566 break;
567 }
568 }
569
570
571
572 TRAVERSE_SPRITE_STAT(headspritestat[STAT_FAF], i, nexti)
573 {
574 sp = &sprite[i];
575
576 if (sp->lotag == match)
577 {
578 // determine x,y position
579 if (sp->hitag == VIEW_THRU_CEILING)
580 {
581 short upper, lower;
582
583 *x = sp->x + xoff;
584 *y = sp->y + yoff;
585
586 // get new sector
587 GetUpperLowerSector(match, *x, *y, &upper, &lower);
588 *sectnum = lower;
589 break;
590 }
591 }
592 }
593
594 if (*sectnum < 0)
595 return(FALSE);
596
597 ASSERT(sp);
598 ASSERT(sp->hitag == VIEW_THRU_CEILING);
599
600 if (FAF_DontMoveSectors)
601 return(TRUE);
602
603 // move ceiling multiple of 128 so that the wall tile will line up
604 pix_diff = labs(z - sector[sp->sectnum].ceilingz) >> 8;
605 newz = sector[sp->sectnum].ceilingz - ((pix_diff / 128) + 1) * Z(128);
606
607 TRAVERSE_SPRITE_STAT(headspritestat[STAT_FAF], i, nexti)
608 {
609 sp = &sprite[i];
610
611 if (sp->lotag == match)
612 {
613 // move upper levels floors down for the correct view
614 if (sp->hitag == VIEW_LEVEL1)
615 {
616 // save it off
617 save.sectnum[save.zcount] = sp->sectnum;
618 save.zval[save.zcount] = sector[sp->sectnum].ceilingz;
619 save.pic[save.zcount] = sector[sp->sectnum].ceilingpicnum;
620 save.slope[save.zcount] = sector[sp->sectnum].ceilingheinum;
621
622 sector[sp->sectnum].ceilingz = newz;
623
624 sector[sp->sectnum].ceilingpicnum = FAF_MIRROR_PIC+1;
625 sector[sp->sectnum].ceilingheinum = 0;
626
627 save.zcount++;
628 ASSERT(save.zcount < ZMAX);
629 }
630 }
631 }
632
633 return (TRUE);
634 }
635
636 BOOL
SectorInScene(short tile_num)637 SectorInScene(short tile_num)
638 {
639 if (TEST(gotsector[tile_num >> 3], 1 << (tile_num & 7)))
640 {
641 RESET(gotsector[tile_num >> 3], 1 << (tile_num & 7));
642 return (TRUE);
643 }
644
645 return (FALSE);
646 }
647
648 short
ViewSectorInScene(short cursectnum,short type,short level)649 ViewSectorInScene(short cursectnum, short type, short level)
650 {
651 int i, nexti;
652 int j, nextj;
653 SPRITEp sp;
654 SPRITEp sp2;
655 int cz, fz;
656 short match;
657
658 TRAVERSE_SPRITE_STAT(headspritestat[STAT_FAF], i, nexti)
659 {
660 sp = &sprite[i];
661
662 if (sp->hitag == level)
663 {
664 if (cursectnum == sp->sectnum)
665 {
666 // ignore case if sprite is pointing up
667 if (sp->ang == 1536)
668 continue;
669
670 // only gets to here is sprite is pointing down
671 // found a potential match
672 match = sp->lotag;
673
674 return(match);
675 }
676 }
677 }
678
679 return (-1);
680 }
681
682 VOID
DrawOverlapRoom(int tx,int ty,int tz,short tang,int thoriz,short tsectnum)683 DrawOverlapRoom(int tx, int ty, int tz, short tang, int thoriz, short tsectnum)
684 {
685 short i;
686 short match;
687
688 save.zcount = 0;
689
690 match = ViewSectorInScene(tsectnum, VIEW_THRU_CEILING, VIEW_LEVEL1);
691 if (match != -1)
692 {
693 FindCeilingView(match, &tx, &ty, tz, &tsectnum);
694
695 if (tsectnum < 0)
696 {
697 sprintf(ds,"COULD NOT FIND TAGGED LEVEL2 SECTOR FROM X %d, Y %d, SECTNUM %d.",posx,posy,cursectnum);
698 Message(ds, 0);
699 return;
700 }
701
702 drawrooms(tx, ty, tz, tang, thoriz, tsectnum);
703 drawmasks();
704
705 // reset Z's
706 for (i = 0; i < save.zcount; i++)
707 {
708 sector[save.sectnum[i]].floorz = save.zval[i];
709 sector[save.sectnum[i]].floorpicnum = save.pic[i];
710 sector[save.sectnum[i]].floorheinum = save.slope[i];
711 }
712 }
713 else
714 {
715 match = ViewSectorInScene(tsectnum, VIEW_THRU_FLOOR, VIEW_LEVEL2);
716 if (match != -1)
717 {
718 FindFloorView(match, &tx, &ty, tz, &tsectnum);
719
720 if (tsectnum < 0)
721 {
722 sprintf(ds,"COULD NOT FIND TAGGED LEVEL1 SECTOR FROM X %d, Y %d, SECTNUM %d.",posx,posy,cursectnum);
723 Message(ds, 0);
724 return;
725 }
726
727 drawrooms(tx, ty, tz, tang, thoriz, tsectnum);
728 drawmasks();
729
730 // reset Z's
731 for (i = 0; i < save.zcount; i++)
732 {
733 sector[save.sectnum[i]].ceilingz = save.zval[i];
734 sector[save.sectnum[i]].ceilingpicnum = save.pic[i];
735 sector[save.sectnum[i]].ceilingheinum = save.slope[i];
736 }
737 }
738 }
739 }
740