void CFunc_LiquidPortal::TeleportImmersedEntity( CBaseEntity *pEntity ) { if( pEntity == NULL ) return; if( pEntity->IsPlayer() ) { CPortal_Player *pEntityAsPlayer = (CPortal_Player *)pEntity; Vector vNewOrigin = m_matrixThisToLinked * pEntity->GetAbsOrigin(); QAngle qNewAngles = TransformAnglesToWorldSpace( pEntityAsPlayer->EyeAngles(), m_matrixThisToLinked.As3x4() ); Vector vNewVelocity = m_matrixThisToLinked.ApplyRotation( pEntity->GetAbsVelocity() ); pEntity->Teleport( &vNewOrigin, &qNewAngles, &vNewVelocity ); pEntityAsPlayer->m_hSurroundingLiquidPortal = m_hLinkedPortal; } else { Vector vNewOrigin = m_matrixThisToLinked * pEntity->GetAbsOrigin(); QAngle qNewAngles = TransformAnglesToWorldSpace( pEntity->GetAbsAngles(), m_matrixThisToLinked.As3x4() ); Vector vNewVelocity = m_matrixThisToLinked.ApplyRotation( pEntity->GetAbsVelocity() ); pEntity->Teleport( &vNewOrigin, &qNewAngles, &vNewVelocity ); } }
float CWeaponPortalgun::FirePortal( bool bPortal2, Vector *pVector /*= 0*/, bool bTest /*= false*/ ) { bool bPlayer = false; Vector vEye; Vector vDirection; Vector vTracerOrigin; CBaseEntity *pOwner = GetOwner(); if ( pOwner && pOwner->IsPlayer() ) { bPlayer = true; } if( bPlayer ) { CPortal_Player *pPlayer = (CPortal_Player *)pOwner; if ( !bTest && pPlayer ) { pPlayer->DoAnimationEvent( PLAYERANIMEVENT_ATTACK_PRIMARY, 0 ); } Vector forward, right, up; AngleVectors( pPlayer->EyeAngles(), &forward, &right, &up ); pPlayer->EyeVectors( &vDirection, NULL, NULL ); vEye = pPlayer->EyePosition(); // Check if the players eye is behind the portal they're in and translate it VMatrix matThisToLinked; CProp_Portal *pPlayerPortal = pPlayer->m_hPortalEnvironment; if ( pPlayerPortal ) { Vector ptPortalCenter; Vector vPortalForward; ptPortalCenter = pPlayerPortal->GetAbsOrigin(); pPlayerPortal->GetVectors( &vPortalForward, NULL, NULL ); Vector vEyeToPortalCenter = ptPortalCenter - vEye; float fPortalDist = vPortalForward.Dot( vEyeToPortalCenter ); if( fPortalDist > 0.0f ) { // Eye is behind the portal matThisToLinked = pPlayerPortal->MatrixThisToLinked(); } else { pPlayerPortal = NULL; } } if ( pPlayerPortal ) { UTIL_Portal_VectorTransform( matThisToLinked, forward, forward ); UTIL_Portal_VectorTransform( matThisToLinked, right, right ); UTIL_Portal_VectorTransform( matThisToLinked, up, up ); UTIL_Portal_VectorTransform( matThisToLinked, vDirection, vDirection ); UTIL_Portal_PointTransform( matThisToLinked, vEye, vEye ); if ( pVector ) { UTIL_Portal_VectorTransform( matThisToLinked, *pVector, *pVector ); } } vTracerOrigin = vEye + forward * 30.0f + right * 4.0f + up * (-5.0f); } else { // This portalgun is not held by the player-- Fire using the muzzle attachment Vector vecShootOrigin; QAngle angShootDir; GetAttachment( LookupAttachment( "muzzle" ), vecShootOrigin, angShootDir ); vEye = vecShootOrigin; vTracerOrigin = vecShootOrigin; AngleVectors( angShootDir, &vDirection, NULL, NULL ); } if ( !bTest ) { SendWeaponAnim( ACT_VM_PRIMARYATTACK ); } if ( pVector ) { vDirection = *pVector; } Vector vTraceStart = vEye + (vDirection * m_fMinRange1); Vector vFinalPosition; QAngle qFinalAngles; PortalPlacedByType ePlacedBy = ( bPlayer ) ? ( PORTAL_PLACED_BY_PLAYER ) : ( PORTAL_PLACED_BY_PEDESTAL ); trace_t tr; float fPlacementSuccess = TraceFirePortal( bPortal2, vTraceStart, vDirection, tr, vFinalPosition, qFinalAngles, ePlacedBy, bTest ); if ( sv_portal_placement_never_fail.GetBool() ) { fPlacementSuccess = 1.0f; } if ( !bTest ) { CProp_Portal *pPortal = CProp_Portal::FindPortal( m_iPortalLinkageGroupID, bPortal2, true ); // If it was a failure, put the effect at exactly where the player shot instead of where the portal bumped to if ( fPlacementSuccess < 0.5f ) vFinalPosition = tr.endpos; pPortal->PlacePortal( vFinalPosition, qFinalAngles, fPlacementSuccess, true ); float fDelay = vTracerOrigin.DistTo( tr.endpos ) / ( ( bPlayer ) ? ( BLAST_SPEED ) : ( BLAST_SPEED_NON_PLAYER ) ); QAngle qFireAngles; VectorAngles( vDirection, qFireAngles ); DoEffectBlast( pPortal->m_bIsPortal2, ePlacedBy, vTracerOrigin, vFinalPosition, qFireAngles, fDelay ); pPortal->SetContextThink( &CProp_Portal::DelayedPlacementThink, gpGlobals->curtime + fDelay, s_pDelayedPlacementContext ); pPortal->m_vDelayedPosition = vFinalPosition; pPortal->m_hPlacedBy = this; } return fPlacementSuccess; }