//-----------------------------------------------------------------------------
// Purpose: Starts the door going to its "down" position (simply ToggleData->vecPosition1).
//-----------------------------------------------------------------------------
void CBaseDoor::DoorGoDown( void )
{
	if ( !HasSpawnFlags( SF_DOOR_SILENT ) )
	{
		// If we're not moving already, start the moving noise
		if ( m_toggle_state != TS_GOING_UP && m_toggle_state != TS_GOING_DOWN )
		{
			StartMovingSound();
		}
	}
	
#ifdef DOOR_ASSERT
	ASSERT(m_toggle_state == TS_AT_TOP);
#endif // DOOR_ASSERT
	m_toggle_state = TS_GOING_DOWN;

	SetMoveDone( &CBaseDoor::DoorHitBottom );
	if ( IsRotatingDoor() )//rotating door
		AngularMove( m_vecAngle1, m_flSpeed);
	else
		LinearMove( m_vecPosition1, m_flSpeed);

	//Fire our closed output
	m_OnClose.FireOutput( this, this );
}
Beispiel #2
0
void CBaseDoor::DoorGoUp( void )
{
	entvars_t	*pevActivator;

	// It could be going-down, if blocked.
	ASSERT( m_iState == STATE_OFF || m_iState == STATE_TURN_OFF );

	// emit door moving and stop sounds on CHAN_STATIC so that the multicast doesn't
	// filter them out and leave a client stuck with looping door sounds!
	if( !FBitSet( pev->spawnflags, SF_DOOR_SILENT ))
		EMIT_SOUND( edict(), CHAN_STATIC, STRING( pev->noise1 ), 1, ATTN_NORM );

	m_iState = STATE_TURN_ON;
	SetMoveDone( DoorHitTop );

	if( IsRotatingDoor( ))
	{
		float sign = 1.0;

		// !!! BUGBUG Triggered doors don't work with this yet
		if( m_hActivator != NULL && m_bDoorTouched )
		{
			pevActivator = m_hActivator->pev;

			// Y axis rotation, move away from the player			
			if( !FBitSet( pev->spawnflags, SF_DOOR_ONEWAY ) && pev->movedir.y )
			{
				// Positive is CCW, negative is CW, so make 'sign' 1 or -1 based on which way we want to open.
				// Important note:  All doors face East at all times, and twist their local angle to open.
				// So you can't look at the door's facing to determine which way to open.

				Vector nearestPoint;

				CalcNearestPoint( m_hActivator->GetAbsOrigin(), &nearestPoint );
				Vector activatorToNearestPoint = nearestPoint - m_hActivator->GetAbsOrigin();
				activatorToNearestPoint.z = 0;

				Vector activatorToOrigin = GetAbsOrigin() - m_hActivator->GetAbsOrigin();
				activatorToOrigin.z = 0;

				// Point right hand at door hinge, curl hand towards closest spot on door, if thumb
				// is up, open door CW. -- Department of Basic Cross Product Understanding for Noobs
				// g-cont. MWA-HA-HA!
				Vector cross = activatorToOrigin.Cross( activatorToNearestPoint );
				if( cross.z > 0.0f ) sign = -1.0f;	
			}
		}

		AngularMove( m_vecAngle2 * sign, pev->speed );
	}
	else
	{
		LinearMove( m_vecPosition2, pev->speed );
	}
}
Beispiel #3
0
void CBaseDoor::DoorGoDown( void )
{
	if( !FBitSet( pev->spawnflags, SF_DOOR_SILENT ))
		EMIT_SOUND( edict(), CHAN_STATIC, STRING( pev->noise1 ), 1, ATTN_NORM );
	
	ASSERT( m_iState == STATE_ON || m_iState == STATE_TURN_ON );
	m_iState = STATE_TURN_OFF;

	SetMoveDone( DoorHitBottom );

	if( IsRotatingDoor( ))
		AngularMove( m_vecAngle1, pev->speed );
	else LinearMove( m_vecPosition1, pev->speed );
}
//-----------------------------------------------------------------------------
// Purpose: 
// Input  : isOpen - 
//-----------------------------------------------------------------------------
void CBaseDoor::UpdateAreaPortals( bool isOpen )
{
	// cancel pending close
	SetContextThink( NULL, gpGlobals->curtime, CLOSE_AREAPORTAL_THINK_CONTEXT );

	if ( IsRotatingDoor() && HasSpawnFlags(SF_DOOR_START_OPEN_OBSOLETE) ) // logic inverted when using rot doors that start open
		isOpen = !isOpen;

	string_t name = GetEntityName();
	if ( !name )
		return;
	
	CBaseEntity *pPortal = NULL;
	while ( ( pPortal = gEntList.FindEntityByClassname( pPortal, "func_areaportal*" ) ) != NULL )
	{
		if ( pPortal->HasTarget( name ) )
		{
			// USE_ON means open the portal, off means close it
			pPortal->Use( this, this, isOpen?USE_ON:USE_OFF, 0 );
		}
	}
}
//-----------------------------------------------------------------------------
// Purpose: Starts the door going to its "up" position (simply ToggleData->vecPosition2).
//-----------------------------------------------------------------------------
void CBaseDoor::DoorGoUp( void )
{
	edict_t	*pevActivator;

	UpdateAreaPortals( true );
	// It could be going-down, if blocked.
	ASSERT(m_toggle_state == TS_AT_BOTTOM || m_toggle_state == TS_GOING_DOWN);

	// emit door moving and stop sounds on CHAN_STATIC so that the multicast doesn't
	// filter them out and leave a client stuck with looping door sounds!
	if ( !HasSpawnFlags(SF_DOOR_SILENT ) )
	{
		// If we're not moving already, start the moving noise
		if ( m_toggle_state != TS_GOING_UP && m_toggle_state != TS_GOING_DOWN )
		{
			StartMovingSound();
		}
	}

	m_toggle_state = TS_GOING_UP;
	
	SetMoveDone( &CBaseDoor::DoorHitTop );
	if ( IsRotatingDoor() )		// !!! BUGBUG Triggered doors don't work with this yet
	{
		float	sign = 1.0;

		if ( m_hActivator != NULL )
		{
			pevActivator = m_hActivator->edict();
			
			if ( !HasSpawnFlags( SF_DOOR_ONEWAY ) && m_vecMoveAng.y ) 		// Y axis rotation, move away from the player
			{
				// Positive is CCW, negative is CW, so make 'sign' 1 or -1 based on which way we want to open.
				// Important note:  All doors face East at all times, and twist their local angle to open.
				//					So you can't look at the door's facing to determine which way to open.

				Vector nearestPoint;
				CollisionProp()->CalcNearestPoint( m_hActivator->GetAbsOrigin(), &nearestPoint );
				Vector activatorToNearestPoint = nearestPoint - m_hActivator->GetAbsOrigin();
				activatorToNearestPoint.z = 0;

				Vector activatorToOrigin = GetAbsOrigin() - m_hActivator->GetAbsOrigin();
				activatorToOrigin.z = 0;

				// Point right hand at door hinge, curl hand towards closest spot on door, if thumb
				// is up, open door CW.  -- Department of Basic Cross Product Understanding for Noobs
				Vector cross = activatorToOrigin.Cross( activatorToNearestPoint );

				if( cross.z > 0.0f )
				{
					sign = -1.0f;	
				}
			}
		}
		AngularMove(m_vecAngle2*sign, m_flSpeed);
	}
	else
	{
		LinearMove(m_vecPosition2, m_flSpeed);
	}

	//Fire our open ouput
	m_OnOpen.FireOutput( this, this );
}
//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
void CBaseDoor::Precache( void )
{
	//Fill in a default value if necessary
	if ( IsRotatingDoor() )
	{
		UTIL_ValidateSoundName( m_NoiseMoving,		"RotDoorSound.DefaultMove" );
		UTIL_ValidateSoundName( m_NoiseArrived,		"RotDoorSound.DefaultArrive" );
		UTIL_ValidateSoundName( m_ls.sLockedSound,	"RotDoorSound.DefaultLocked" );
		UTIL_ValidateSoundName( m_ls.sUnlockedSound,"DoorSound.Null" );
	}
	else
	{
		UTIL_ValidateSoundName( m_NoiseMoving,		"DoorSound.DefaultMove" );
		UTIL_ValidateSoundName( m_NoiseArrived,		"DoorSound.DefaultArrive" );
#ifndef HL1_DLL		
		UTIL_ValidateSoundName( m_ls.sLockedSound,	"DoorSound.DefaultLocked" );
#endif
		UTIL_ValidateSoundName( m_ls.sUnlockedSound,"DoorSound.Null" );
	}

#ifdef HL1_DLL
	if( m_ls.sLockedSound != NULL_STRING && strlen((char*)STRING(m_ls.sLockedSound)) < 4 )
	{
		// Too short to be ANYTHING ".wav", so it must be an old index into a long-lost
		// array of sound choices. slam it to a known "deny" sound. We lose the designer's
		// original selection, but we don't get unresponsive doors.
		m_ls.sLockedSound = AllocPooledString("buttons/button2.wav");
	}
#endif//HL1_DLL

	//Precache them all
	PrecacheScriptSound( (char *) STRING(m_NoiseMoving) );
	PrecacheScriptSound( (char *) STRING(m_NoiseArrived) );
	PrecacheScriptSound( (char *) STRING(m_NoiseMovingClosed) );
	PrecacheScriptSound( (char *) STRING(m_NoiseArrivedClosed) );
	PrecacheScriptSound( (char *) STRING(m_ls.sLockedSound) );
	PrecacheScriptSound( (char *) STRING(m_ls.sUnlockedSound) );

	//Get sentence group names, for doors which are directly 'touched' to open
	switch (m_bLockedSentence)
	{
		case 1: m_ls.sLockedSentence = AllocPooledString("NA"); break; // access denied
		case 2: m_ls.sLockedSentence = AllocPooledString("ND"); break; // security lockout
		case 3: m_ls.sLockedSentence = AllocPooledString("NF"); break; // blast door
		case 4: m_ls.sLockedSentence = AllocPooledString("NFIRE"); break; // fire door
		case 5: m_ls.sLockedSentence = AllocPooledString("NCHEM"); break; // chemical door
		case 6: m_ls.sLockedSentence = AllocPooledString("NRAD"); break; // radiation door
		case 7: m_ls.sLockedSentence = AllocPooledString("NCON"); break; // gen containment
		case 8: m_ls.sLockedSentence = AllocPooledString("NH"); break; // maintenance door
		case 9: m_ls.sLockedSentence = AllocPooledString("NG"); break; // broken door
		
		default: m_ls.sLockedSentence = NULL_STRING; break;
	}

	switch (m_bUnlockedSentence)
	{
		case 1: m_ls.sUnlockedSentence = AllocPooledString("EA"); break; // access granted
		case 2: m_ls.sUnlockedSentence = AllocPooledString("ED"); break; // security door
		case 3: m_ls.sUnlockedSentence = AllocPooledString("EF"); break; // blast door
		case 4: m_ls.sUnlockedSentence = AllocPooledString("EFIRE"); break; // fire door
		case 5: m_ls.sUnlockedSentence = AllocPooledString("ECHEM"); break; // chemical door
		case 6: m_ls.sUnlockedSentence = AllocPooledString("ERAD"); break; // radiation door
		case 7: m_ls.sUnlockedSentence = AllocPooledString("ECON"); break; // gen containment
		case 8: m_ls.sUnlockedSentence = AllocPooledString("EH"); break; // maintenance door
		
		default: m_ls.sUnlockedSentence = NULL_STRING; break;
	}
}
//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
void CBaseDoor::Spawn()
{
	Precache();

#ifdef HL1_DLL
	SetSolid( SOLID_BSP );
#else
	if ( GetMoveParent() && GetRootMoveParent()->GetSolid() == SOLID_BSP )
	{
		SetSolid( SOLID_BSP );
	}
	else
	{
		SetSolid( SOLID_VPHYSICS );
	}
#endif

	// Convert movedir from angles to a vector
	QAngle angMoveDir = QAngle( m_vecMoveDir.x, m_vecMoveDir.y, m_vecMoveDir.z );
	AngleVectors( angMoveDir, &m_vecMoveDir );

	SetModel( STRING( GetModelName() ) );
	m_vecPosition1	= GetLocalOrigin();

	// Subtract 2 from size because the engine expands bboxes by 1 in all directions making the size too big
	Vector vecOBB = CollisionProp()->OBBSize();
	vecOBB -= Vector( 2, 2, 2 );
	m_vecPosition2	= m_vecPosition1 + (m_vecMoveDir * (DotProductAbs( m_vecMoveDir, vecOBB ) - m_flLip));

	if ( !IsRotatingDoor() )
	{
		if ( ( m_eSpawnPosition == FUNC_DOOR_SPAWN_OPEN ) || HasSpawnFlags( SF_DOOR_START_OPEN_OBSOLETE ) )
		{	// swap pos1 and pos2, put door at pos2
			UTIL_SetOrigin( this, m_vecPosition2);
			m_toggle_state = TS_AT_TOP;
		}
		else
		{
			m_toggle_state = TS_AT_BOTTOM;
		}
	}

	if (HasSpawnFlags(SF_DOOR_LOCKED))
	{
		m_bLocked = true;
	}

	SetMoveType( MOVETYPE_PUSH );
	
	if (m_flSpeed == 0)
	{
		m_flSpeed = 100;
	}
	
	SetTouch( &CBaseDoor::DoorTouch );

	if ( !FClassnameIs( this, "func_water" ) )
	{
		if ( HasSpawnFlags(SF_DOOR_PASSABLE) )
		{
			//normal door
			AddEFlags( EFL_USE_PARTITION_WHEN_NOT_SOLID );
			AddSolidFlags( FSOLID_NOT_SOLID );
		}

		if ( HasSpawnFlags( SF_DOOR_NONSOLID_TO_PLAYER ) )
		{
			SetCollisionGroup( COLLISION_GROUP_PASSABLE_DOOR );
			// HACKHACK: Set this hoping that any children of the door that get blocked by the player
			// will get fixed up by vphysics
			// NOTE: We could decouple this as a separate behavior, but managing player collisions is already complex enough.
			// NOTE: This is necessary to prevent the player from blocking the wrecked train car in ep2_outland_01
			AddFlag( FL_UNBLOCKABLE_BY_PLAYER );
		}
		if ( m_bIgnoreDebris )
		{
			// both of these flags want to set the collision group and 
			// there isn't a combo group
			Assert( !HasSpawnFlags( SF_DOOR_NONSOLID_TO_PLAYER ) );
			if ( HasSpawnFlags( SF_DOOR_NONSOLID_TO_PLAYER ) )
			{
				Warning("Door %s with conflicting collision settings, removing ignoredebris\n", GetDebugName() );
			}
			else
			{
				SetCollisionGroup( COLLISION_GROUP_INTERACTIVE );
			}
		}
	}

	if ( ( m_eSpawnPosition == FUNC_DOOR_SPAWN_OPEN ) && HasSpawnFlags( SF_DOOR_START_OPEN_OBSOLETE ) )
	{
		Warning("Door %s using obsolete 'Start Open' spawnflag with 'Spawn Position' set to 'Open'. Reverting to old behavior.\n", GetDebugName() );
	}

	CreateVPhysics();
}