CAreaPortalOneWay

From Valve Developer Community
Revision as of 12:35, 9 June 2008 by TomEdwards (talk | contribs) (some entity source code)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
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 its 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