CAreaPortalOneWay

From Valve Developer Community
Jump to navigation Jump to search

This is free entity source code for CAreaPortalOneWay, an areaportal that is only open when the player is within 90° of a specified direction relative to it. It is useful in brightly-lit holes/windows that can be seen out of but not into.

Tip.pngTip:If the player needs to walk through the portal, func_areaportalwindow is a better choice.

C++

Paste this at the end of game\server\func_areaportal.cpp (there is no header file).

class CAreaPortalOneWay : public CAreaPortal
{
	DECLARE_CLASS( CAreaPortalOneWay, CAreaPortal );
	DECLARE_DATADESC();

	Vector m_vecOpenVector;
	string_t m_szLinkedEnt; // Anything with an origin will do

	void Activate();
	bool UpdateVisibility( const Vector &vOrigin, float fovDistanceAdjustFactor, bool &bIsOpenOnClient );
};

LINK_ENTITY_TO_CLASS( func_areaportal_oneway, CAreaPortalOneWay );

BEGIN_DATADESC( CAreaPortalOneWay )
	DEFINE_KEYFIELD( m_vecOpenVector, FIELD_VECTOR, "onewayfacing" ),
	DEFINE_KEYFIELD( m_szLinkedEnt, FIELD_STRING, "linkedent" ),
END_DATADESC()

void CAreaPortalOneWay::Activate()
{
	BaseClass::Activate();

	// Get our brush
	CBaseEntity* pBrush = gEntList.FindEntityByName(NULL,m_szLinkedEnt);
	if ( !pBrush || pBrush->GetAbsOrigin() == Vector(0,0,0) ) // FIXME: Once in a blue moon (0,0,0) might be valid!
	{
		Warning( "%s has missing/invalid associated entity! DELETING!\n", GetDebugName() );
		UTIL_Remove(this);
		return;
	}

	SetAbsOrigin( pBrush->GetAbsOrigin() );

	// Convert our angle from Hammer to a proper vector
	QAngle angOpenDir = QAngle( m_vecOpenVector.x, m_vecOpenVector.y, m_vecOpenVector.z );
	AngleVectors( angOpenDir, &m_vecOpenVector );

	// Re-scale the vector's axes to between 0 and 1
	VectorNormalize(m_vecOpenVector);

	// Move our vector so that it's an offset from the brush's origin
	m_vecOpenVector = GetAbsOrigin() * m_vecOpenVector;
}

bool CAreaPortalOneWay::UpdateVisibility( const Vector &vOrigin, float fovDistanceAdjustFactor, bool &bIsOpenOnClient )
{
	// Move vOrigin so that it's an offset from the brush
	// (Need a new var since it's const)
	Vector point = vOrigin - GetAbsOrigin();
	VectorNormalize(point);

	// Is the adjusted vOrigin behind openvector?
	if ( DotProduct( m_vecOpenVector, point ) < 0 )
		return false;
	else
		// Let the baseclass close the portal if it wants
		return BaseClass::UpdateVisibility( vOrigin, fovDistanceAdjustFactor, bIsOpenOnClient );
}

Doors

If you want to attach a door to a CAreaPortalOneWay, you will need to modify the former's code so that it finds the "func_areaportal_oneway" entity.

CBasePropDoor::UpdateAreaPortals & CBaseDoor::UpdateAreaPortals:
  - while ((pPortal = gEntList.FindEntityByClassname(pPortal, "func_areaportal")) != NULL)
  + while ((pPortal = gEntList.FindEntityByClassname(pPortal, "func_areaportal*")) != NULL)

Note the new asterisk.

FGD

@SolidClass base(func_areaportal) color(0 255 255) = func_areaportal_oneway :
	"An areaportal that is only open when the player is within 90 degrees of the specified  direction."
[
	onewayfacing(angle) : "Open direction" : "0 0 0" : "The portal will be open when the player is within 90 degrees of this direction, relative to the origin of the linked entity."
	linkedent(target_destination) : "Linked entity (required)" : "" : "An entity of some sort is required to bring the compiled portal back into world co-ordinates. It will probably be a brush that fills the gap left by the portal when closed."
]

See also