void CASW_Laser_Mine::LaserThink( void )
{
	if ( !m_bMineActive )
	{
		SetNextThink( gpGlobals->curtime );
		return;
	}
		
	UpdateLaser();

	// check for destroying the mine if we attach to a moving door
	if ( GetMoveParent() && GetMoveParent()->Classify() == CLASS_ASW_DOOR )
	{
		CASW_Door *pDoor = assert_cast<CASW_Door*>( GetMoveParent() );
		if ( !pDoor->IsDoorClosed() )
		{
			// do a small explosion when we die in this fashion
			m_flDamage = 10.0f;
			m_flDamageRadius = 64.0f;
			Explode();
		}
	}
	
	SetNextThink( gpGlobals->curtime + 0.1f );
}
//-----------------------------------------------------------------------------
// Purpose:
// Input  : *pHandleEntity -
//			contentsMask -
// Output : Returns true on success, false on failure.
//-----------------------------------------------------------------------------
bool CASW_Trace_Filter_Doors::ShouldHitEntity( IHandleEntity *pHandleEntity, int contentsMask )
{
    if ( !StandardFilterRules( pHandleEntity, contentsMask ) )
        return false;

    // Don't test if the game code tells us we should ignore this collision...
    CBaseEntity *pEntity = EntityFromEntityHandle( pHandleEntity );
    const CBaseEntity *pEntPass = EntityFromEntityHandle( m_pPassEnt );

    // don't hurt ourself
    if ( pEntPass == pEntity )
        return false;

    if ( !pEntity || pEntity->Classify() != CLASS_ASW_DOOR )
        return false;

    CASW_Door *pDoor = assert_cast<CASW_Door*>( pEntity );
    if ( !pDoor )
        return false;

    if ( m_bRequireLockedOrSealed )
    {
        if ( pDoor->GetSealAmount() > 0 || !pDoor->IsAutoOpen() )
        {
            return true;
        }
        else
        {
            return false;
        }
    }

    return true;
}
void CASW_Button_Area::ActivateUnlockedButton(CASW_Marine* pMarine)
{
	// don't use the button if we're in the delay between using
	if ( m_fLastButtonUseTime != 0 && gpGlobals->curtime < m_fLastButtonUseTime + m_flWait )
		return;
	if ( !pMarine )
		return;

	if( !RequirementsMet( pMarine ) )
		return;

	if ( m_bIsDoorButton )
	{
		// if the door isn't sealed (or greater than a certain amount of damage?)
		//  then make it open
		CASW_Door* pDoor = GetDoor();
		if ( pDoor )
		{
			if (pDoor->GetSealAmount() > 0)
			{
				//Msg("Door mechanism not responding.  Maintenance Division has been notified of the problem.\n");
			}
			else
			{				
				//Msg("Toggling door...\n");
				variant_t emptyVariant;
				pDoor->AcceptInput("Toggle", pMarine, this, emptyVariant, 0);
			}
		}
	}

	// send our 'activated' output
	m_OnButtonActivated.FireOutput(pMarine, this);

	// Fire event
	IGameEvent * event = gameeventmanager->CreateEvent( "button_area_used" );
	if ( event )
	{
		CASW_Player *pPlayer = pMarine->GetCommander();

		event->SetInt( "userid", ( pPlayer ? pPlayer->GetUserID() : 0 ) );
		event->SetInt( "entindex", entindex() );
		gameeventmanager->FireEvent( event );
	}

	m_fLastButtonUseTime = gpGlobals->curtime;

	UpdateWaitingForInput();

	if ( m_bDisableAfterUse )
	{
		UTIL_Remove(this);
	}
}
void asw_flip_door_f()
{
	CBaseEntity* pEntity = NULL;
	while ((pEntity = gEntList.FindEntityByClassname( pEntity, "asw_door" )) != NULL)
	{
		CASW_Door* pDoor = dynamic_cast<CASW_Door*>(pEntity);
		if (pDoor)
		{
			pDoor->FlipDoor();
		}
	}
}
bool CASW_Weapon_Welder::OffhandActivate()
{
	CASW_Marine *pMarine = GetMarine();
	if ( !pMarine || !pMarine->GetCommander() )
		return false;

	bool bRecommendedSeal = false;

	float fSealAmount = -1.0f;

	CASW_Door *pDoor = FindDoor();
	if ( pDoor )
	{
		fSealAmount = pDoor->GetSealAmount();
		bRecommendedSeal = pDoor->IsRecommendedSeal();
	}

	if ( fSealAmount < 0.0f )
	{
		return true;
	}

	// start automatic welding
	if ( !m_bShotDelayed )
	{
		m_bShotDelayed = true;
#ifdef GAME_DLL
		pMarine->OnWeldStarted();
#endif
		if ( fSealAmount == 0.0f || ( bRecommendedSeal && fSealAmount < 1.0f ) )
		{
			m_iAutomaticWeldDirection = 1;
		}
		else
		{
			// default to unsealing the door
			m_iAutomaticWeldDirection = -1;
		}
	}	
	else
	{
		// already welding, just flip direction
		m_iAutomaticWeldDirection = -m_iAutomaticWeldDirection;
	}

	return true;
}
void CASW_Button_Area::UpdateWaitingForInput()
{
	bool bOldWaitingForInput = m_bWaitingForInput;

	bool bSet = false;

	if ( m_bIsDoorButton )
	{
		CASW_Door *pDoor = GetDoor();
		if ( pDoor && pDoor->IsAutoOpen() )
		{
			m_bWaitingForInput = false;
			bSet = true;
		}
	}

	if ( !bSet )
	{
		m_bWaitingForInput = ASWGameRules()->GetGameState() == ASW_GS_INGAME && 
							 ( !m_bNoPower && !m_bIsInUse && ( m_bIsLocked || ( !m_bWasLocked && m_fLastButtonUseTime == 0 ) ) );
	}

	if ( !bOldWaitingForInput && m_bWaitingForInput )
	{
		VisibilityMonitor_AddEntity( this, asw_visrange_generic.GetFloat() * 0.9f, &CASW_Button_Area::WaitingForInputVismonCallback, &CASW_Button_Area::WaitingForInputVismonEvaluator );
	}
	else if ( bOldWaitingForInput && !m_bWaitingForInput )
	{
		VisibilityMonitor_RemoveEntity( this );

		IGameEvent * event = gameeventmanager->CreateEvent( "button_area_inactive" );
		if ( event )
		{
			event->SetInt( "entindex", entindex() );
			gameeventmanager->FireEvent( event );
		}
	}
}
CASW_Door* CASW_Weapon_Welder::FindDoor()
{
	CASW_Marine *pMarine = GetMarine();
	if ( !pMarine )
		return NULL;

	if ( pMarine->IsInhabited() )
	{
		CASW_Player *pPlayer = pMarine->GetCommander();
		if ( !pPlayer )
			return NULL;

		// find our door area
		for ( int i = 0; i < pPlayer->GetNumUseEntities(); i++ )
		{
			CBaseEntity* pEnt = pPlayer->GetUseEntity( i );
			CASW_Door_Area* pDoorArea = dynamic_cast< CASW_Door_Area* >( pEnt );
			if ( pDoorArea )
			{
				CASW_Door* pDoor = pDoorArea->GetASWDoor();
				if ( pDoor && pDoor->GetHealth() > 0 )
				{
					return pDoor;
				}
			}
		}
	}
	else
	{
#ifdef GAME_DLL
		CASW_Door_Area *pClosestArea = NULL;
		float flClosestDist = FLT_MAX;

		for ( int i = 0; i < IASW_Use_Area_List::AutoList().Count(); i++ )
		{
			CASW_Use_Area *pArea = static_cast< CASW_Use_Area* >( IASW_Use_Area_List::AutoList()[ i ] );
			if ( pArea->Classify() == CLASS_ASW_DOOR_AREA )
			{
				CASW_Door_Area *pDoorArea = assert_cast<CASW_Door_Area*>( pArea );
				CASW_Door* pDoor = pDoorArea->GetASWDoor();
				if ( !pDoor || pDoor->GetHealth() <= 0 )
				{
					continue;
				}

				float flDist = GetAbsOrigin().DistTo( pArea->WorldSpaceCenter() );
				if ( flDist < flClosestDist && pArea->CollisionProp()->IsPointInBounds( pMarine->WorldSpaceCenter() ) )
				{
					flClosestDist = flDist;
					pClosestArea = pDoorArea;
				}
			}
		}

		if ( pClosestArea )
		{
			CASW_Door* pDoor = pClosestArea->GetASWDoor();
			if ( pDoor )
			{
				return pDoor;
			}
		}
#endif
	}
	return NULL;
}
void CASW_Weapon_Welder::WeldDoor(bool bSeal)
{
	CASW_Marine *pMarine = GetMarine();
	if ( !pMarine || !pMarine->GetCommander() )
		return;

	bool bWelding = false;

	CASW_Door* pDoor = FindDoor();
	if ( pDoor )
	{
		bWelding = true;

		Vector vecFacingPoint = pDoor->GetWeldFacingPoint(pMarine);
		Vector diff = vecFacingPoint - pMarine->GetAbsOrigin();
		diff.z = 0;
		VectorNormalize(diff);
		QAngle angCurrentFacing = pMarine->ASWEyeAngles();
		Vector vecCurrentFacing = vec3_origin;
		AngleVectors(angCurrentFacing, &vecCurrentFacing);
		vecCurrentFacing.z = 0;
		VectorNormalize(vecCurrentFacing);
		bool bFacing = DotProduct(diff, vecCurrentFacing) > 0.6f;
		if ( !pMarine->IsInhabited() )
		{
			bFacing = true;	// AI marines don't know how to face the door yet
		}
		if ( bFacing && !pDoor->IsOpen() )
		{
			// do our muzzle flash, if we're going to alter the weld some
			if ( bSeal && pDoor->GetSealAmount() < 1.0f )
			{
				pMarine->DoMuzzleFlash();
				m_bIsFiring = true;
			}
			else if ( !bSeal && pDoor->GetSealAmount() > 0 )
			{
				pMarine->DoMuzzleFlash();
				m_bIsFiring = true;
			}					
		}
#ifdef CLIENT_DLL
		pMarine->SetFacingPoint(vecFacingPoint, GetFireRate()*2.0f);
#else
		if ( gpGlobals->maxClients <= 1 )
		{
			pMarine->SetFacingPoint(vecFacingPoint, GetFireRate()*2.0f);
		}
#endif
		if ( bFacing )
		{
			if ( pDoor->IsOpen() )
			{
#ifndef CLIENT_DLL
				if ( bSeal )
				{
					pDoor->CloseForWeld( pMarine );	// shut the door first, so we can start welding it
				}
#endif
			}
			else
			{
				// tell the weapon to weld over the next fire rate interval
				m_fWeldTime = GetFireRate() + 0.004f;
				m_bWeldSeal = bSeal;
#ifndef CLIENT_DLL
				m_pWeldDoor = pDoor;
				//Msg( "Setting weld door to %d\n", pDoor->entindex() );
				// network door which door we're working on so all players can see progress
				if ( pMarine->GetMarineResource() )
					pMarine->GetMarineResource()->m_hWeldingDoor = pDoor;
#endif
			}
		}
	}
	else
	{
		//Msg( "Couldn't find door to weld\n" );
	}

	if ( pMarine->GetActiveWeapon() != this )
	{
		bool bAttack1, bAttack2, bReload, bOldReload, bOldAttack1;
		GetButtons( bAttack1, bAttack2, bReload, bOldReload, bOldAttack1 );

		if ( bAttack1 || bAttack2 || bReload || pMarine->GetCurrentMeleeAttack() )
		{
			bWelding = false;
		}
	}

	if ( !bWelding )
	{
		m_iAutomaticWeldDirection = 0;
		m_bShotDelayed = false;
#ifdef GAME_DLL
		if ( pMarine->GetMarineResource() )
		{
			pMarine->GetMarineResource()->m_hWeldingDoor = NULL;
		}

		m_pWeldDoor = NULL;

		pMarine->OnWeldFinished();
#endif
		m_bIsFiring = false;
	}
	else
	{
		if ( bSeal )
		{
			m_flNextPrimaryAttack = m_flNextPrimaryAttack + GetFireRate();
		}
		else
		{
			m_flNextSecondaryAttack = m_flNextSecondaryAttack + GetFireRate();
		}
	}
}