//----------------------------------------------------------------------------- // 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 ); }
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 ); } }
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(); }