raze-gles/polymer/eduke32/source/sw/src/brooms.c

738 lines
20 KiB
C
Raw Normal View History

//-------------------------------------------------------------------------
/*
Copyright (C) 1996, 2005 - 3D Realms Entertainment
This file is NOT part of Shadow Warrior version 1.2
However, it is either an older version of a file that is, or is
some test code written during the development of Shadow Warrior.
This file is provided purely for educational interest.
Shadow Warrior is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
Prepared for public release: 03/28/2005 - Charlie Wiederhold, 3D Realms
*/
//-------------------------------------------------------------------------
#include "build.h"
#include "editor.h"
#include "keys.h"
#include "names2.h"
#include "game.h"
extern int posx, posy, posz;
extern short cursectnum;
extern short ang;
extern int horiz;
extern int qsetmode;
SWBOOL FindCeilingView(short match, int32_t* x, int32_t* y, int32_t z, int16_t* sectnum);
SWBOOL FindFloorView(short match, int32_t* x, int32_t* y, int32_t z, int16_t* sectnum);
short ViewSectorInScene(short cursectnum, short type, short level);
void Message(char *string, char color);
void
_Assert(char *expr, char *strFile, unsigned uLine)
{
printf(ds, "Assertion failed: %s %s, line %u\n", expr, strFile, uLine);
//DSPRINTF(ds, "Assertion failed: %s %s, line %u", expr, strFile, uLine);
MONO_PRINT(ds);
exit(0);
}
////////////////////////////////////////////////////////////////////
//
// FLOOR ABOVE FLOOR
//
////////////////////////////////////////////////////////////////////
#define ZMAX 400
typedef struct
{
int32_t zval[ZMAX];
int16_t sectnum[ZMAX];
int16_t pic[ZMAX];
int16_t slope[ZMAX];
int16_t zcount;
} SAVE, *SAVEp;
SAVE save;
SWBOOL FAF_DebugView = 0;
SWBOOL FAFon = 0;
SWBOOL FAF_DontMoveSectors = FALSE;
short bak_searchsector, bak_searchwall, bak_searchstat;
extern short searchsector, searchwall, searchstat, searchit;
void SetupBuildFAF(void);
void ResetBuildFAF(void);
void ToggleFAF(void)
{
if (keystatus[KEYSC_3])
{
keystatus[KEYSC_3] = FALSE;
FLIP(FAFon, 1);
if (FAFon)
{
SetupBuildFAF();
}
else
{
ResetBuildFAF();
}
}
if (FAFon && qsetmode == 200)
{
DrawOverlapRoom(posx, posy, posz, ang, horiz, cursectnum);
// make it so that you can edit both areas in 3D
// back up vars after the first drawrooms
bak_searchsector = searchsector;
bak_searchwall = searchwall;
bak_searchstat = searchstat;
searchit = 2;
}
if (FAFon && qsetmode == 200 && keystatus[KEYSC_4])
{
short match;
int tx,ty,tz;
short tsectnum;
short i;
keystatus[KEYSC_4] = FALSE;
tx = posx;
ty = posy;
tz = posz;
tsectnum = cursectnum;
save.zcount = 0;
if (sector[cursectnum].ceilingpicnum == FAF_MIRROR_PIC)
{
match = ViewSectorInScene(tsectnum, VIEW_THRU_CEILING, VIEW_LEVEL1);
FAF_DontMoveSectors = TRUE;
FindCeilingView(match, &tx, &ty, tz, &tsectnum);
FAF_DontMoveSectors = FALSE;
posx = tx;
posy = ty;
cursectnum = tsectnum;
posz = sector[cursectnum].floorz - Z(20);
}
else if (sector[cursectnum].floorpicnum == FAF_MIRROR_PIC)
{
match = ViewSectorInScene(tsectnum, VIEW_THRU_FLOOR, VIEW_LEVEL2);
FAF_DontMoveSectors = TRUE;
FindFloorView(match, &tx, &ty, tz, &tsectnum);
FAF_DontMoveSectors = FALSE;
posx = tx;
posy = ty;
cursectnum = tsectnum;
posz = sector[cursectnum].ceilingz + Z(20);
}
}
}
void FAF_AfterDrawRooms(void)
{
// make it so that you can edit both areas in 3D
// if your cursor is in the FAF_MIRROR_PIC area use the vars from the first
// drawrooms instead
if ((searchstat == 1 && sector[searchsector].ceilingpicnum == FAF_MIRROR_PIC) ||
(searchstat == 2 && sector[searchsector].floorpicnum == FAF_MIRROR_PIC))
{
searchsector = bak_searchsector;
searchwall = bak_searchwall;
searchstat = bak_searchstat;
}
}
void
SetupBuildFAF(void)
{
short i, nexti;
SPRITEp sp,vc_sp,vf_sp,vl_sp;
short SpriteNum, NextSprite;
short vc,nextvc,vf,nextvf,l,nextl;
int zdiff;
// move every sprite to the correct list
TRAVERSE_SPRITE_STAT(headspritestat[STAT_DEFAULT], SpriteNum, NextSprite)
{
sp = &sprite[SpriteNum];
if (sp->picnum != ST1)
continue;
switch (sp->hitag)
{
case VIEW_THRU_CEILING:
case VIEW_THRU_FLOOR:
{
int i,nexti;
// make sure there is only one set per level of these
TRAVERSE_SPRITE_STAT(headspritestat[STAT_FAF], i, nexti)
{
if (sprite[i].hitag == sp->hitag && sprite[i].lotag == sp->lotag)
{
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);
Message(ds,0);
}
}
changespritestat(SpriteNum, STAT_FAF);
break;
}
case VIEW_LEVEL1:
case VIEW_LEVEL2:
case VIEW_LEVEL3:
case VIEW_LEVEL4:
case VIEW_LEVEL5:
case VIEW_LEVEL6:
{
changespritestat(SpriteNum, STAT_FAF);
break;
}
}
}
TRAVERSE_SPRITE_STAT(headspritestat[STAT_FAF], i, nexti)
{
sp = &sprite[i];
if (sector[sp->sectnum].ceilingpicnum == FAF_PLACE_MIRROR_PIC)
{
sector[sp->sectnum].ceilingpicnum = FAF_MIRROR_PIC;
if (sector[sp->sectnum].floorz == sector[sp->sectnum].ceilingz)
{
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);
Message(ds,0);
}
}
if (sector[sp->sectnum].floorpicnum == FAF_PLACE_MIRROR_PIC)
{
sector[sp->sectnum].floorpicnum = FAF_MIRROR_PIC;
if (sector[sp->sectnum].floorz == sector[sp->sectnum].ceilingz)
{
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);
Message(ds,0);
}
}
if (sector[sp->sectnum].ceilingpicnum == FAF_PLACE_MIRROR_PIC+1)
sector[sp->sectnum].ceilingpicnum = FAF_MIRROR_PIC+1;
if (sector[sp->sectnum].floorpicnum == FAF_PLACE_MIRROR_PIC+1)
sector[sp->sectnum].floorpicnum = FAF_MIRROR_PIC+1;
}
for (i = 0; i < numwalls; i++)
{
if (wall[i].picnum == FAF_PLACE_MIRROR_PIC)
wall[i].picnum = FAF_MIRROR_PIC;
if (wall[i].picnum == FAF_PLACE_MIRROR_PIC+1)
wall[i].picnum = FAF_MIRROR_PIC+1;
}
#if 0
// check ceiling and floor heights
TRAVERSE_SPRITE_STAT(headspritestat[STAT_FAF], vc, nextvc)
{
vc_sp = &sprite[vc];
if (vc_sp->hitag == VIEW_THRU_CEILING)
{
TRAVERSE_SPRITE_STAT(headspritestat[STAT_FAF], vf, nextvf)
{
vf_sp = &sprite[vf];
if (vf_sp->hitag == VIEW_THRU_FLOOR && vf_sp->lotag == vc_sp->lotag)
{
zdiff = labs(sector[vc_sp->sectnum].ceilingz - sector[vf_sp->sectnum].floorz);
//DSPRINTF(ds,"zdiff %d",zdiff);
MONO_PRINT(ds);
TRAVERSE_SPRITE_STAT(headspritestat[STAT_FAF], l, nextl)
{
vl_sp = &sprite[l];
if (vl_sp->hitag == VIEW_LEVEL1)
{
if (sector[vl_sp->sectnum].ceilingz < sector[vc_sp->sectnum].ceilingz + zdiff)
{
sprintf(ds,"Sector %d (x %d, y %d) ceiling z to close to VIEW_THRU_CEILING z",
vl_sp->sectnum, wall[sector[vl_sp->sectnum].wallptr].x, wall[sector[vl_sp->sectnum].wallptr].y);
Message(ds,0);
}
}
else if (vl_sp->hitag == VIEW_LEVEL2)
{
if (sector[vl_sp->sectnum].floorz > sector[vf_sp->sectnum].floorz + zdiff)
{
sprintf(ds,"Sector %d (x %d, y %d)floor z to close to VIEW_THRU_FLOOR z",
vl_sp->sectnum, wall[sector[vl_sp->sectnum].wallptr].x, wall[sector[vl_sp->sectnum].wallptr].y);
Message(ds,0);
}
}
}
}
}
}
}
#endif
}
void
ResetBuildFAF(void)
{
short i, nexti;
SPRITEp sp;
TRAVERSE_SPRITE_STAT(headspritestat[STAT_FAF], i, nexti)
{
sp = &sprite[i];
if (sector[sp->sectnum].ceilingpicnum == FAF_MIRROR_PIC)
sector[sp->sectnum].ceilingpicnum = FAF_PLACE_MIRROR_PIC;
if (sector[sp->sectnum].floorpicnum == FAF_MIRROR_PIC)
sector[sp->sectnum].floorpicnum = FAF_PLACE_MIRROR_PIC;
if (sector[sp->sectnum].ceilingpicnum == FAF_MIRROR_PIC+1)
sector[sp->sectnum].ceilingpicnum = FAF_PLACE_MIRROR_PIC+1;
if (sector[sp->sectnum].floorpicnum == FAF_MIRROR_PIC+1)
sector[sp->sectnum].floorpicnum = FAF_PLACE_MIRROR_PIC+1;
}
for (i = 0; i < numwalls; i++)
{
if (wall[i].picnum == FAF_MIRROR_PIC)
wall[i].picnum = FAF_PLACE_MIRROR_PIC;
if (wall[i].picnum == FAF_MIRROR_PIC+1)
wall[i].picnum = FAF_PLACE_MIRROR_PIC+1;
}
TRAVERSE_SPRITE_STAT(headspritestat[STAT_FAF], i, nexti)
{
changespritestat(i, STAT_DEFAULT);
}
}
SWBOOL
PicInView(short tile_num, SWBOOL reset)
{
if (TEST(gotpic[tile_num >> 3], 1 << (tile_num & 7)))
{
if (reset)
RESET(gotpic[tile_num >> 3], 1 << (tile_num & 7));
return TRUE;
}
return FALSE;
}
void
GetUpperLowerSector(short match, int x, int y, short *upper, short *lower)
{
int i, j;
short sectorlist[16];
short sln = 0;
short SpriteNum, Next;
SPRITEp sp;
// didn't find it yet so test ALL sectors
if (sln < 2)
{
sln = 0;
for (i = numsectors - 1; i >= 0; i--)
{
if (inside(x, y, (short) i) == 1)
{
SWBOOL found = FALSE;
TRAVERSE_SPRITE_SECT(headspritesect[i], SpriteNum, Next)
{
sp = &sprite[SpriteNum];
if (sp->statnum == STAT_FAF &&
(sp->hitag >= VIEW_LEVEL1 && sp->hitag <= VIEW_LEVEL6)
&& sp->lotag == match)
{
found = TRUE;
}
}
if (!found)
continue;
sectorlist[sln] = i;
sln++;
}
}
}
if (sln == 0)
{
*upper = -1;
*lower = -1;
return;
}
// Map rooms have NOT been dragged on top of each other
if (sln == 1)
{
*lower = sectorlist[0];
*upper = sectorlist[0];
return;
}
else
// Map rooms HAVE been dragged on top of each other
if (sln > 2)
{
// try again moving the x,y pos around until you only get two sectors
GetUpperLowerSector(match, x - 1, y, upper, lower);
}
if (sln == 2)
{
if (sector[sectorlist[0]].floorz < sector[sectorlist[1]].floorz)
{
// swap
// make sectorlist[0] the LOW sector
short hold;
hold = sectorlist[0];
sectorlist[0] = sectorlist[1];
sectorlist[1] = hold;
}
*lower = sectorlist[0];
*upper = sectorlist[1];
}
}
SWBOOL
FindCeilingView(short match, int32_t* x, int32_t* y, int32_t z, int16_t* sectnum)
{
int xoff = 0;
int yoff = 0;
short i, nexti;
SPRITEp sp = NULL;
short top_sprite = -1;
int pix_diff;
int newz;
save.zcount = 0;
// Search Stat List For closest ceiling view sprite
// Get the match, xoff, yoff from this point
TRAVERSE_SPRITE_STAT(headspritestat[STAT_FAF], i, nexti)
{
sp = &sprite[i];
if (sp->hitag == VIEW_THRU_CEILING && sp->lotag == match)
{
xoff = *x - sp->x;
yoff = *y - sp->y;
break;
}
}
TRAVERSE_SPRITE_STAT(headspritestat[STAT_FAF], i, nexti)
{
sp = &sprite[i];
if (sp->lotag == match)
{
// determine x,y position
if (sp->hitag == VIEW_THRU_FLOOR)
{
short upper, lower;
*x = sp->x + xoff;
*y = sp->y + yoff;
// get new sector
GetUpperLowerSector(match, *x, *y, &upper, &lower);
*sectnum = upper;
break;
}
}
}
if (*sectnum < 0)
return FALSE;
ASSERT(sp);
ASSERT(sp->hitag == VIEW_THRU_FLOOR);
if (FAF_DontMoveSectors)
return TRUE;
pix_diff = labs(z - sector[sp->sectnum].floorz) >> 8;
newz = sector[sp->sectnum].floorz + ((pix_diff / 128) + 1) * Z(128);
TRAVERSE_SPRITE_STAT(headspritestat[STAT_FAF], i, nexti)
{
sp = &sprite[i];
if (sp->lotag == match)
{
// move lower levels ceilings up for the correct view
if (sp->hitag == VIEW_LEVEL2)
{
// save it off
save.sectnum[save.zcount] = sp->sectnum;
save.zval[save.zcount] = sector[sp->sectnum].floorz;
save.pic[save.zcount] = sector[sp->sectnum].floorpicnum;
save.slope[save.zcount] = sector[sp->sectnum].floorheinum;
sector[sp->sectnum].floorz = newz;
sector[sp->sectnum].floorpicnum = FAF_MIRROR_PIC+1;
sector[sp->sectnum].floorheinum = 0;
save.zcount++;
ASSERT(save.zcount < ZMAX);
}
}
}
return TRUE;
}
SWBOOL
FindFloorView(short match, int32_t* x, int32_t* y, int32_t z, int16_t* sectnum)
{
int xoff = 0;
int yoff = 0;
short i, nexti;
SPRITEp sp = NULL;
int newz;
int pix_diff;
save.zcount = 0;
// Search Stat List For closest ceiling view sprite
// Get the match, xoff, yoff from this point
TRAVERSE_SPRITE_STAT(headspritestat[STAT_FAF], i, nexti)
{
sp = &sprite[i];
if (sp->hitag == VIEW_THRU_FLOOR && sp->lotag == match)
{
xoff = *x - sp->x;
yoff = *y - sp->y;
break;
}
}
TRAVERSE_SPRITE_STAT(headspritestat[STAT_FAF], i, nexti)
{
sp = &sprite[i];
if (sp->lotag == match)
{
// determine x,y position
if (sp->hitag == VIEW_THRU_CEILING)
{
short upper, lower;
*x = sp->x + xoff;
*y = sp->y + yoff;
// get new sector
GetUpperLowerSector(match, *x, *y, &upper, &lower);
*sectnum = lower;
break;
}
}
}
if (*sectnum < 0)
return FALSE;
ASSERT(sp);
ASSERT(sp->hitag == VIEW_THRU_CEILING);
if (FAF_DontMoveSectors)
return TRUE;
// move ceiling multiple of 128 so that the wall tile will line up
pix_diff = labs(z - sector[sp->sectnum].ceilingz) >> 8;
newz = sector[sp->sectnum].ceilingz - ((pix_diff / 128) + 1) * Z(128);
TRAVERSE_SPRITE_STAT(headspritestat[STAT_FAF], i, nexti)
{
sp = &sprite[i];
if (sp->lotag == match)
{
// move upper levels floors down for the correct view
if (sp->hitag == VIEW_LEVEL1)
{
// save it off
save.sectnum[save.zcount] = sp->sectnum;
save.zval[save.zcount] = sector[sp->sectnum].ceilingz;
save.pic[save.zcount] = sector[sp->sectnum].ceilingpicnum;
save.slope[save.zcount] = sector[sp->sectnum].ceilingheinum;
sector[sp->sectnum].ceilingz = newz;
sector[sp->sectnum].ceilingpicnum = FAF_MIRROR_PIC+1;
sector[sp->sectnum].ceilingheinum = 0;
save.zcount++;
ASSERT(save.zcount < ZMAX);
}
}
}
return TRUE;
}
SWBOOL
SectorInScene(short tile_num)
{
if (TEST(gotsector[tile_num >> 3], 1 << (tile_num & 7)))
{
RESET(gotsector[tile_num >> 3], 1 << (tile_num & 7));
return TRUE;
}
return FALSE;
}
short
ViewSectorInScene(short cursectnum, short type, short level)
{
int i, nexti;
int j, nextj;
SPRITEp sp;
SPRITEp sp2;
int cz, fz;
short match;
TRAVERSE_SPRITE_STAT(headspritestat[STAT_FAF], i, nexti)
{
sp = &sprite[i];
if (sp->hitag == level)
{
if (cursectnum == sp->sectnum)
{
// ignore case if sprite is pointing up
if (sp->ang == 1536)
continue;
// only gets to here is sprite is pointing down
// found a potential match
match = sp->lotag;
return match;
}
}
}
return -1;
}
void
DrawOverlapRoom(int tx, int ty, int tz, short tang, int thoriz, short tsectnum)
{
short i;
short match;
save.zcount = 0;
match = ViewSectorInScene(tsectnum, VIEW_THRU_CEILING, VIEW_LEVEL1);
if (match != -1)
{
FindCeilingView(match, &tx, &ty, tz, &tsectnum);
if (tsectnum < 0)
{
sprintf(ds,"COULD NOT FIND TAGGED LEVEL2 SECTOR FROM X %d, Y %d, SECTNUM %d.",posx,posy,cursectnum);
Message(ds, 0);
return;
}
drawrooms(tx, ty, tz, tang, thoriz, tsectnum);
drawmasks();
// reset Z's
for (i = 0; i < save.zcount; i++)
{
sector[save.sectnum[i]].floorz = save.zval[i];
sector[save.sectnum[i]].floorpicnum = save.pic[i];
sector[save.sectnum[i]].floorheinum = save.slope[i];
}
}
else
{
match = ViewSectorInScene(tsectnum, VIEW_THRU_FLOOR, VIEW_LEVEL2);
if (match != -1)
{
FindFloorView(match, &tx, &ty, tz, &tsectnum);
if (tsectnum < 0)
{
sprintf(ds,"COULD NOT FIND TAGGED LEVEL1 SECTOR FROM X %d, Y %d, SECTNUM %d.",posx,posy,cursectnum);
Message(ds, 0);
return;
}
drawrooms(tx, ty, tz, tang, thoriz, tsectnum);
drawmasks();
// reset Z's
for (i = 0; i < save.zcount; i++)
{
sector[save.sectnum[i]].ceilingz = save.zval[i];
sector[save.sectnum[i]].ceilingpicnum = save.pic[i];
sector[save.sectnum[i]].ceilingheinum = save.slope[i];
}
}
}
}