Example #1
0
BOOL EV_DoPillar (DPillar::EPillar type, int tag, fixed_t speed, fixed_t height,
				  fixed_t height2, bool crush)
{
	BOOL rtn = false;
	int secnum = -1;

	while ((secnum = P_FindSectorFromTag (tag, secnum)) >= 0)
	{
		sector_t *sec = &sectors[secnum];
		fixed_t floorheight = P_FloorHeight(sec);
		fixed_t ceilingheight = P_CeilingHeight(sec);

		if (sec->floordata || sec->ceilingdata)
			continue;

		if (type == DPillar::pillarBuild && floorheight == ceilingheight)
			continue;

		if (type == DPillar::pillarOpen && floorheight != ceilingheight)
			continue;

		rtn = true;
		new DPillar (sec, type, speed, height, height2, crush);
		P_AddMovingCeiling(sec);
	}
	return rtn;
}
Example #2
0
//
// R_InterpolationTicker
//
// Records the current height of all moving planes and position of scrolling
// textures, which will be used as the previous position during iterpolation.
// This should be called once per gametic.
//
void R_InterpolationTicker()
{
	prev_ceilingheight.clear();
	prev_floorheight.clear();

	if (gamestate == GS_LEVEL)
	{
		for (int i = 0; i < numsectors; i++)
		{
			if (sectors[i].ceilingdata)
				prev_ceilingheight.push_back(std::make_pair(P_CeilingHeight(&sectors[i]), i));
			if (sectors[i].floordata)
				prev_floorheight.push_back(std::make_pair(P_FloorHeight(&sectors[i]), i));
		}
	}
}
Example #3
0
//
// R_BeginInterpolation
//
// Saves the current height of all moving planes and position of scrolling
// textures, which will be restored by R_EndInterpolation. The height of a
// moving plane will be interpolated between the previous height and this
// current height. This should be called every time a frame is rendered.
//
void R_BeginInterpolation(fixed_t amount)
{
	saved_ceilingheight.clear();
	saved_floorheight.clear();

	if (gamestate == GS_LEVEL)
	{
		for (std::vector<fixed_uint_pair>::const_iterator ceiling_it = prev_ceilingheight.begin();
			 ceiling_it != prev_ceilingheight.end(); ++ceiling_it)
		{
			unsigned int secnum = ceiling_it->second;
			sector_t* sector = &sectors[secnum];

			fixed_t old_value = ceiling_it->first;
			fixed_t cur_value = P_CeilingHeight(sector);

			saved_ceilingheight.push_back(std::make_pair(cur_value, secnum));
			
			fixed_t new_value = old_value + FixedMul(cur_value - old_value, amount);
			P_SetCeilingHeight(sector, new_value);
		}

		for (std::vector<fixed_uint_pair>::const_iterator floor_it = prev_floorheight.begin();
			 floor_it != prev_floorheight.end(); ++floor_it)
		{
			unsigned int secnum = floor_it->second;
			sector_t* sector = &sectors[secnum];

			fixed_t old_value = floor_it->first;
			fixed_t cur_value = P_FloorHeight(sector);

			saved_floorheight.push_back(std::make_pair(cur_value, secnum));
			
			fixed_t new_value = old_value + FixedMul(cur_value - old_value, amount);
			P_SetFloorHeight(sector, new_value);
		}
	}
}
Example #4
0
// [RH] SpawnDoor: Helper function for EV_DoDoor
DDoor::DDoor (sector_t *sec, line_t *ln, EVlDoor type, fixed_t speed, int delay)
	: DMovingCeiling (sec), m_Status(init)
{
	m_Type = type;
	m_TopWait = delay;
	m_TopCountdown = -1;
	m_Speed = speed;
    m_Line = ln;

	fixed_t ceilingheight = P_CeilingHeight(sec);
	
	switch (type)
	{
	case doorClose:
		m_TopHeight = P_FindLowestCeilingSurrounding(sec) - 4*FRACUNIT;
		m_Status = closing;
		PlayDoorSound();
		break;

	case doorOpen:
	case doorRaise:
		m_Status = opening;
		m_TopHeight = P_FindLowestCeilingSurrounding(sec) - 4*FRACUNIT;
		if (m_TopHeight != ceilingheight)
			PlayDoorSound();

		break;

	case doorCloseWaitOpen:
		m_TopHeight = ceilingheight;
		m_Status = closing;
		PlayDoorSound();
		break;

	case doorRaiseIn5Mins: // denis - fixme - does this need code?
		break;
	}
}
Example #5
0
//
// R_Subsector
// Determine floor/ceiling planes.
// Add sprites of things in sector.
// Draw one or more line segments.
//
void R_Subsector (int num)
{
	int 		 count;
	seg_t*		 line;
	subsector_t *sub;
	sector_t     tempsec;				// killough 3/7/98: deep water hack
	int          floorlightlevel;		// killough 3/16/98: set floor lightlevel
	int          ceilinglightlevel;		// killough 4/11/98

#ifdef RANGECHECK
    if (num>=numsubsectors)
		I_Error ("R_Subsector: ss %i with numss = %i",
				 num,
				 numsubsectors);
#endif

	sub = &subsectors[num];
	frontsector = sub->sector;
	count = sub->numlines;
	line = &segs[sub->firstline];

	// killough 3/8/98, 4/4/98: Deep water / fake ceiling effect
	frontsector = R_FakeFlat(frontsector, &tempsec, &floorlightlevel,
						   &ceilinglightlevel, false);	// killough 4/11/98

	basecolormap = frontsector->colormap->maps;

	ceilingplane = P_CeilingHeight(camera) > viewz ||
		frontsector->ceilingpic == skyflatnum ||
		(frontsector->heightsec && 
		!(frontsector->heightsec->MoreFlags & SECF_IGNOREHEIGHTSEC) && 
		frontsector->heightsec->floorpic == skyflatnum) ?
		R_FindPlane(frontsector->ceilingplane,		// killough 3/8/98
					frontsector->ceilingpic == skyflatnum &&  // killough 10/98
						frontsector->sky & PL_SKYFLAT ? frontsector->sky :
						frontsector->ceilingpic,
					ceilinglightlevel,				// killough 4/11/98
					frontsector->ceiling_xoffs,		// killough 3/7/98
					frontsector->ceiling_yoffs + frontsector->base_ceiling_yoffs,
					frontsector->ceiling_xscale,
					frontsector->ceiling_yscale,
					frontsector->ceiling_angle + frontsector->base_ceiling_angle
					) : NULL;

	// killough 3/7/98: Add (x,y) offsets to flats, add deep water check
	// killough 3/16/98: add floorlightlevel
	// killough 10/98: add support for skies transferred from sidedefs
	floorplane = P_FloorHeight(camera) < viewz || // killough 3/7/98
		(frontsector->heightsec &&
		!(frontsector->heightsec->MoreFlags & SECF_IGNOREHEIGHTSEC) &&
		frontsector->heightsec->ceilingpic == skyflatnum) ?
		R_FindPlane(frontsector->floorplane,
					frontsector->floorpic == skyflatnum &&  // killough 10/98
						frontsector->sky & PL_SKYFLAT ? frontsector->sky :
						frontsector->floorpic,
					floorlightlevel,				// killough 3/16/98
					frontsector->floor_xoffs,		// killough 3/7/98
					frontsector->floor_yoffs + frontsector->base_floor_yoffs,
					frontsector->floor_xscale,
					frontsector->floor_yscale,
					frontsector->floor_angle + frontsector->base_floor_angle
					) : NULL;

	// [RH] set foggy flag
	foggy = level.fadeto_color[0] || level.fadeto_color[1] || level.fadeto_color[2] || level.fadeto_color[3]
				|| frontsector->colormap->fade;

	// killough 9/18/98: Fix underwater slowdown, by passing real sector
	// instead of fake one. Improve sprite lighting by basing sprite
	// lightlevels on floor & ceiling lightlevels in the surrounding area.
	R_AddSprites (sub->sector, (floorlightlevel + ceilinglightlevel) / 2, FakeSide);

	// [RH] Add particles
	if (r_particles)
	{
		for (WORD i = ParticlesInSubsec[num]; i != NO_PARTICLE; i = Particles[i].nextinsubsector)
			R_ProjectParticle(Particles + i, subsectors[num].sector, FakeSide);
	}		

	if (sub->poly)
	{ // Render the polyobj in the subsector first
		int polyCount = sub->poly->numsegs;
		seg_t **polySeg = sub->poly->segs;
		while (polyCount--)
			R_AddLine (*polySeg++);
	}
	
	while (count--)
		R_AddLine (line++);
}
Example #6
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;
}
Example #7
0
DPlat::DPlat(sector_t *sec, DPlat::EPlatType type, fixed_t height,
			 int speed, int delay, fixed_t lip)
	: DMovingFloor(sec), m_Status(init)
{
	m_Type = type;
	m_Crush = false;
	m_Speed = speed;
	m_Wait = delay;
	m_Height = height;
	m_Lip = lip;

	//jff 1/26/98 Avoid raise plat bouncing a head off a ceiling and then
	//going down forever -- default lower to plat height when triggered
	m_Low = P_FloorHeight(sec);

	switch (type)
	{
	case DPlat::platRaiseAndStay:
		m_High = P_FindNextHighestFloor(sec);
		m_Status = DPlat::midup;
		PlayPlatSound();
		break;

	case DPlat::platUpByValue:
	case DPlat::platUpByValueStay:
		m_High = P_FloorHeight(sec) + height;
		m_Status = DPlat::midup;
		PlayPlatSound();
		break;
	
	case DPlat::platDownByValue:
		m_Low = P_FloorHeight(sec) - height;
		m_Status = DPlat::middown;
		PlayPlatSound();
		break;

	case DPlat::platDownWaitUpStay:
		m_Low = P_FindLowestFloorSurrounding(sec) + lip;

		if (m_Low > P_FloorHeight(sec))
			m_Low = P_FloorHeight(sec);

		m_High = P_FloorHeight(sec);
		m_Status = DPlat::down;
		PlayPlatSound();
		break;
	
	case DPlat::platUpWaitDownStay:
		m_High = P_FindHighestFloorSurrounding(sec);

		if (m_High < P_FloorHeight(sec))
			m_High = P_FloorHeight(sec);

		m_Status = DPlat::up;
		PlayPlatSound();
		break;

	case DPlat::platPerpetualRaise:
		m_Low = P_FindLowestFloorSurrounding(sec) + lip;

		if (m_Low > P_FloorHeight(sec))
			m_Low = P_FloorHeight(sec);

		m_High = P_FindHighestFloorSurrounding (sec);

		if (m_High < P_FloorHeight(sec))
			m_High = P_FloorHeight(sec);

		m_Status = P_Random () & 1 ? DPlat::down : DPlat::up;

		PlayPlatSound();
		break;

	case DPlat::platToggle:	//jff 3/14/98 add new type to support instant toggle
		m_Crush = false;	//jff 3/14/98 crush anything in the way

		// set up toggling between ceiling, floor inclusive
		m_Low = P_CeilingHeight(sec);
		m_High = P_FloorHeight(sec);
		m_Status = DPlat::down;
// 			SN_StartSequence (sec, "Silence");
		break;

	case DPlat::platDownToNearestFloor:
		m_Low = P_FindNextLowestFloor(sec) + lip;
		m_Status = DPlat::down;
		m_High = P_FloorHeight(sec);
		PlayPlatSound();
		break;

	case DPlat::platDownToLowestCeiling:
	    m_Low = P_FindLowestCeilingSurrounding (sec);
		m_High = P_FloorHeight(sec);

		if (m_Low > P_FloorHeight(sec))
			m_Low = P_FloorHeight(sec);

		m_Status = DPlat::down;
		PlayPlatSound();
		break;

	default:
		break;
	}	
}
//
// 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;
}
Example #9
0
//
// R_AddLine
// Clips the given segment
// and adds any visible pieces to the line list.
//
void R_AddLine (seg_t *line)
{
	int 			x1;
	int 			x2;
	angle_t 		angle1;
	angle_t 		angle2;
	angle_t 		span;
	angle_t 		tspan;
	static sector_t tempsec;	// killough 3/8/98: ceiling/water hack

	curline = line;

	// [RH] Color if not texturing line
	dc_color = ((line - segs) & 31) * 4;

	// OPTIMIZE: quickly reject orthogonal back sides.
	angle1 = R_PointToAngle (line->v1->x, line->v1->y);
	angle2 = R_PointToAngle (line->v2->x, line->v2->y);

	// Clip to view edges.
	// OPTIMIZE: make constant out of 2*clipangle (FIELDOFVIEW).
	span = angle1 - angle2;

	// Back side? I.e. backface culling?
	if (span >= ANG180)
		return;

	// Global angle needed by segcalc.
	rw_angle1 = angle1;
	angle1 -= viewangle;
	angle2 -= viewangle;

	tspan = angle1 + clipangle;
	if (tspan > 2*clipangle)
	{
		// Totally off the left edge?
		if (tspan - 2*clipangle >= span)
			return;

		angle1 = clipangle;
	}
	tspan = clipangle - angle2;
	if (tspan > 2*clipangle)
	{
		// Totally off the left edge?
		if (tspan - 2*clipangle >= span)
			return;
		angle2 = (unsigned) (-(int)clipangle);
	}

	// The seg is in the view range, but not necessarily visible.
	angle1 = (angle1+ANG90)>>ANGLETOFINESHIFT;
	angle2 = (angle2+ANG90)>>ANGLETOFINESHIFT;

	// killough 1/31/98: Here is where "slime trails" can SOMETIMES occur:
	x1 = viewangletox[angle1];
	x2 = viewangletox[angle2];

	// Does not cross a pixel?
	if (x1 >= x2)	// killough 1/31/98 -- change == to >= for robustness
		return;

	rw_start = x1;
	rw_stop = x2 - 1;
	
	rw_frontcz1 = P_CeilingHeight(line->v1->x, line->v1->y, frontsector);
	rw_frontfz1 = P_FloorHeight(line->v1->x, line->v1->y, frontsector);
	rw_frontcz2 = P_CeilingHeight(line->v2->x, line->v2->y, frontsector);
	rw_frontfz2 = P_FloorHeight(line->v2->x, line->v2->y, frontsector);	
	
	backsector = line->backsector;
	// Single sided line?
	if (!backsector)
		goto clipsolid;

	// killough 3/8/98, 4/4/98: hack for invisible ceilings / deep water
	backsector = R_FakeFlat (backsector, &tempsec, NULL, NULL, true);
		
	rw_backcz1 = P_CeilingHeight(line->v1->x, line->v1->y, backsector);
	rw_backfz1 = P_FloorHeight(line->v1->x, line->v1->y, backsector);
	rw_backcz2 = P_CeilingHeight(line->v2->x, line->v2->y, backsector);
	rw_backfz2 = P_FloorHeight(line->v2->x, line->v2->y, backsector);

	// [SL] Check for closed doors or other scenarios that would make this
	// line seg solid.
	//
	// This fixes the automap floor height bug -- killough 1/18/98:
	// killough 4/7/98: optimize: save result in doorclosed for use in r_segs.c
	if (!(line->linedef->flags & ML_TWOSIDED) ||
		 (rw_backcz1 <= rw_frontfz1 && rw_backcz2 <= rw_frontfz2) ||
		 (rw_backfz1 >= rw_frontcz1 && rw_backfz2 >= rw_frontcz2) ||

		// handle a case where the backsector slopes one direction
		// and the frontsector slopes the opposite:
		(rw_backcz1 <= rw_frontfz1 && rw_backfz1 >= rw_frontcz1) ||
		(rw_backcz2 <= rw_frontfz2 && rw_backfz2 >= rw_frontcz2) ||

		// if door is closed because back is shut:
		((rw_backcz1 <= rw_backfz1 && rw_backcz2 <= rw_backfz2) &&
		
		// preserve a kind of transparent door/lift special effect:
		((rw_backcz1 >= rw_frontcz1 && rw_backcz2 >= rw_frontcz2) ||
		 line->sidedef->toptexture) &&
		
		((rw_backfz1 <= rw_frontfz1 && rw_backfz2 <= rw_frontfz2) ||
		 line->sidedef->bottomtexture) &&

		// properly render skies (consider door "open" if both ceilings are sky):
		 (backsector->ceilingpic !=skyflatnum || 
		  frontsector->ceilingpic!=skyflatnum)))
	{
		doorclosed = true;
		goto clipsolid;
	}
	else
	{
		doorclosed = false;
	}

	// Window.
	if (!P_IdenticalPlanes(&frontsector->ceilingplane, &backsector->ceilingplane) ||
		!P_IdenticalPlanes(&frontsector->floorplane, &backsector->floorplane))
		goto clippass;

	// Reject empty lines used for triggers
	//	and special events.
	// Identical floor and ceiling on both sides,
	// identical light levels on both sides,
	// and no middle texture.
	if (backsector->lightlevel == frontsector->lightlevel
		&& backsector->floorpic == frontsector->floorpic
		&& backsector->ceilingpic == frontsector->ceilingpic
		&& curline->sidedef->midtexture == 0

		// killough 3/7/98: Take flats offsets into account:
		&& backsector->floor_xoffs == frontsector->floor_xoffs
		&& (backsector->floor_yoffs + backsector->base_floor_yoffs) == (frontsector->floor_yoffs + backsector->base_floor_yoffs)
		&& backsector->ceiling_xoffs == frontsector->ceiling_xoffs
		&& (backsector->ceiling_yoffs + backsector->base_ceiling_yoffs) == (frontsector->ceiling_yoffs + frontsector->base_ceiling_yoffs)

		// killough 4/16/98: consider altered lighting
		&& backsector->floorlightsec == frontsector->floorlightsec
		&& backsector->ceilinglightsec == frontsector->ceilinglightsec

		// [RH] Also consider colormaps
		&& backsector->floorcolormap == frontsector->floorcolormap
		&& backsector->ceilingcolormap == frontsector->ceilingcolormap

		// [RH] and scaling
		&& backsector->floor_xscale == frontsector->floor_xscale
		&& backsector->floor_yscale == frontsector->floor_yscale
		&& backsector->ceiling_xscale == frontsector->ceiling_xscale
		&& backsector->ceiling_yscale == frontsector->ceiling_yscale

		// [RH] and rotation
		&& (backsector->floor_angle + backsector->base_floor_angle) == (frontsector->floor_angle + frontsector->base_floor_angle)
		&& (backsector->ceiling_angle + backsector->base_ceiling_angle) == (frontsector->ceiling_angle + frontsector->base_ceiling_angle)
		)
	{
		return;
	}

  clippass:
	R_ClipPassWallSegment (x1, x2-1);
	return;

  clipsolid:
	R_ClipSolidWallSegment (x1, x2-1);
}
Example #10
0
//
// T_VerticalDoor
//
void DDoor::RunThink ()
{
	fixed_t ceilingheight = P_CeilingHeight(m_Sector);
	fixed_t floorheight = P_FloorHeight(m_Sector);
	
	EResult res;
		
	switch (m_Status)
	{
	case finished:
		PlayDoorSound();
		// fall through
	case destroy:
		P_SetDoorDestroy(this);
		return;
		
	case waiting:
		// WAITING
		if (!--m_TopCountdown)
		{
			switch (m_Type)
			{
			case doorRaise:
				// time to go back down
				m_Status = closing;
				PlayDoorSound();
				break;
				
			case doorCloseWaitOpen:
				m_Status = opening;
				PlayDoorSound();
				break;
				
			default:
				break;
			}
		}
		break;
		
	case init:
		//	INITIAL WAIT
		if (!--m_TopCountdown)
		{
			switch (m_Type)
			{
			case doorRaiseIn5Mins:
				m_Type = doorRaise;
				m_Status = opening;
				PlayDoorSound();
				break;

			default:
				break;
			}
		}
		break;
		
	case closing:
		res = MoveCeiling(m_Speed, floorheight, false, -1);
		
        if (m_Line && m_Line->id)
        {
            EV_LightTurnOnPartway(m_Line->id,
                FixedDiv(ceilingheight - floorheight, m_TopHeight - floorheight));
        }
		if (res == pastdest)
		{
			//S_StopSound (m_Sector->soundorg);
			SN_StopSequence (m_Sector);
			switch (m_Type)
			{
			case doorRaise:
			case doorClose:
				m_Status = finished;
				return;
				
			case doorCloseWaitOpen:
				m_TopCountdown = m_TopWait;
				m_Status = waiting;
				break;
				
			default:
				break;
			}
            if (m_Line && m_Line->id)
            {
                EV_LightTurnOnPartway(m_Line->id, 0);
            }
		}
		else if (res == crushed)
		{
			switch (m_Type)
			{
			case doorClose:				// DO NOT GO BACK UP!
				break;
				
			default:
				m_Status = reopening;
				PlayDoorSound();
				break;
			}
		}
		break;
		
	case reopening:
	case opening:
		res = MoveCeiling(m_Speed, m_TopHeight, false, 1);
		
        if (m_Line && m_Line->id)
        {
            EV_LightTurnOnPartway(m_Line->id,
                FixedDiv(ceilingheight - floorheight, m_TopHeight - floorheight));
        }
		if (res == pastdest)
		{
			//S_StopSound (m_Sector->soundorg);
			SN_StopSequence (m_Sector);
			switch (m_Type)
			{
			case doorRaise:
				// wait at top
				m_TopCountdown = m_TopWait;
				m_Status = waiting;
				break;
				
			case doorCloseWaitOpen:
			case doorOpen:
				m_Status = finished;
				return;
				
			default:
				break;
			}
            if (m_Line && m_Line->id)
            {
                EV_LightTurnOnPartway(m_Line->id, FRACUNIT);
            }
		}
		break;
	default:
		break;
	}
}
Example #11
0
DPillar::DPillar (sector_t *sector, EPillar type, fixed_t speed,
				  fixed_t height, fixed_t height2, bool crush)
	: DMover (sector), m_Status(init)
{
	fixed_t	ceilingdist, floordist;

	sector->floordata = sector->ceilingdata = this;

	fixed_t floorheight = P_FloorHeight(sector);
	fixed_t ceilingheight = P_CeilingHeight(sector);

	m_Type = type;
	m_Crush = crush;

	if (type == pillarBuild)
	{
		// If the pillar height is 0, have the floor and ceiling meet halfway
		if (height == 0)
		{
			m_FloorTarget = m_CeilingTarget =
				 (ceilingheight - floorheight) / 2 + floorheight;
			floordist = m_FloorTarget - floorheight;
		}
		else
		{
			m_FloorTarget = m_CeilingTarget = floorheight + height;
			floordist = height;
		}
		ceilingdist = ceilingheight - m_CeilingTarget;
	}
	else
	{
		// If one of the heights is 0, figure it out based on the
		// surrounding sectors
		if (height == 0)
		{
			m_FloorTarget = P_FindLowestFloorSurrounding (sector);
			floordist = floorheight - m_FloorTarget;
		}
		else
		{
			floordist = height;
			m_FloorTarget = floorheight - height;
		}
		if (height2 == 0)
		{
			m_CeilingTarget = P_FindHighestCeilingSurrounding (sector);
			ceilingdist = m_CeilingTarget - ceilingheight;
		}
		else
		{
			m_CeilingTarget = ceilingheight + height2;
			ceilingdist = height2;
		}
	}

	// The speed parameter applies to whichever part of the pillar
	// travels the farthest. The other part's speed is then set so
	// that it arrives at its destination at the same time.
	if (floordist > ceilingdist)
	{
		m_FloorSpeed = speed;
		m_CeilingSpeed = FixedDiv (FixedMul (speed, ceilingdist), floordist);
	}
	else
	{
		m_CeilingSpeed = speed;
		m_FloorSpeed = FixedDiv (FixedMul (speed, floordist), ceilingdist);
	}

	PlayPillarSound();
}