Example #1
0
DPillar::DPillar (sector_t *sector, EPillar type, double speed,
				  double floordist, double ceilingdist, int crush, bool hexencrush)
	: DMover (sector)
{
	double newheight;
	vertex_t *spot;

	sector->floordata = sector->ceilingdata = this;
	m_Interp_Floor = sector->SetInterpolation(sector_t::FloorMove, true);
	m_Interp_Ceiling = sector->SetInterpolation(sector_t::CeilingMove, true);

	m_Type = type;
	m_Crush = crush;
	m_Hexencrush = hexencrush;

	if (type == pillarBuild)
	{
		// If the pillar height is 0, have the floor and ceiling meet halfway
		if (floordist == 0)
		{
			newheight = (sector->CenterFloor () + sector->CenterCeiling ()) / 2;
			m_FloorTarget = sector->floorplane.PointToDist (sector->centerspot, newheight);
			m_CeilingTarget = sector->ceilingplane.PointToDist (sector->centerspot, newheight);
			floordist = newheight - sector->CenterFloor ();
		}
		else
		{
			newheight = sector->CenterFloor () + floordist;
			m_FloorTarget = sector->floorplane.PointToDist (sector->centerspot, newheight);
			m_CeilingTarget = sector->ceilingplane.PointToDist (sector->centerspot, newheight);
		}
		ceilingdist = sector->CenterCeiling () - newheight;
	}
	else
	{
		// If one of the heights is 0, figure it out based on the
		// surrounding sectors
		if (floordist == 0)
		{
			newheight = sector->FindLowestFloorSurrounding (&spot);
			m_FloorTarget = sector->floorplane.PointToDist (spot, newheight);
			floordist = sector->floorplane.ZatPoint (spot) - newheight;
		}
		else
		{
			newheight = sector->CenterFloor() - floordist;
			m_FloorTarget = sector->floorplane.PointToDist (sector->centerspot, newheight);
		}
		if (ceilingdist == 0)
		{
			newheight = sector->FindHighestCeilingSurrounding (&spot);
			m_CeilingTarget = sector->ceilingplane.PointToDist (spot, newheight);
			ceilingdist = newheight - sector->ceilingplane.ZatPoint (spot);
		}
		else
		{
			newheight = sector->CenterCeiling() + ceilingdist;
			m_CeilingTarget = sector->ceilingplane.PointToDist (sector->centerspot, newheight);
		}
	}

	// 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 = speed * ceilingdist / floordist;
	}
	else
	{
		m_CeilingSpeed = speed;
		m_FloorSpeed = speed * floordist / ceilingdist;
	}

	if (!(m_Sector->Flags & SECF_SILENTMOVE))
	{
		if (sector->seqType >= 0)
		{
			SN_StartSequence(sector, CHAN_FLOOR, sector->seqType, SEQ_PLATFORM, 0);
		}
		else if (sector->SeqName != NAME_None)
		{
			SN_StartSequence(sector, CHAN_FLOOR, sector->SeqName, 0);
		}
		else
		{
			SN_StartSequence(sector, CHAN_FLOOR, "Floor", 0);
		}
	}
}
Example #2
0
//==================================================================
//
//      T_VerticalDoor
//
//==================================================================
void T_VerticalDoor(vldoor_t * door)
{
	result_e res;

	switch (door->direction)
	{
		case 0:                // WAITING
			if (!--door->topcountdown)
				switch (door->type)
				{
					case DREV_NORMAL:
						door->direction = -1;   // time to go back down
						SN_StartSequence((mobj_t *) & door->sector->soundorg,
										 SEQ_DOOR_STONE +
										 door->sector->seqType);
						break;
					case DREV_CLOSE30THENOPEN:
						door->direction = 1;
						break;
					default:
						break;
				}
			break;
		case 2:                // INITIAL WAIT
			if (!--door->topcountdown)
			{
				switch (door->type)
				{
					case DREV_RAISEIN5MINS:
						door->direction = 1;
						door->type = DREV_NORMAL;
						break;
					default:
						break;
				}
			}
			break;
		case -1:               // DOWN
			res = T_MovePlane(door->sector, door->speed,
							  door->sector->floorheight, false, 1,
							  door->direction);
			if (res == RES_PASTDEST)
			{
				SN_StopSequence((mobj_t *) & door->sector->soundorg);
				switch (door->type)
				{
					case DREV_NORMAL:
					case DREV_CLOSE:
						door->sector->specialdata = NULL;
						P_TagFinished(door->sector->tag);
						P_RemoveThinker(&door->thinker);        // unlink and free
						break;
					case DREV_CLOSE30THENOPEN:
						door->direction = 0;
						door->topcountdown = 35 * 30;
						break;
					default:
						break;
				}
			}
			else if (res == RES_CRUSHED)
			{
				switch (door->type)
				{
					case DREV_CLOSE:   // DON'T GO BACK UP!
						break;
					default:
						door->direction = 1;
						break;
				}
			}
			break;
		case 1:                // UP
			res = T_MovePlane(door->sector, door->speed,
							  door->topheight, false, 1, door->direction);
			if (res == RES_PASTDEST)
			{
				SN_StopSequence((mobj_t *) & door->sector->soundorg);
				switch (door->type)
				{
					case DREV_NORMAL:
						door->direction = 0;    // wait at top
						door->topcountdown = door->topwait;
						break;
					case DREV_CLOSE30THENOPEN:
					case DREV_OPEN:
						door->sector->specialdata = NULL;
						P_TagFinished(door->sector->tag);
						P_RemoveThinker(&door->thinker);        // unlink and free
						break;
					default:
						break;
				}
			}
			break;
	}
}
void DDoor::DoorSound(bool raise, DSeqNode *curseq) const
{
	int choice;

	// For multiple-selection sound sequences, the following choices are used:
	//  0  Opening
	//  1  Closing
	//  2  Opening fast
	//  3  Closing fast

	choice = !raise;

	if (m_Speed >= FRACUNIT*8)
	{
		choice += 2;
	}

	if (m_Sector->seqType >= 0)
	{
		if (curseq == NULL || !SN_AreModesSame(m_Sector->seqType, SEQ_DOOR, choice, curseq->GetModeNum()))
		{
			SN_StartSequence(m_Sector, CHAN_CEILING, m_Sector->seqType, SEQ_DOOR, choice);
		}
	}
	else if (m_Sector->SeqName != NAME_None)
	{
		if (curseq == NULL || !SN_AreModesSame(m_Sector->SeqName, choice, curseq->GetModeNum()))
		{
			SN_StartSequence(m_Sector, CHAN_CEILING, m_Sector->SeqName, choice);
		}
	}
	else
	{
		const char *snd;

		switch (gameinfo.gametype)
		{
		default:	/* Doom and Hexen */
			snd = "DoorNormal";
			break;
			
		case GAME_Heretic:
			snd = "HereticDoor";
			break;

		case GAME_Strife:
			snd = "DoorSmallMetal";

			// Search the front top textures of 2-sided lines on the door sector
			// for a door sound to use.
			for (int i = 0; i < m_Sector->linecount; ++i)
			{
				const char *texname;
				line_t *line = m_Sector->lines[i];

				if (line->backsector == NULL)
					continue;

				FTexture *tex = TexMan[line->sidedef[0]->GetTexture(side_t::top)];
				texname = tex ? tex->Name.GetChars() : NULL;
				if (texname != NULL && texname[0] == 'D' && texname[1] == 'O' && texname[2] == 'R')
				{
					switch (texname[3])
					{
					case 'S':
						snd = "DoorStone";
						break;

					case 'M':
						if (texname[4] == 'L')
						{
							snd = "DoorLargeMetal";
						}
						break;

					case 'W':
						if (texname[4] == 'L')
						{
							snd = "DoorLargeWood";
						}
						else
						{
							snd = "DoorSmallWood";
						}
						break;
					}
				}
			}
			break;
		}
		if (curseq == NULL || !SN_AreModesSame(snd, choice, curseq->GetModeNum()))
		{
			SN_StartSequence(m_Sector, CHAN_CEILING, snd, choice);
		}
	}
}
Example #4
0
//==================================================================
//
//      EV_VerticalDoor : open a door manually, no tag value
//
//==================================================================
boolean EV_VerticalDoor(line_t * line, mobj_t * thing)
{
	sector_t *sec;
	vldoor_t *door;
	int side;

	side = 0;                   // only front sides can be used

	// if the sector has an active thinker, use it
	sec = sides[line->sidenum[side ^ 1]].sector;
	if (sec->specialdata)
	{
		return false;
/*
				door = sec->specialdata;
				switch(line->special)
				{       // only for raise doors
						case 12:
								if(door->direction == -1)
								{
										door->direction = 1; // go back up
								}
								else
								{
										if(!thing->player)
										{ // Monsters don't close doors
												return;
										}
										door->direction = -1; // start going down immediately
								}
								return;
				}
*/
	}
	//
	// new door thinker
	//
	door = Z_Malloc(sizeof(*door), PU_LEVSPEC, 0);
	P_AddThinker(&door->thinker);
	sec->specialdata = door;
	door->thinker.function = T_VerticalDoor;
	door->sector = sec;
	door->direction = 1;
	switch (line->special)
	{
		case 11:
			door->type = DREV_OPEN;
			line->special = 0;
			break;
		case 12:
		case 13:
			door->type = DREV_NORMAL;
			break;
		default:
			door->type = DREV_NORMAL;
			break;
	}
	door->speed = line->arg2 * (FRACUNIT / 8);
	door->topwait = line->arg3;

	//
	// find the top and bottom of the movement range
	//
	door->topheight = P_FindLowestCeilingSurrounding(sec);
	door->topheight -= 4 * FRACUNIT;
	SN_StartSequence((mobj_t *) & door->sector->soundorg,
					 SEQ_DOOR_STONE + door->sector->seqType);
	return true;
}
Example #5
0
void DPlat::Tick ()
{
	EMoveResult res;
		
	switch (m_Status)
	{
	case up:
		res = m_Sector->MoveFloor (m_Speed, m_High, m_Crush, 1, false);
										
		if (res == EMoveResult::crushed && (m_Crush == -1))
		{
			m_Count = m_Wait;
			m_Status = down;
			PlayPlatSound ("Platform");
		}
		else if (res == EMoveResult::pastdest)
		{
			SN_StopSequence (m_Sector, CHAN_FLOOR);
			if (m_Type != platToggle)
			{
				m_Count = m_Wait;
				m_Status = waiting;

				switch (m_Type)
				{
					case platRaiseAndStayLockout:
						// Instead of keeping the dead thinker like Heretic did let's 
						// better use a flag to avoid problems elsewhere. For example,
						// keeping the thinker would make tagwait wait indefinitely.
						m_Sector->planes[sector_t::floor].Flags |= PLANEF_BLOCKED; 
					case platRaiseAndStay:
					case platDownByValue:
					case platDownWaitUpStay:
					case platDownWaitUpStayStone:
					case platUpByValueStay:
					case platDownToNearestFloor:
					case platDownToLowestCeiling:
						Destroy ();
						break;
					default:
						break;
				}
			}
			else
			{
				m_OldStatus = m_Status;		//jff 3/14/98 after action wait  
				m_Status = in_stasis;		//for reactivation of toggle
			}
		}
		break;
		
	case down:
		res = m_Sector->MoveFloor (m_Speed, m_Low, -1, -1, false);

		if (res == EMoveResult::pastdest)
		{
			SN_StopSequence (m_Sector, CHAN_FLOOR);
			// if not an instant toggle, start waiting
			if (m_Type != platToggle)		//jff 3/14/98 toggle up down
			{								// is silent, instant, no waiting
				m_Count = m_Wait;
				m_Status = waiting;

				switch (m_Type)
				{
					case platUpWaitDownStay:
					case platUpNearestWaitDownStay:
					case platUpByValue:
						Destroy ();
						break;
					default:
						break;
				}
			}
			else
			{	// instant toggles go into stasis awaiting next activation
				m_OldStatus = m_Status;		//jff 3/14/98 after action wait  
				m_Status = in_stasis;		//for reactivation of toggle
			}
		}
		else if (res == EMoveResult::crushed && m_Crush < 0 && m_Type != platToggle)
		{
			m_Status = up;
			m_Count = m_Wait;
			PlayPlatSound ("Platform");
		}

		//jff 1/26/98 remove the plat if it bounced so it can be tried again
		//only affects plats that raise and bounce

		// remove the plat if it's a pure raise type
		switch (m_Type)
		{
			case platUpByValueStay:
			case platRaiseAndStay:
			case platRaiseAndStayLockout:
				Destroy ();
			default:
				break;
		}

		break;
		
	case waiting:
		if (m_Count > 0 && !--m_Count)
		{
			if (m_Sector->floorplane.fD() == m_Low)
				m_Status = up;
			else
				m_Status = down;

			if (m_Type == platToggle)
				SN_StartSequence (m_Sector, CHAN_FLOOR, "Silence", 0);
			else
				PlayPlatSound ("Platform");
		}
		break;

	case in_stasis:
		break;
	}
}
Example #6
0
bool FLevelLocals::EV_DoPlat (int tag, line_t *line, DPlat::EPlatType type, double height, double speed, int delay, int lip, int change)
{
	DPlat *plat;
	int secnum;
	sector_t *sec;
	bool rtn = false;
	bool manual = false;
	double newheight = 0;
	vertex_t *spot;

	if (tag != 0)
	{
		//	Activate all <type> plats that are in_stasis
		switch (type)
		{
		case DPlat::platToggle:
			rtn = true;
		case DPlat::platPerpetualRaise:
			ActivateInStasisPlat (tag);
			break;

		default:
			break;
		}
	}


	// [RH] If tag is zero, use the sector on the back side
	//		of the activating line (if any).
	auto itr = GetSectorTagIterator(tag, line);
	while ((secnum = itr.Next()) >= 0)
	{
		sec = &sectors[secnum];

		if (sec->PlaneMoving(sector_t::floor))
		{
			continue;
		}

		// Find lowest & highest floors around sector
		rtn = true;
		plat = CreateThinker<DPlat> (sec);

		plat->m_Type = type;
		plat->m_Crush = -1;
		plat->m_Tag = tag;
		plat->m_Speed = speed;
		plat->m_Wait = delay;

		//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
		plat->m_Low = sec->floorplane.fD();

		if (change)
		{
			if (line)
				sec->SetTexture(sector_t::floor, line->sidedef[0]->sector->GetTexture(sector_t::floor));
			if (change == 1) sec->ClearSpecial();
		}

		switch (type)
		{
		case DPlat::platRaiseAndStay:
		case DPlat::platRaiseAndStayLockout:
			newheight = FindNextHighestFloor (sec, &spot);
			plat->m_High = sec->floorplane.PointToDist (spot, newheight);
			plat->m_Low = sec->floorplane.fD();
			plat->m_Status = DPlat::up;
			plat->PlayPlatSound ("Floor");
			sec->ClearSpecial();
			break;

		case DPlat::platUpByValue:
		case DPlat::platUpByValueStay:
			newheight = sec->floorplane.ZatPoint (sec->centerspot) + height;
			plat->m_High = sec->floorplane.PointToDist (sec->centerspot, newheight);
			plat->m_Low = sec->floorplane.fD();
			plat->m_Status = DPlat::up;
			plat->PlayPlatSound ("Floor");
			break;
		
		case DPlat::platDownByValue:
			newheight = sec->floorplane.ZatPoint (sec->centerspot) - height;
			plat->m_Low = sec->floorplane.PointToDist (sec->centerspot, newheight);
			plat->m_High = sec->floorplane.fD();
			plat->m_Status = DPlat::down;
			plat->PlayPlatSound ("Floor");
			break;

		case DPlat::platDownWaitUpStay:
		case DPlat::platDownWaitUpStayStone:
			newheight = FindLowestFloorSurrounding (sec, &spot) + lip;
			plat->m_Low = sec->floorplane.PointToDist (spot, newheight);

			if (plat->m_Low < sec->floorplane.fD())
				plat->m_Low = sec->floorplane.fD();

			plat->m_High = sec->floorplane.fD();
			plat->m_Status = DPlat::down;
			plat->PlayPlatSound (type == DPlat::platDownWaitUpStay ? "Platform" : "Floor");
			break;
		
		case DPlat::platUpNearestWaitDownStay:
			newheight = FindNextHighestFloor (sec, &spot);
			// Intentional fall-through

		case DPlat::platUpWaitDownStay:
			if (type == DPlat::platUpWaitDownStay)
			{
				newheight = FindHighestFloorSurrounding (sec, &spot);
			}
			plat->m_High = sec->floorplane.PointToDist (spot, newheight);
			plat->m_Low = sec->floorplane.fD();

			if (plat->m_High > sec->floorplane.fD())
				plat->m_High = sec->floorplane.fD();

			plat->m_Status = DPlat::up;
			plat->PlayPlatSound ("Platform");
			break;

		case DPlat::platPerpetualRaise:
			newheight = FindLowestFloorSurrounding (sec, &spot) + lip;
			plat->m_Low =  sec->floorplane.PointToDist (spot, newheight);

			if (plat->m_Low < sec->floorplane.fD())
				plat->m_Low = sec->floorplane.fD();

			newheight = FindHighestFloorSurrounding (sec, &spot);
			plat->m_High =  sec->floorplane.PointToDist (spot, newheight);

			if (plat->m_High > sec->floorplane.fD())
				plat->m_High = sec->floorplane.fD();

			plat->m_Status = pr_doplat() & 1 ? DPlat::up : DPlat::down;

			plat->PlayPlatSound ("Platform");
			break;

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

			// set up toggling between ceiling, floor inclusive
			newheight = FindLowestCeilingPoint(sec, &spot);
			plat->m_Low = sec->floorplane.PointToDist (spot, newheight);
			plat->m_High = sec->floorplane.fD();
			plat->m_Status = DPlat::down;
			SN_StartSequence (sec, CHAN_FLOOR, "Silence", 0);
			break;

		case DPlat::platDownToNearestFloor:
			newheight = FindNextLowestFloor (sec, &spot) + lip;
			plat->m_Low = sec->floorplane.PointToDist (spot, newheight);
			plat->m_Status = DPlat::down;
			plat->m_High = sec->floorplane.fD();
			plat->PlayPlatSound ("Platform");
			break;

		case DPlat::platDownToLowestCeiling:
			newheight = FindLowestCeilingSurrounding (sec, &spot);
		    plat->m_Low = sec->floorplane.PointToDist (spot, newheight);
			plat->m_High = sec->floorplane.fD();

			if (plat->m_Low < sec->floorplane.fD())
				plat->m_Low = sec->floorplane.fD();

			plat->m_Status = DPlat::down;
			plat->PlayPlatSound ("Platform");
			break;

		default:
			break;
		}
	}
	return rtn;
}
Example #7
0
//==================================================================
//
//              EV_DoCeiling
//              Move a ceiling up/down and all around!
//
//==================================================================
int EV_DoCeiling(line_t *line, byte *arg, ceiling_e type)
{
	int     secnum, rtn;
	sector_t *sec;
	ceiling_t *ceiling;

	secnum = -1;
	rtn = 0;

	/* Old Ceiling stasis code
	   //
	   //      Reactivate in-stasis ceilings...for certain types.
	   //
	   switch(type)
	   {
	   case CLEV_CRUSHANDRAISE:
	   P_ActivateInStasisCeiling(line);
	   default:
	   break;
	   }
	 */
	while((secnum = P_FindSectorFromTag(arg[0], secnum)) >= 0)
	{
		sec = &sectors[secnum];
		if(sec->specialdata)
			continue;

		//
		// new door thinker
		//
		rtn = 1;
		ceiling = Z_Malloc(sizeof(*ceiling), PU_LEVSPEC, 0);
		P_AddThinker(&ceiling->thinker);
		sec->specialdata = ceiling;
		ceiling->thinker.function = T_MoveCeiling;
		ceiling->sector = sec;
		ceiling->crush = 0;
		ceiling->speed = arg[1] * (FRACUNIT / 8);
		switch (type)
		{
		case CLEV_CRUSHRAISEANDSTAY:
			ceiling->crush = arg[2];	// arg[2] = crushing value
			ceiling->topheight = sec->ceilingheight;
			ceiling->bottomheight = sec->floorheight + (8 * FRACUNIT);
			ceiling->direction = -1;
			break;
		case CLEV_CRUSHANDRAISE:
			ceiling->topheight = sec->ceilingheight;
		case CLEV_LOWERANDCRUSH:
			ceiling->crush = arg[2];	// arg[2] = crushing value
		case CLEV_LOWERTOFLOOR:
			ceiling->bottomheight = sec->floorheight;
			if(type != CLEV_LOWERTOFLOOR)
			{
				ceiling->bottomheight += 8 * FRACUNIT;
			}
			ceiling->direction = -1;
			break;
		case CLEV_RAISETOHIGHEST:
			ceiling->topheight = P_FindHighestCeilingSurrounding(sec);
			ceiling->direction = 1;
			break;
		case CLEV_LOWERBYVALUE:
			ceiling->bottomheight = sec->ceilingheight - arg[2] * FRACUNIT;
			ceiling->direction = -1;
			break;
		case CLEV_RAISEBYVALUE:
			ceiling->topheight = sec->ceilingheight + arg[2] * FRACUNIT;
			ceiling->direction = 1;
			break;
		case CLEV_MOVETOVALUETIMES8:
			{
				int     destHeight = arg[2] * FRACUNIT * 8;

				if(arg[3])
				{
					destHeight = -destHeight;
				}
				if(sec->ceilingheight <= destHeight)
				{
					ceiling->direction = 1;
					ceiling->topheight = destHeight;
					if(sec->ceilingheight == destHeight)
					{
						rtn = 0;
					}
				}
				else if(sec->ceilingheight > destHeight)
				{
					ceiling->direction = -1;
					ceiling->bottomheight = destHeight;
				}
				break;
			}
		default:
			rtn = 0;
			break;
		}
		ceiling->tag = sec->tag;
		ceiling->type = type;
		P_AddActiveCeiling(ceiling);
		if(rtn)
		{
			SN_StartSequence((mobj_t *) &ceiling->sector->soundorg,
							 SEQ_PLATFORM + ceiling->sector->seqType);
		}
	}
	return rtn;
}
Example #8
0
void ASoundSequence::Activate (AActor *activator)
{
	SN_StartSequence (this, args[0], SEQ_ENVIRONMENT, args[1]);
}