Пример #1
0
sector_t *R_FakeFlat(sector_t *sec, sector_t *tempsec,
					 int *floorlightlevel, int *ceilinglightlevel,
					 bool back)
{
	// [RH] allow per-plane lighting
	if (floorlightlevel != NULL)
	{
		*floorlightlevel = sec->floorlightsec == NULL ?
			sec->lightlevel : sec->floorlightsec->lightlevel;
	}

	if (ceilinglightlevel != NULL)
	{
		*ceilinglightlevel = sec->ceilinglightsec == NULL ? // killough 4/11/98
			sec->lightlevel : sec->ceilinglightsec->lightlevel;
	}

	FakeSide = FAKED_Center;

	if (!sec->heightsec || sec->heightsec->MoreFlags & SECF_IGNOREHEIGHTSEC)
		return sec;
	if (!camera || !camera->subsector || !camera->subsector->sector)
		return sec;

	const sector_t* s = sec->heightsec;
	sector_t *heightsec = camera->subsector->sector->heightsec;

	bool underwater = r_fakingunderwater ||
		(heightsec && viewz <= P_FloorHeight(viewx, viewy, heightsec));
	bool doorunderwater = false;
	int diffTex = (s->MoreFlags & SECF_CLIPFAKEPLANES);

	// Replace sector being drawn with a copy to be hacked
	*tempsec = *sec;

	// Replace floor and ceiling height with control sector's heights.
	if (diffTex)
	{
		if (CopyPlaneIfValid (&tempsec->floorplane, &s->floorplane, &sec->ceilingplane))
			tempsec->floorpic = s->floorpic;
		else if (s->MoreFlags & SECF_FAKEFLOORONLY)
		{
			if (underwater)
			{
				tempsec->colormap = s->colormap;

				if (!(s->MoreFlags & SECF_NOFAKELIGHT))
				{
					tempsec->lightlevel = s->lightlevel;

					if (floorlightlevel != NULL)
					{
						*floorlightlevel = s->floorlightsec == NULL ?
							s->lightlevel : s->floorlightsec->lightlevel;
					}

					if (ceilinglightlevel != NULL)
					{
						*ceilinglightlevel = s->ceilinglightsec == NULL ?
							s->lightlevel : s->ceilinglightsec->lightlevel;
					}
				}

				FakeSide = FAKED_BelowFloor;
				return tempsec;
			}
			return sec;
		}
	}
	else
	{
		tempsec->floorplane = s->floorplane;
	}

	if (!(s->MoreFlags & SECF_FAKEFLOORONLY))
	{
		if (diffTex)
		{
			if (CopyPlaneIfValid (&tempsec->ceilingplane, &s->ceilingplane, &sec->floorplane))
				tempsec->ceilingpic = s->ceilingpic;
		}
		else
		{
			tempsec->ceilingplane  = s->ceilingplane;
		}
	}

	fixed_t refceilz = P_CeilingHeight(viewx, viewy, s);
	fixed_t orgceilz = P_CeilingHeight(viewx, viewy, sec);

	// [RH] Allow viewing underwater areas through doors/windows that
	// are underwater but not in a water sector themselves.
	// Only works if you cannot see the top surface of any deep water
	// sectors at the same time.

	if (back && !r_fakingunderwater && curline->frontsector->heightsec == NULL)
	{
		fixed_t fcz1 = P_CeilingHeight(curline->v1->x, curline->v1->y, frontsector);
		fixed_t fcz2 = P_CeilingHeight(curline->v2->x, curline->v2->y, frontsector);

		if (fcz1 <= P_FloorHeight(curline->v1->x, curline->v1->y, s) &&
			fcz2 <= P_FloorHeight(curline->v2->x, curline->v2->y, s))
		{
			// will any columns of this window be visible or will they be blocked
			// by 1s lines and closed doors?
			if (memchr(solidcol + rw_start, 0, rw_stop - rw_start + 1) != NULL)
			{	
				doorunderwater = true;
				r_fakingunderwater = true;
			}
		}
	}

	if (underwater || doorunderwater)
	{
		tempsec->floorplane = sec->floorplane;
		tempsec->ceilingplane = s->floorplane;
		P_InvertPlane(&tempsec->ceilingplane);
		P_ChangeCeilingHeight(tempsec, -1);
		tempsec->colormap = s->colormap;
	}

	// killough 11/98: prevent sudden light changes from non-water sectors:
	if ((underwater && !back) || doorunderwater)
	{					// head-below-floor hack
		tempsec->floorpic			= diffTex ? sec->floorpic : s->floorpic;
		tempsec->floor_xoffs		= s->floor_xoffs;
		tempsec->floor_yoffs		= s->floor_yoffs;
		tempsec->floor_xscale		= s->floor_xscale;
		tempsec->floor_yscale		= s->floor_yscale;
		tempsec->floor_angle		= s->floor_angle;
		tempsec->base_floor_angle	= s->base_floor_angle;
		tempsec->base_floor_yoffs	= s->base_floor_yoffs;

		tempsec->ceilingplane		= s->floorplane;
		P_InvertPlane(&tempsec->ceilingplane);
		P_ChangeCeilingHeight(tempsec, -1);
		if (s->ceilingpic == skyflatnum)
		{
			tempsec->floorplane			= tempsec->ceilingplane;
			P_InvertPlane(&tempsec->floorplane);
			P_ChangeFloorHeight(tempsec, +1);
			tempsec->ceilingpic			= tempsec->floorpic;
			tempsec->ceiling_xoffs		= tempsec->floor_xoffs;
			tempsec->ceiling_yoffs		= tempsec->floor_yoffs;
			tempsec->ceiling_xscale		= tempsec->floor_xscale;
			tempsec->ceiling_yscale		= tempsec->floor_yscale;
			tempsec->ceiling_angle		= tempsec->floor_angle;
			tempsec->base_ceiling_angle	= tempsec->base_floor_angle;
			tempsec->base_ceiling_yoffs	= tempsec->base_floor_yoffs;
		}
		else
		{
			tempsec->ceilingpic			= diffTex ? s->floorpic : s->ceilingpic;
			tempsec->ceiling_xoffs		= s->ceiling_xoffs;
			tempsec->ceiling_yoffs		= s->ceiling_yoffs;
			tempsec->ceiling_xscale		= s->ceiling_xscale;
			tempsec->ceiling_yscale		= s->ceiling_yscale;
			tempsec->ceiling_angle		= s->ceiling_angle;
			tempsec->base_ceiling_angle	= s->base_ceiling_angle;
			tempsec->base_ceiling_yoffs	= s->base_ceiling_yoffs;
		}

		if (!(s->MoreFlags & SECF_NOFAKELIGHT))
		{
			tempsec->lightlevel = s->lightlevel;

			if (floorlightlevel != NULL)
			{
				*floorlightlevel = s->floorlightsec == NULL ?
					s->lightlevel : s->floorlightsec->lightlevel;
			}

			if (ceilinglightlevel != NULL)
			{
				*ceilinglightlevel = s->ceilinglightsec == NULL ?
					s->lightlevel : s->ceilinglightsec->lightlevel;
			}
		}
		FakeSide = FAKED_BelowFloor;
	}
	else if (heightsec && viewz >= P_CeilingHeight(viewx, viewy, heightsec) &&
			 orgceilz > refceilz && !(s->MoreFlags & SECF_FAKEFLOORONLY))
	{	// Above-ceiling hack
		tempsec->ceilingplane		= s->ceilingplane;
		tempsec->floorplane			= s->ceilingplane;
		P_InvertPlane(&tempsec->floorplane);
		P_ChangeFloorHeight(tempsec, +1);

		tempsec->colormap			= s->colormap;

		tempsec->ceilingpic = diffTex ? sec->ceilingpic : s->ceilingpic;
		tempsec->floorpic											= s->ceilingpic;
		tempsec->floor_xoffs		= tempsec->ceiling_xoffs		= s->ceiling_xoffs;
		tempsec->floor_yoffs		= tempsec->ceiling_yoffs		= s->ceiling_yoffs;
		tempsec->floor_xscale		= tempsec->ceiling_xscale		= s->ceiling_xscale;
		tempsec->floor_yscale		= tempsec->ceiling_yscale		= s->ceiling_yscale;
		tempsec->floor_angle		= tempsec->ceiling_angle		= s->ceiling_angle;
		tempsec->base_floor_angle	= tempsec->base_ceiling_angle	= s->base_ceiling_angle;
		tempsec->base_floor_yoffs	= tempsec->base_ceiling_yoffs	= s->base_ceiling_yoffs;

		if (s->floorpic != skyflatnum)
		{
			tempsec->ceilingplane	= sec->ceilingplane;
			tempsec->floorpic		= s->floorpic;
			tempsec->floor_xoffs	= s->floor_xoffs;
			tempsec->floor_yoffs	= s->floor_yoffs;
			tempsec->floor_xscale	= s->floor_xscale;
			tempsec->floor_yscale	= s->floor_yscale;
			tempsec->floor_angle	= s->floor_angle;
		}

		if (!(s->MoreFlags & SECF_NOFAKELIGHT))
		{
			tempsec->lightlevel  = s->lightlevel;

			if (floorlightlevel != NULL)
			{
				*floorlightlevel = s->floorlightsec == NULL ?
					s->lightlevel : s->floorlightsec->lightlevel;
			}

			if (ceilinglightlevel != NULL)
			{
				*ceilinglightlevel = s->ceilinglightsec == NULL ?
					s->lightlevel : s->ceilinglightsec->lightlevel;
			}
		}
		FakeSide = FAKED_AboveCeiling;
	}
	sec = tempsec;					// Use other sector

	return sec;
}
//
// Move a plane (floor or ceiling) and check for crushing
// [RH] Crush specifies the actual amount of crushing damage inflictable.
//		(Use -1 to prevent it from trying to crush)
//
DMover::EResult DMover::MovePlane (fixed_t speed, fixed_t dest, bool crush,
								   int floorOrCeiling, int direction)
{
	bool	 	flag;
	fixed_t 	lastpos;

	switch (floorOrCeiling)
	{
	case 0:
		// FLOOR
		switch (direction)
		{
		case -1:
			// DOWN
			lastpos = P_FloorHeight(m_Sector);
			if (lastpos - speed < dest)
			{
				P_ChangeFloorHeight(m_Sector, dest - lastpos);
				flag = P_ChangeSector (m_Sector, crush);
				if (flag == true)
				{
					P_ChangeFloorHeight(m_Sector, lastpos - dest);
					P_ChangeSector (m_Sector, crush);
					//return crushed;
				}
				return pastdest;
			}
			else
			{
				P_ChangeFloorHeight(m_Sector, -speed);
				flag = P_ChangeSector (m_Sector, crush);
				if (flag == true)
				{
					P_ChangeFloorHeight(m_Sector, speed);	// should be lastpos
					P_ChangeSector (m_Sector, crush);
					return crushed;
				}
			}
			break;

		case 1:
			// UP
			lastpos = P_FloorHeight(m_Sector);

			if (lastpos + speed > dest)
			{
				P_ChangeFloorHeight(m_Sector, dest - lastpos);
				flag = P_ChangeSector (m_Sector, crush);
				if (flag == true)
				{
					P_ChangeFloorHeight(m_Sector, lastpos - dest);
					P_ChangeSector (m_Sector, crush);
				}
				return pastdest;
			}
			else
			{
				// COULD GET CRUSHED
				P_ChangeFloorHeight(m_Sector, speed);
				flag = P_ChangeSector (m_Sector, crush);
				if (flag == true)
				{
					if (crush)
						return crushed;
					P_ChangeFloorHeight(m_Sector, -speed);
					P_ChangeSector (m_Sector, crush);
					return crushed;
				}
			}
			break;
		}
		break;

	  case 1:
		// CEILING
		switch(direction)
		{
		case -1:
			// DOWN
			lastpos = P_CeilingHeight(m_Sector);

			if (lastpos - speed < dest)
			{
				P_SetCeilingHeight(m_Sector, dest);
				flag = P_ChangeSector (m_Sector, crush);

				if (flag == true)
				{
					P_SetCeilingHeight(m_Sector, lastpos);
					P_ChangeSector (m_Sector, crush);
				}
				return pastdest;
			}
			else
			{
				// COULD GET CRUSHED
				P_SetCeilingHeight(m_Sector, lastpos - speed);
				flag = P_ChangeSector (m_Sector, crush);

				if (flag == true)
				{
					if (crush)
						return crushed;

					P_SetCeilingHeight(m_Sector, lastpos); 
					P_ChangeSector (m_Sector, crush);
					return crushed;
				}
			}
			break;

		case 1:
			// UP
			lastpos = P_CeilingHeight(m_Sector);

			if (lastpos + speed > dest)
			{
				P_SetCeilingHeight(m_Sector, dest);
				flag = P_ChangeSector (m_Sector, crush);
				if (flag == true)
				{
					P_SetCeilingHeight(m_Sector, lastpos);
					P_ChangeSector (m_Sector, crush);
				}
				return pastdest;
			}
			else
			{
				P_SetCeilingHeight(m_Sector, lastpos + speed);
				flag = P_ChangeSector (m_Sector, crush);
// UNUSED
#if 0
				if (flag == true)
				{
					P_ChangeCeilingHeight(m_Sector, -speed);
					P_ChangeSector (m_Sector, crush);
					return crushed;
				}
#endif
			}
			break;
		}
		break;

	}
	return ok;
}