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