//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CTFWeaponBuilder::ItemPostFrame( void ) { CTFPlayer *pOwner = ToTFPlayer( GetOwner() ); if ( !pOwner ) return; // If we're building, and our team has lost, stop placing the object if ( m_hObjectBeingBuilt.Get() && TFGameRules()->State_Get() == GR_STATE_TEAM_WIN && pOwner->GetTeamNumber() != TFGameRules()->GetWinningTeam() ) { StopPlacement(); return; } // Check that I still have enough resources to build this item if ( pOwner->CanBuild( m_iObjectType ) != CB_CAN_BUILD ) { SwitchOwnersWeaponToLast(); } if (( pOwner->m_nButtons & IN_ATTACK ) && (m_flNextPrimaryAttack <= gpGlobals->curtime) ) { PrimaryAttack(); } if ( pOwner->m_nButtons & IN_ATTACK2 ) { if ( m_flNextSecondaryAttack <= gpGlobals->curtime ) { SecondaryAttack(); } } else { m_bInAttack2 = false; } WeaponIdle(); }
//----------------------------------------------------------------------------- // Purpose: Start placing or building the currently selected object //----------------------------------------------------------------------------- void CTFWeaponBuilder::PrimaryAttack( void ) { CTFPlayer *pOwner = ToTFPlayer( GetOwner() ); if ( !pOwner ) return; if ( !CanAttack() ) return; // Necessary so that we get the latest building position for the test, otherwise // we are one frame behind. UpdatePlacementState(); // What state should we move to? switch( m_iBuildState ) { case BS_IDLE: { // Idle state starts selection SetCurrentState( BS_SELECTING ); } break; case BS_SELECTING: { // Do nothing, client handles selection return; } break; case BS_PLACING: { if ( m_hObjectBeingBuilt ) { int iFlags = m_hObjectBeingBuilt->GetObjectFlags(); // Tricky, because this can re-calc the object position and change whether its a valid // pos or not. Best not to do this only in debug, but we can be pretty sure that this // will give the same result as was calculated in UpdatePlacementState() above. Assert( IsValidPlacement() ); // If we're placing an attachment, like a sapper, play a placement animation on the owner if ( m_hObjectBeingBuilt->MustBeBuiltOnAttachmentPoint() ) { pOwner->DoAnimationEvent( PLAYERANIMEVENT_ATTACK_GRENADE ); } StartBuilding(); // Should we switch away? if ( iFlags & OF_ALLOW_REPEAT_PLACEMENT ) { // Start placing another SetCurrentState( BS_PLACING ); StartPlacement(); } else { SwitchOwnersWeaponToLast(); } } } break; case BS_PLACING_INVALID: { if ( m_flNextDenySound < gpGlobals->curtime ) { CSingleUserRecipientFilter filter( pOwner ); EmitSound( filter, entindex(), "Player.DenyWeaponSelection" ); m_flNextDenySound = gpGlobals->curtime + 0.5; } } break; } m_flNextPrimaryAttack = gpGlobals->curtime + 0.2f; }
//----------------------------------------------------------------------------- // Purpose: Start placing or building the currently selected object //----------------------------------------------------------------------------- void CTFWeaponBuilder::PrimaryAttack( void ) { CTFPlayer *pOwner = ToTFPlayer( GetOwner() ); if ( !pOwner ) return; if ( !CanAttack() ) return; // Necessary so that we get the latest building position for the test, otherwise // we are one frame behind. UpdatePlacementState(); // What state should we move to? switch( m_iBuildState ) { case BS_IDLE: { // Idle state starts selection SetCurrentState( BS_SELECTING ); } break; case BS_SELECTING: { // Do nothing, client handles selection return; } break; case BS_PLACING: { if ( m_hObjectBeingBuilt ) { int iFlags = m_hObjectBeingBuilt->GetObjectFlags(); // Tricky, because this can re-calc the object position and change whether its a valid // pos or not. Best not to do this only in debug, but we can be pretty sure that this // will give the same result as was calculated in UpdatePlacementState() above. Assert( IsValidPlacement() ); // If we're placing an attachment, like a sapper, play a placement animation on the owner if ( m_hObjectBeingBuilt->MustBeBuiltOnAttachmentPoint() ) { pOwner->DoAnimationEvent( PLAYERANIMEVENT_ATTACK_GRENADE ); } // Need to save this for later since StartBuilding will clear m_hObjectBeingBuilt. CBaseObject *pParentObject = m_hObjectBeingBuilt->GetParentObject(); StartBuilding(); // Attaching a sapper to a teleporter automatically saps another end. if ( GetType() == OBJ_ATTACHMENT_SAPPER ) { CObjectTeleporter *pTeleporter = dynamic_cast<CObjectTeleporter *>( pParentObject ); if ( pTeleporter ) { CObjectTeleporter *pMatch = pTeleporter->GetMatchingTeleporter(); // If the other end is not already sapped then place a sapper on it. if ( pMatch && !pMatch->IsPlacing() && !pMatch->HasSapper() ) { SetCurrentState( BS_PLACING ); StartPlacement(); if ( m_hObjectBeingBuilt.Get() ) { m_hObjectBeingBuilt->UpdateAttachmentPlacement( pMatch ); StartBuilding(); } } } } // Should we switch away? if ( iFlags & OF_ALLOW_REPEAT_PLACEMENT ) { // Start placing another SetCurrentState( BS_PLACING ); StartPlacement(); } else { SwitchOwnersWeaponToLast(); } } } break; case BS_PLACING_INVALID: { if ( m_flNextDenySound < gpGlobals->curtime ) { CSingleUserRecipientFilter filter( pOwner ); EmitSound( filter, entindex(), "Player.DenyWeaponSelection" ); m_flNextDenySound = gpGlobals->curtime + 0.5; } } break; } m_flNextPrimaryAttack = gpGlobals->curtime + 0.2f; }