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