BOOL CXTPMDIWndTab::UnInstall()
{
	// Remove all of the items from the child array.
	while (!m_arMDIChildern.IsEmpty())
	{
		MDICHILD* pMDIChild = m_arMDIChildern.RemoveHead();
		SAFE_DELETE(pMDIChild);
	}

	CXTPTabCtrlButtons* pNavBtns = GetButtons();
	if (pNavBtns && pNavBtns->GetSafeHwnd())
	{
		pNavBtns->UnSubclassTabButtons();
	}

	if (::IsWindow(m_hWnd) && m_pMDIFrameWnd)
	{
		// Unsubclass the MDI client and free the dynamic memory.
		m_pMDIClientWnd->UnsubclassWindow();
		SAFE_DELETE (m_pMDIClientWnd);

		// Force parent frame to re-adjust layout.
		m_pMDIFrameWnd->RecalcLayout();

		// Destroy this window.
		return DestroyWindow();
	}

	return FALSE;
}
bool CASW_Weapon_Minigun::ShouldMarineMoveSlow()
{
	bool bAttack1, bAttack2, bReload, bOldReload, bOldAttack1;
	GetButtons(bAttack1, bAttack2, bReload, bOldReload, bOldAttack1 );

	return ( BaseClass::ShouldMarineMoveSlow() || bAttack2 || bAttack1 || GetSpinRate() >= 0.99f );
}
Exemple #3
0
int main(int argc, char *argv[]) {
	displayWindow = SDL_CreateWindow("Jello", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, SCREENWIDTH, SCREENHEIGHT, SDL_WINDOW_OPENGL);
	context = SDL_GL_CreateContext(displayWindow);
	glOrtho(-SCREENWIDTH / 2, SCREENWIDTH / 2, SCREENHEIGHT / 2, -SCREENHEIGHT / 2, 0, 1);

	LoadContent();

	while (isRunning) {
		RemoveInitialPress();
		leftButtonPress = false;
		while (SDL_PollEvent(&event)) {
			if (event.type == SDL_QUIT)
				isRunning = false;

			GetKeys(event);
			GetButtons(event);
		}

		if (deltaTime < 1 / 60) {
			frameStart = SDL_GetTicks();
			SDL_Delay(1);
			frameEnd = SDL_GetTicks();
			deltaTime = frameEnd - frameStart;
		}
		frameStart = SDL_GetTicks();
		Update(deltaTime);
		Render(displayWindow, context);
		frameEnd = SDL_GetTicks();
		deltaTime = frameEnd - frameStart;
	}

	return 0;
}
void CFileManagerDlg::PrepareBackground(CDC *pDC)
{
  CDC *pCurDC = pDC;
  if (pCurDC == NULL)
    pCurDC = GetDC();

  CDC dcMem;
  dcMem.CreateCompatibleDC(pCurDC);
  if (m_bmpBkgnd.m_hObject != NULL)
    m_bmpBkgnd.DeleteObject();
  CRect rt;
  GetClientRect(&rt);
  m_bmpBkgnd.CreateCompatibleBitmap(pCurDC, rt.Width(), rt.Height());
  dcMem.SelectObject(&m_bmpBkgnd);
  DrawBackground(&dcMem);

  CButtonST **pButtons;
  UINT nButtons;
  GetButtons(pButtons, nButtons);

  for (unsigned int i = 0; i < nButtons; i++) {
    pButtons[i]->SetBk(&dcMem);
  }

  if (pDC == NULL)
    ReleaseDC(pCurDC);
}
void CASW_Weapon_Sniper_Rifle::ItemPostFrame( void )
{
	BaseClass::ItemPostFrame();

	CASW_Marine *pMarine = GetMarine();
	if ( !pMarine )
		return;

	// AIs switch out of zoom mode
	if ( !pMarine->IsInhabited() && IsZoomed() )
	{
		m_bZoomed = false;
	}

	bool bAttack1, bAttack2, bReload, bOldReload, bOldAttack1;
	GetButtons( bAttack1, bAttack2, bReload, bOldReload, bOldAttack1 );

	bool bOldAttack2 = false;
	if ( pMarine->IsInhabited() && pMarine->GetCommander() )
	{
		bOldAttack2 = !!(pMarine->m_nOldButtons & IN_ATTACK2);
	}

	if ( bAttack2 && !bOldAttack2 )
	{
		m_bZoomed = !IsZoomed();
	}
}
Exemple #6
0
void CBaseDelay::DelayThink( void )
{
	CBaseEntity *pActivator = NULL;

	if( GetOwner() )		// A player activated this on delay
	{
		pActivator = GetOwner();
	}
	// The use type is cached (and stashed) in GetButtons()
	SUB_UseTargets( pActivator, ( USE_TYPE ) GetButtons().Get(), 0 );
	UTIL_RemoveNow( this );
}
void CASW_Weapon_Minigun::UpdateSpinRate()
{
	bool bAttack1, bAttack2, bReload, bOldReload, bOldAttack1;
	GetButtons(bAttack1, bAttack2, bReload, bOldReload, bOldAttack1 );

	CASW_Marine *pMarine = GetMarine();
	bool bMeleeing = pMarine && ( pMarine->GetCurrentMeleeAttack() != NULL );
	bool bWalking = pMarine && pMarine->m_bWalking.Get();

	bool bSpinUp = !m_bInReload && !bMeleeing && ( bAttack1 || bAttack2 || bWalking );
	if ( bSpinUp )
	{
		m_flSpinRate = MIN( 1.0f, GetSpinRate() + gpGlobals->frametime * asw_minigun_spin_up_rate.GetFloat() );
	}
	else
	{
		m_flSpinRate = MAX( 0.0f, GetSpinRate() - gpGlobals->frametime * asw_minigun_spin_down_rate.GetFloat() * ( ( m_bInReload || bMeleeing ) ? 3.0f : 1.0f ) );
	}
}
/* Set the silkscreen to contain the toolbar buttons */
void HanderaSetSilkScreen( void )
{
    UInt16          defaultSize;
    PenBtnListType* defaultButtons;
    UInt16          numNewButtons;
    UInt16          newSize;
    PenBtnListType* newButtons;

    /* currently only handeraSilkScreen supported */
    if ( GetDIAHardware() != DIA_HARDWARE_HANDERA )
        return;

    currentSilkStatus = ( GetDIAState() == DIA_STATE_MAX ? 
                                         HANDERA_SILK_UP : HANDERA_SILK_DOWN );

    /* if we already have defaultButtonsHandle stored in memory, there
       is no point in doing everything again, since its already done */
    if ( defaultButtonsHandle[ currentSilkStatus ] != NULL )
        return;

    defaultSize = SilkGetButtonListSize( (Boolean) currentSilkStatus );

    defaultButtonsHandle[ currentSilkStatus ] = MemHandleNew( defaultSize );
    defaultButtons = MemHandleLock( defaultButtonsHandle[ currentSilkStatus ] );
    SilkGetButtonList( defaultButtons, (Boolean) currentSilkStatus );

    numNewButtons = defaultButtons->numButtons + TOTAL_ICONS;
    newSize = sizeof( PenBtnListType ) +
        ( sizeof( PenBtnInfoType ) * ( numNewButtons - 1 ) );
    newButtons = SafeMemPtrNew( newSize );
    MemMove( newButtons, defaultButtons, defaultSize );

    GetButtons();
    DrawButtons();
    SetButtons( newButtons );
    SilkSetButtonList( newButtons, (Boolean) currentSilkStatus );

    MemPtrUnlock( defaultButtons );
    SafeMemPtrFree( newButtons );
}
void CBasePlayer::PostThink()
{
	if( g_fGameOver )
		goto pt_end;         // intermission or finale

	if( !IsAlive() )
		goto pt_end;

	// Handle Tank controlling
	if( m_pTank != NULL )
	{
		// if they've moved too far from the gun,  or selected a weapon, unuse the gun
		if( m_pTank->OnControls( this ) && !HasWeaponModelName() )
		{
			m_pTank->Use( this, this, USE_SET, 2 );	// try fire the gun
		}
		else
		{  // they've moved off the platform
			m_pTank->Use( this, this, USE_OFF, 0 );
			m_pTank = NULL;
		}
	}

	// do weapon stuff
	ItemPostFrame();

	// check to see if player landed hard enough to make a sound
	// falling farther than half of the maximum safe distance, but not as far a max safe distance will
	// play a bootscrape sound, and no damage will be inflicted. Fallling a distance shorter than half
	// of maximum safe distance will make no sound. Falling farther than max safe distance will play a 
	// fallpain sound, and damage will be inflicted based on how far the player fell

	if( GetFlags().Any( FL_ONGROUND ) && ( GetHealth() > 0 ) && m_flFallVelocity >= PLAYER_FALL_PUNCH_THRESHHOLD )
	{
		// ALERT ( at_console, "%f\n", m_flFallVelocity );

		if( GetWaterType() == CONTENTS_WATER )
		{
			// Did he hit the world or a non-moving entity?
			// BUG - this happens all the time in water, especially when 
			// BUG - water has current force
			//CBaseEntity* pEntity = GetGroundEntity();
			//if ( !pEntity || pEntity->GetAbsVelocity().z == 0 )
			//	EMIT_SOUND( this, CHAN_BODY, "player/pl_wade1.wav", 1, ATTN_NORM);
		}
		else if( m_flFallVelocity > PLAYER_MAX_SAFE_FALL_SPEED )
		{
			// after this point, we start doing damage

			float flFallDamage = g_pGameRules->FlPlayerFallDamage( this );

			if( flFallDamage > GetHealth() )
			{//splat
			 // note: play on item channel because we play footstep landing on body channel
				EMIT_SOUND( this, CHAN_ITEM, "common/bodysplat.wav", 1, ATTN_NORM );
			}

			if( flFallDamage > 0 )
			{
				TakeDamage( CWorld::GetInstance(), CWorld::GetInstance(), flFallDamage, DMG_FALL );
				Vector vecPunchAngle = GetPunchAngle();
				vecPunchAngle.x = 0;
				SetPunchAngle( vecPunchAngle );
			}
		}

		if( IsAlive() )
		{
			SetAnimation( PLAYER_WALK );
		}
	}

	if( GetFlags().Any( FL_ONGROUND ) )
	{
		if( m_flFallVelocity > 64 && !g_pGameRules->IsMultiplayer() )
		{
			CSoundEnt::InsertSound( bits_SOUND_PLAYER, GetAbsOrigin(), m_flFallVelocity, 0.2 );
			// ALERT( at_console, "fall %f\n", m_flFallVelocity );
		}
		m_flFallVelocity = 0;
	}

	// select the proper animation for the player character	
	if( IsAlive() )
	{
		if( !GetAbsVelocity().x && !GetAbsVelocity().y )
			SetAnimation( PLAYER_IDLE );
		else if( ( GetAbsVelocity().x || GetAbsVelocity().y ) && ( GetFlags().Any( FL_ONGROUND ) ) )
			SetAnimation( PLAYER_WALK );
		else if( GetWaterLevel() > WATERLEVEL_FEET )
			SetAnimation( PLAYER_WALK );
	}

	StudioFrameAdvance();
	CheckPowerups( this );

	UpdatePlayerSound();

pt_end:
#if defined( CLIENT_WEAPONS )
	// Decay timers on weapons
	// go through all of the weapons and make a list of the ones to pack
	for( int i = 0; i < MAX_WEAPON_SLOTS; i++ )
	{
		if( m_rgpPlayerItems[ i ] )
		{
			CBasePlayerWeapon *pPlayerItem = m_rgpPlayerItems[ i ];

			while( pPlayerItem )
			{
				if( pPlayerItem->IsPredicted() )
				{
					pPlayerItem->m_flNextPrimaryAttack = max( pPlayerItem->m_flNextPrimaryAttack - gpGlobals->frametime, -1.0f );
					pPlayerItem->m_flNextSecondaryAttack = max( pPlayerItem->m_flNextSecondaryAttack - gpGlobals->frametime, -0.001f );

					if( pPlayerItem->m_flTimeWeaponIdle != 1000 )
					{
						pPlayerItem->m_flTimeWeaponIdle = max( pPlayerItem->m_flTimeWeaponIdle - gpGlobals->frametime, -0.001f );
					}

					if( pPlayerItem->pev->fuser1 != 1000 )
					{
						pPlayerItem->pev->fuser1 = max( pPlayerItem->pev->fuser1 - gpGlobals->frametime, -0.001f );
					}

					pPlayerItem->DecrementTimers( gpGlobals->frametime );

					// Only decrement if not flagged as NO_DECREMENT
					//					if ( gun->m_flPumpTime != 1000 )
					//	{
					//		gun->m_flPumpTime	= max( gun->m_flPumpTime - gpGlobals->frametime, -0.001 );
					//	}

				}

				pPlayerItem = pPlayerItem->m_pNext;
			}
		}
	}

	m_flNextAttack -= gpGlobals->frametime;
	if( m_flNextAttack < -0.001 )
		m_flNextAttack = -0.001;

	if( m_flNextAmmoBurn != 1000 )
	{
		m_flNextAmmoBurn -= gpGlobals->frametime;

		if( m_flNextAmmoBurn < -0.001 )
			m_flNextAmmoBurn = -0.001;
	}

	if( m_flAmmoStartCharge != 1000 )
	{
		m_flAmmoStartCharge -= gpGlobals->frametime;

		if( m_flAmmoStartCharge < -0.001 )
			m_flAmmoStartCharge = -0.001;
	}
#endif

	// Track button info so we can detect 'pressed' and 'released' buttons next frame
	m_afButtonLast = GetButtons().Get();
}
void CBasePlayer::PreThink()
{
	const int buttonsChanged = ( m_afButtonLast ^ GetButtons().Get() );	// These buttons have changed this frame

	// Debounced button codes for pressed/released
	// UNDONE: Do we need auto-repeat?
	m_afButtonPressed = buttonsChanged & GetButtons().Get();		// The changed ones still down are "pressed"
	m_afButtonReleased = buttonsChanged & ( ~GetButtons().Get() );	// The ones not down are "released"

	g_pGameRules->PlayerThink( this );

	bool bCheckVehicles = true;

#if USE_ANGELSCRIPT
	uint32_t uiFlags = PreThinkFlag::NONE;

	CallGlobalEvent( g_PlayerPreThinkEvent, CallFlag::NONE, this, &uiFlags );

	bCheckVehicles = !( uiFlags & PreThinkFlag::SKIP_VEHICLES );
#endif

	if( g_fGameOver )
		return;         // intermission or finale

	UTIL_MakeVectors( GetViewAngle() );             // is this still used?

	ItemPreFrame();
	WaterMove();

	if( g_pGameRules && g_pGameRules->FAllowFlashlight() )
		m_iHideHUD &= ~HIDEHUD_FLASHLIGHT;
	else
		m_iHideHUD |= HIDEHUD_FLASHLIGHT;


	// JOHN: checks if new client data (for HUD and view control) needs to be sent to the client
	UpdateClientData();

	CheckTimeBasedDamage();

	CheckSuitUpdate();

	// Observer Button Handling
	if( IsObserver() )
	{
		Observer_HandleButtons();
		Observer_CheckTarget();
		Observer_CheckProperties();
		SetImpulse( 0 );
		return;
	}

	if( GetDeadFlag() >= DEAD_DYING )
	{
		PlayerDeathThink();
		return;
	}

	// So the correct flags get sent to client asap.
	//
	if( m_afPhysicsFlags & PFLAG_ONTRAIN )
		GetFlags() |= FL_ONTRAIN;
	else
		GetFlags().ClearFlags( FL_ONTRAIN );

	if( bCheckVehicles )
	{
#if USE_OPFOR
	//We're on a rope. - Solokiller
	if( m_afPhysicsFlags & PFLAG_ONROPE && m_pRope )
	{
		SetAbsVelocity( g_vecZero );

		const Vector vecAttachPos = m_pRope->GetAttachedObjectsPosition();

		SetAbsOrigin( vecAttachPos );

		Vector vecForce;

		/*
		//TODO: This causes sideways acceleration that doesn't occur in Op4. - Solokiller
		//TODO: should be IN_MOVERIGHT and IN_MOVELEFT - Solokiller
		if( GetButtons().Any( IN_DUCK ) )
		{
			vecForce.x = gpGlobals->v_right.x;
			vecForce.y = gpGlobals->v_right.y;
			vecForce.z = 0;
			
			m_pRope->ApplyForceFromPlayer( vecForce );
		}

		if( GetButtons().Any( IN_JUMP ) )
		{
			vecForce.x = -gpGlobals->v_right.x;
			vecForce.y = -gpGlobals->v_right.y;
			vecForce.z = 0;
			m_pRope->ApplyForceFromPlayer( vecForce );
		}
		*/

		//Determine if any force should be applied to the rope, or if we should move around. - Solokiller
		if( GetButtons().Any( IN_BACK | IN_FORWARD ) )
		{
			if( ( gpGlobals->v_forward.x * gpGlobals->v_forward.x + 
				gpGlobals->v_forward.y * gpGlobals->v_forward.y - 
				gpGlobals->v_forward.z * gpGlobals->v_forward.z ) <= 0.0 )
			{
				if( m_bIsClimbing )
				{
					const float flDelta = gpGlobals->time - m_flLastClimbTime;
					m_flLastClimbTime = gpGlobals->time;
					if( GetButtons().Any( IN_FORWARD ) )
					{
						if( gpGlobals->v_forward.z < 0.0 )
						{
							if( !m_pRope->MoveDown( flDelta ) )
							{
								//Let go of the rope, detach. - Solokiller
								SetMoveType( MOVETYPE_WALK );
								SetSolidType( SOLID_SLIDEBOX );

								m_afPhysicsFlags &= ~PFLAG_ONROPE;
								m_pRope->DetachObject();
								m_pRope = nullptr;
								m_bIsClimbing = false;
							}
						}
						else
						{
							m_pRope->MoveUp( flDelta );
						}
					}
					if( GetButtons().Any( IN_BACK ) )
					{
						if( gpGlobals->v_forward.z < 0.0 )
						{
							m_pRope->MoveUp( flDelta );
						}
						else if( !m_pRope->MoveDown( flDelta ) )
						{
							//Let go of the rope, detach. - Solokiller
							SetMoveType( MOVETYPE_WALK );
							SetSolidType( SOLID_SLIDEBOX );
							m_afPhysicsFlags &= ~PFLAG_ONROPE;
							m_pRope->DetachObject();
							m_pRope = nullptr;
							m_bIsClimbing = false;
						}
					}
				}
				else
				{
					m_bIsClimbing = true;
					m_flLastClimbTime = gpGlobals->time;
				}
			}
			else
			{
				vecForce.x = gpGlobals->v_forward.x;
				vecForce.y = gpGlobals->v_forward.y;
				vecForce.z = 0.0;
				if( GetButtons().Any( IN_BACK ) )
				{
					vecForce.x = -gpGlobals->v_forward.x;
					vecForce.y = -gpGlobals->v_forward.y;
					vecForce.z = 0;
				}
				m_pRope->ApplyForceFromPlayer( vecForce );
				m_bIsClimbing = false;
			}
		}
		else
		{
			m_bIsClimbing = false;
		}

		if( m_afButtonPressed & IN_JUMP )
		{
			//We've jumped off the rope, give us some momentum - Solokiller
			SetMoveType( MOVETYPE_WALK );
			SetSolidType( SOLID_SLIDEBOX );
			this->m_afPhysicsFlags &= ~PFLAG_ONROPE;

			Vector vecDir = gpGlobals->v_up * 165.0 + gpGlobals->v_forward * 150.0;

			Vector vecVelocity = m_pRope->GetAttachedObjectsVelocity() * 2;

			vecVelocity.NormalizeInPlace();

			vecVelocity = vecVelocity * 200;

			SetAbsVelocity( vecVelocity + vecDir );

			m_pRope->DetachObject();
			m_pRope = nullptr;
			m_bIsClimbing = false;
		}
		return;
	}
#endif

		// Train speed control
		if( m_afPhysicsFlags & PFLAG_ONTRAIN )
		{
			CBaseEntity *pTrain = GetGroundEntity();

			//To match original behavior, Instance returns the world if entity is null - Solokiller
			if( !pTrain )
				pTrain = CWorld::GetInstance();

			float vel;

			if( !pTrain )
			{
				TraceResult trainTrace;
				// Maybe this is on the other side of a level transition
				UTIL_TraceLine( GetAbsOrigin(), GetAbsOrigin() + Vector( 0, 0, -38 ), ignore_monsters, ENT( pev ), &trainTrace );

				// HACKHACK - Just look for the func_tracktrain classname
				if( trainTrace.flFraction != 1.0 && trainTrace.pHit )
					pTrain = CBaseEntity::Instance( trainTrace.pHit );


				if( !pTrain || !( pTrain->ObjectCaps() & FCAP_DIRECTIONAL_USE ) || !pTrain->OnControls( this ) )
				{
					//ALERT( at_error, "In train mode with no train!\n" );
					m_afPhysicsFlags &= ~PFLAG_ONTRAIN;
					m_iTrain = TRAIN_NEW | TRAIN_OFF;
					return;
				}
			}
			else if( !GetFlags().Any( FL_ONGROUND ) || pTrain->GetSpawnFlags().Any( SF_TRACKTRAIN_NOCONTROL ) || ( GetButtons().Any( IN_MOVELEFT | IN_MOVERIGHT ) ) )
			{
				// Turn off the train if you jump, strafe, or the train controls go dead
				m_afPhysicsFlags &= ~PFLAG_ONTRAIN;
				m_iTrain = TRAIN_NEW | TRAIN_OFF;
				return;
			}

			SetAbsVelocity( g_vecZero );
			vel = 0;
			if( m_afButtonPressed & IN_FORWARD )
			{
				vel = 1;
				pTrain->Use( this, this, USE_SET, ( float ) vel );
			}
			else if( m_afButtonPressed & IN_BACK )
			{
				vel = -1;
				pTrain->Use( this, this, USE_SET, ( float ) vel );
			}

			if( vel )
			{
				m_iTrain = TrainSpeed( pTrain->GetSpeed(), pTrain->GetImpulse() );
				m_iTrain |= TRAIN_ACTIVE | TRAIN_NEW;
			}

		}
		else if( m_iTrain & TRAIN_ACTIVE )
			m_iTrain = TRAIN_NEW; // turn off train
	}

	if( GetButtons().Any( IN_JUMP ) )
	{
		// If on a ladder, jump off the ladder
		// else Jump
		Jump();
	}


	// If trying to duck, already ducked, or in the process of ducking
	if( GetButtons().Any( IN_DUCK ) || GetFlags().Any( FL_DUCKING ) || ( m_afPhysicsFlags & PFLAG_DUCKING ) )
		Duck();

	if( !GetFlags().Any( FL_ONGROUND ) )
	{
		m_flFallVelocity = -GetAbsVelocity().z;
	}

	// StudioFrameAdvance( );//!!!HACKHACK!!! Can't be hit by traceline when not animating?

	// Clear out ladder pointer
	m_hEnemy = NULL;

	if( m_afPhysicsFlags & PFLAG_ONBARNACLE )
	{
		SetAbsVelocity( g_vecZero );
	}
}
// simplified version of the one in CASW_Weapon, don't worry about ammo or clips for the welder
void CASW_Weapon_Welder::BaseItemPostFrame()
{
	//CBasePlayer *pOwner = GetCommander();
	CASW_Marine* pOwner = GetMarine();
	
	if (!pOwner)
		return;

	bool bAttack1, bAttack2, bReload, bOldReload, bOldAttack1;
	GetButtons(bAttack1, bAttack2, bReload, bOldReload, bOldAttack1 );

	// check for automatic welding
	if ( m_bShotDelayed )
	{
		if ( m_iAutomaticWeldDirection > 0 )
		{
			bAttack1 = true;
			//Msg( "doing automatic attack1 since bShotDelayed\n" );
		}
		else if ( m_iAutomaticWeldDirection < 0 )
		{
			bAttack2 = true;
			//Msg( "doing automatic attack2 since bShotDelayed\n" );
		}
	}

	//Track the duration of the fire
	//FIXME: Check for IN_ATTACK2 as well?
	//FIXME: What if we're calling ItemBusyFrame?
	m_fFireDuration = bAttack1 ? ( m_fFireDuration + gpGlobals->frametime ) : 0.0f;

	if ( UsesClipsForAmmo1() )
	{
		CheckReload();
	}

	bool bFired = false;

	if ( bAttack2 && m_flNextSecondaryAttack <= gpGlobals->curtime )
	{
		bFired = true;
		SecondaryAttack();
	}
	
	if ( !bFired && bAttack1 && m_flNextPrimaryAttack <= gpGlobals->curtime )
	{				
		// If the firing button was just pressed, reset the firing time
		if ( pOwner && bAttack1 )
		{
			m_flNextPrimaryAttack = gpGlobals->curtime;
		}

		PrimaryAttack();
	}

	if ( !bAttack1 && !bAttack2 )
		m_bIsFiring = false;

	// -----------------------
	//  No buttons down
	// -----------------------
	if (!(bAttack1 || bAttack2 || bReload))
	{
		// no fire buttons down or reloading
		if ( !ReloadOrSwitchWeapons() && !m_bInReload )
		{
			WeaponIdle();
		}
	}
}
// check player or marine commander's buttons for firing/reload/etc
void CASW_Weapon::ItemPostFrame( void )
{
	//CBasePlayer *pOwner = GetCommander();
	CASW_Marine* pOwner = GetMarine();
	if (!pOwner)
		return;

	bool bThisActive = ( pOwner && pOwner->GetActiveWeapon() == this );

	bool bAttack1, bAttack2, bReload, bOldReload, bOldAttack1;
	GetButtons(bAttack1, bAttack2, bReload, bOldReload, bOldAttack1 );

	if ( pOwner->IsHacking() )
	{
		bThisActive = bAttack1 = bAttack2 = bReload = false;
	}

	// check for clearing our weapon switching bool
	if (m_bSwitchingWeapons && gpGlobals->curtime > m_flNextPrimaryAttack)
	{
		m_bSwitchingWeapons = false;
	}

	// check for clearing our firing bool from reloading
	if (m_bInReload && gpGlobals->curtime > m_fReloadClearFiringTime)
	{
		ClearIsFiring();
	}

	if ( m_bShotDelayed && gpGlobals->curtime > m_flDelayedFire )
	{
		DelayedAttack();
	}

	if ( UsesClipsForAmmo1() )
	{
		CheckReload();
	}

	bool bFired = false;
	if ( bThisActive )
	{
		//Track the duration of the fire
		//FIXME: Check for IN_ATTACK2 as well?
		//FIXME: What if we're calling ItemBusyFrame?
		m_fFireDuration = bAttack1 ? ( m_fFireDuration + gpGlobals->frametime ) : 0.0f;

		if (bAttack2 && (m_flNextSecondaryAttack <= gpGlobals->curtime) && gpGlobals->curtime > pOwner->m_fFFGuardTime)
		{
			if ( SecondaryAttackUsesPrimaryAmmo() )
			{
				if ( !IsMeleeWeapon() &&  
					(( UsesClipsForAmmo1() && !(this->PrimaryAmmoLoaded())) || ( !UsesClipsForAmmo1() && pOwner->GetAmmoCount(m_iPrimaryAmmoType)<=0 )) )
				{
					HandleFireOnEmpty();
				}
				else
				{
					bFired = true;
					SecondaryAttack();

#ifndef CLIENT_DLL
					if ( pOwner->IsInhabited() )
					{
						IGameEvent * event = gameeventmanager->CreateEvent( "player_alt_fire" );
						if ( event )
						{
							CASW_Player *pPlayer = pOwner->GetCommander();
							event->SetInt( "userid", ( pPlayer ? pPlayer->GetUserID() : 0 ) );
							gameeventmanager->FireEvent( event );
						}
					}
#endif
				}
			}
			else if ( UsesSecondaryAmmo() &&  
				 ( ( UsesClipsForAmmo2() && m_iClip2 <= 0 ) ||
				   ( !UsesClipsForAmmo2() && pOwner->GetAmmoCount( m_iSecondaryAmmoType ) <= 0 ) ) )
			{
				if ( m_flNextEmptySoundTime < gpGlobals->curtime )
				{
					WeaponSound( EMPTY );
					m_flNextSecondaryAttack = m_flNextEmptySoundTime = gpGlobals->curtime + 0.5;
				}
			}		
			else
			{
				bFired = true;
				SecondaryAttack();

#ifndef CLIENT_DLL
				if ( pOwner->IsInhabited() )
				{
					IGameEvent * event = gameeventmanager->CreateEvent( "player_alt_fire" );
					if ( event )
					{
						CASW_Player *pPlayer = pOwner->GetCommander();
						event->SetInt( "userid", ( pPlayer ? pPlayer->GetUserID() : 0 ) );
						gameeventmanager->FireEvent( event );
					}
				}
#endif

				// Secondary ammo doesn't have a reload animation
				// this code makes secondary ammo come from nowhere!
				/*
				if ( UsesClipsForAmmo2() )
				{
					// reload clip2 if empty
					if (m_iClip2 < 1)
					{
						pOwner->RemoveAmmo( 1, m_iSecondaryAmmoType );
						m_iClip2 = m_iClip2 + 1;
					}
				}*/
			}
		}
		
		if ( !bFired && bAttack1 && (m_flNextPrimaryAttack <= gpGlobals->curtime) && gpGlobals->curtime > pOwner->m_fFFGuardTime)
		{
			// Clip empty? Or out of ammo on a no-clip weapon?
			if ( !IsMeleeWeapon() &&  
				(( UsesClipsForAmmo1() && !(this->PrimaryAmmoLoaded())) || ( !UsesClipsForAmmo1() && pOwner->GetAmmoCount(m_iPrimaryAmmoType)<=0 )) )
			{
				HandleFireOnEmpty();
			}
			else if (pOwner->GetWaterLevel() == 3 && m_bFiresUnderwater == false)
			{
				// This weapon doesn't fire underwater
				WeaponSound(EMPTY);
				m_flNextPrimaryAttack = gpGlobals->curtime + 0.2;
				return;
			}
			else
			{
				//NOTENOTE: There is a bug with this code with regards to the way machine guns catch the leading edge trigger
				//			on the player hitting the attack key.  It relies on the gun catching that case in the same frame.
				//			However, because the player can also be doing a secondary attack, the edge trigger may be missed.
				//			We really need to hold onto the edge trigger and only clear the condition when the gun has fired its
				//			first shot.  Right now that's too much of an architecture change -- jdw
				
				// If the firing button was just pressed, reset the firing time
				if ( pOwner && bAttack1 )
				{
	#ifdef CLIENT_DLL
					//Msg("[Client] setting nextprimaryattack to now %f\n", gpGlobals->curtime);
	#else
					//Msg("[Server] setting nextprimaryattack to now %f\n", gpGlobals->curtime);
	#endif
					 m_flNextPrimaryAttack = gpGlobals->curtime;
				}
				PrimaryAttack();
			}
		}
	}

	if (!bAttack1)	// clear our firing var if we don't have the attack button held down (not totally accurate since firing could continue for some time after pulling the trigger, but it's good enough for our purposes)
	{
		m_bIsFiring = false;		// NOTE: Only want to clear primary fire IsFiring bool here (i.e. don't call ClearIsFiring as that'll clear secondary fire too, in subclasses that have it)
		if ( bOldAttack1 )
		{
			OnStoppedFiring();
		}
	}

	// -----------------------
	//  Reload pressed / Clip Empty
	// -----------------------
	if ( bReload && UsesClipsForAmmo1())	
	{
		if ( m_bInReload ) 
		{
			// todo: check for a fast reload
			//Msg("Check for fast reload\n");
		}
		else
		{
			// reload when reload is pressed, or if no buttons are down and weapon is empty.
			Reload();
			m_fFireDuration = 0.0f;
		}
	}

	// -----------------------
	//  No buttons down
	// -----------------------
	if (!(bAttack1 || bAttack2 || bReload))
	{
		// no fire buttons down or reloading
		if ( !ReloadOrSwitchWeapons() && ( m_bInReload == false ) )
		{
			WeaponIdle();
		}
	}
}
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();
		}
	}
}
void CASW_Weapon::ItemBusyFrame( void )
{
	CASW_Marine* pMarine = GetMarine();
	if ( !pMarine )
		return;

	bool bAttack1, bAttack2, bReload, bOldReload, bOldAttack1;
	GetButtons(bAttack1, bAttack2, bReload, bOldReload, bOldAttack1 );

	// check for clearing our weapon switching bool
	if (m_bSwitchingWeapons && gpGlobals->curtime > m_flNextPrimaryAttack)
	{
		m_bSwitchingWeapons = false;
	}

	// check for clearing our firing bool from reloading
	if (m_bInReload && gpGlobals->curtime > m_fReloadClearFiringTime)
	{
		ClearIsFiring();
	}

	if ( (bReload && !bOldReload) && UsesClipsForAmmo1() && asw_fast_reload_enabled.GetBool() )
	{
		if ( m_bInReload ) 
		{
			// check for a fast reload
			//Msg("%f Check for fast reload while busy\n", gpGlobals->curtime);
			if (gpGlobals->curtime >= m_fFastReloadStart && gpGlobals->curtime <= m_fFastReloadEnd)
			{
				// todo: reduce next attack time
				m_fFastReloadEnd = 0;
				m_fFastReloadStart = 0;

				CBaseCombatCharacter *pOwner = GetOwner();
				if ( pOwner )
				{
					float flSucceedDelay = gpGlobals->curtime + 0.5f;
					pOwner->SetNextAttack( flSucceedDelay );
					m_flNextPrimaryAttack = m_flNextSecondaryAttack = flSucceedDelay;
				}

				// TODO: hook up anim
				//pMarine->DoAnimationEvent( PLAYERANIMEVENT_RELOAD_SUCCEED );

				DispatchParticleEffect( "fast_reload", PATTACH_POINT_FOLLOW, this, "muzzle" );
				pMarine->m_flPreventLaserSightTime = gpGlobals->curtime + 2.5f;

#ifdef GAME_DLL
				pMarine->m_nFastReloadsInARow++;

				IGameEvent * event = gameeventmanager->CreateEvent( "fast_reload" );
				if ( event )
				{
					event->SetInt( "marine", pMarine->entindex() );
					event->SetInt( "reloads", pMarine->m_nFastReloadsInARow );
					gameeventmanager->FireEvent( event );
				}

				if ( pMarine->m_nFastReloadsInARow >= 4 && pMarine->IsInhabited() )
				{
					if ( pMarine->GetMarineResource() )
					{
						pMarine->GetMarineResource()->m_bDidFastReloadsInARow = true;
					}

					if ( pMarine->GetCommander() )
					{
						pMarine->GetCommander()->AwardAchievement( ACHIEVEMENT_ASW_FAST_RELOADS_IN_A_ROW );
					}
				}
#endif
				CSoundParameters params;
				if ( !GetParametersForSound( "FastReload.Success", params, NULL ) )
					return;

				EmitSound_t playparams(params);
				playparams.m_nPitch = params.pitch;

				CASW_Player *pPlayer = GetCommander();
				if ( pPlayer )
				{
					CSingleUserRecipientFilter filter( pMarine->GetCommander() );
					if ( IsPredicted() && CBaseEntity::GetPredictionPlayer() )
					{
						filter.UsePredictionRules();
					}
					EmitSound(filter, entindex(), playparams);
				}
				
				//Msg("%f RELOAD SUCCESS! - bAttack1 = %d, bOldAttack1 = %d\n", gpGlobals->curtime, bAttack1, bOldAttack1 );
				//Msg( "S: %f - %f - %f RELOAD SUCCESS! -- Progress = %f\n", gpGlobals->curtime, fFastStart, fFastEnd, flProgress );
#ifdef GAME_DLL				
				pMarine->GetMarineSpeech()->PersonalChatter(CHATTER_SELECTION);
#endif
				m_bFastReloadSuccess = true;
				m_bFastReloadFailure = false;
			}
			else if (m_fFastReloadStart != 0)
			{
				CSoundParameters params;
				if ( !GetParametersForSound( "FastReload.Miss", params, NULL ) )
					return;

				EmitSound_t playparams(params);
				playparams.m_nPitch = params.pitch;

				CASW_Player *pPlayer = GetCommander();
				if ( pPlayer )
				{
					CSingleUserRecipientFilter filter( pMarine->GetCommander() );
					if ( IsPredicted() && CBaseEntity::GetPredictionPlayer() )
					{
						filter.UsePredictionRules();
					}
					EmitSound(filter, entindex(), playparams);
				}
				//Msg("%f RELOAD MISSED! - bAttack1 = %d, bOldAttack1 = %d\n", gpGlobals->curtime, bAttack1, bOldAttack1 );
				//Msg( "S: %f - %f - %f RELOAD MISSED! -- Progress = %f\n", gpGlobals->curtime, fFastStart, fFastEnd, flProgress );
				m_fFastReloadEnd = 0;
				m_fFastReloadStart = 0;

				CBaseCombatCharacter *pOwner = GetOwner();
				if ( pOwner )
				{
					float flMissDelay = MAX( gpGlobals->curtime + 2.0f, m_flNextPrimaryAttack + 1.0f );
					pOwner->SetNextAttack( flMissDelay );
					m_flNextPrimaryAttack = m_flNextSecondaryAttack = flMissDelay;
					m_flReloadFailTime = m_flNextPrimaryAttack - gpGlobals->curtime;
				}

				// TODO: hook up anim
				//pMarine->DoAnimationEvent( PLAYERANIMEVENT_RELOAD_FAIL );

#ifdef GAME_DLL
				pMarine->m_nFastReloadsInARow = 0;
#endif

				DispatchParticleEffect( "reload_fail", PATTACH_POINT_FOLLOW, this, "muzzle" );

#ifdef GAME_DLL	
				pMarine->GetMarineSpeech()->PersonalChatter(CHATTER_PAIN_SMALL);
#endif
				m_bFastReloadSuccess = false;
				m_bFastReloadFailure = true;

			}
		}
	}

#ifdef CLIENT_DLL	
	if ( m_bInReload ) 
	{
		float fStart = m_fReloadStart;
		float fNext = MAX( m_flNextPrimaryAttack, GetOwner() ? GetOwner()->GetNextAttack() : 0 );
		float fTotalTime = fNext - fStart;
		if (fTotalTime <= 0)
			fTotalTime = 0.1f;

		m_fReloadProgress = (gpGlobals->curtime - fStart) / fTotalTime;
	}
	else
	{
		m_fReloadProgress = 0;
	}
	//Msg( "S: %f Reload Progress = %f\n", gpGlobals->curtime, m_fReloadProgress );
#endif //CLIENT_DLL
}
//=========================================================
// UpdatePlayerSound - updates the position of the player's
// reserved sound slot in the sound list.
//=========================================================
void CBasePlayer::UpdatePlayerSound()
{
	int iBodyVolume;
	int iVolume;
	CSound *pSound = CSoundEnt::SoundPointerForIndex( CSoundEnt::ClientSoundIndex( this ) );

	if( !pSound )
	{
		ALERT( at_console, "Client lost reserved sound!\n" );
		return;
	}

	pSound->m_iType = bits_SOUND_NONE;

	// now calculate the best target volume for the sound. If the player's weapon
	// is louder than his body/movement, use the weapon volume, else, use the body volume.

	if( GetFlags().Any( FL_ONGROUND ) )
	{
		iBodyVolume = GetAbsVelocity().Length();

		// clamp the noise that can be made by the body, in case a push trigger,
		// weapon recoil, or anything shoves the player abnormally fast. 
		if( iBodyVolume > 512 )
		{
			iBodyVolume = 512;
		}
	}
	else
	{
		iBodyVolume = 0;
	}

	if( GetButtons().Any( IN_JUMP ) )
	{
		iBodyVolume += 100;
	}

	// convert player move speed and actions into sound audible by monsters.
	if( m_iWeaponVolume > iBodyVolume )
	{
		m_iTargetVolume = m_iWeaponVolume;

		// OR in the bits for COMBAT sound if the weapon is being louder than the player. 
		pSound->m_iType |= bits_SOUND_COMBAT;
	}
	else
	{
		m_iTargetVolume = iBodyVolume;
	}

	// decay weapon volume over time so bits_SOUND_COMBAT stays set for a while
	m_iWeaponVolume -= 250 * gpGlobals->frametime;

	// if target volume is greater than the player sound's current volume, we paste the new volume in 
	// immediately. If target is less than the current volume, current volume is not set immediately to the
	// lower volume, rather works itself towards target volume over time. This gives monsters a much better chance
	// to hear a sound, especially if they don't listen every frame.
	iVolume = pSound->m_iVolume;

	if( m_iTargetVolume > iVolume )
	{
		iVolume = m_iTargetVolume;
	}
	else if( iVolume > m_iTargetVolume )
	{
		iVolume -= 250 * gpGlobals->frametime;

		if( iVolume < m_iTargetVolume )
		{
			iVolume = 0;
		}
	}

	if( m_fNoPlayerSound )
	{
		// debugging flag, lets players move around and shoot without monsters hearing.
		iVolume = 0;
	}

	if( gpGlobals->time > m_flStopExtraSoundTime )
	{
		// since the extra sound that a weapon emits only lasts for one client frame, we keep that sound around for a server frame or two 
		// after actual emission to make sure it gets heard.
		m_iExtraSoundTypes = 0;
	}

	if( pSound )
	{
		pSound->m_vecOrigin = GetAbsOrigin();
		pSound->m_iType |= ( bits_SOUND_PLAYER | m_iExtraSoundTypes );
		pSound->m_iVolume = iVolume;
	}

	// keep track of virtual muzzle flash
	m_iWeaponFlash -= 256 * gpGlobals->frametime;
	if( m_iWeaponFlash < 0 )
		m_iWeaponFlash = 0;

	//UTIL_MakeVectors ( GetAbsAngles() );
	//gpGlobals->v_forward.z = 0;

	// Below are a couple of useful little bits that make it easier to determine just how much noise the 
	// player is making. 
	// UTIL_ParticleEffect ( GetAbsOrigin() + gpGlobals->v_forward * iVolume, g_vecZero, 255, 25 );
	//ALERT ( at_console, "%d/%d\n", iVolume, m_iTargetVolume );
}
void CBasePlayer::PlayerDeathThink()
{
	if( GetFlags().Any( FL_ONGROUND ) )
	{
		const float flForward = GetAbsVelocity().Length() - 20;
		if( flForward <= 0 )
			SetAbsVelocity( g_vecZero );
		else
			SetAbsVelocity( flForward * GetAbsVelocity().Normalize() );
	}

	if( HasWeapons() )
	{
		// we drop the guns here because weapons that have an area effect and can kill their user
		// will sometimes crash coming back from CBasePlayer::Killed() if they kill their owner because the
		// player class sometimes is freed. It's safer to manipulate the weapons once we know
		// we aren't calling into any of their code anymore through the player pointer.
		PackDeadPlayerItems();
	}


	if( GetModelIndex() && ( !m_fSequenceFinished ) && ( GetDeadFlag() == DEAD_DYING ) )
	{
		StudioFrameAdvance();

		m_iRespawnFrames++;				// Note, these aren't necessarily real "frames", so behavior is dependent on # of client movement commands
		if( m_iRespawnFrames < 120 )   // Animations should be no longer than this
			return;
	}

	// once we're done animating our death and we're on the ground, we want to set movetype to None so our dead body won't do collisions and stuff anymore
	// this prevents a bug where the dead body would go to a player's head if he walked over it while the dead player was clicking their button to respawn
	if( GetMoveType() != MOVETYPE_NONE && GetFlags().Any( FL_ONGROUND ) )
		SetMoveType( MOVETYPE_NONE );

	if( GetDeadFlag() == DEAD_DYING )
		SetDeadFlag( DEAD_DEAD );

	StopAnimation();

	GetEffects() |= EF_NOINTERP;
	SetFrameRate( 0.0 );

	const bool fAnyButtonDown = ( GetButtons().Any( ~IN_SCORE ) ) != 0;

	// wait for all buttons released
	if( GetDeadFlag() == DEAD_DEAD )
	{
		if( fAnyButtonDown )
			return;

		if( g_pGameRules->FPlayerCanRespawn( this ) )
		{
			m_fDeadTime = gpGlobals->time;
			SetDeadFlag( DEAD_RESPAWNABLE );
		}

		return;
	}

	// if the player has been dead for one second longer than allowed by forcerespawn, 
	// forcerespawn isn't on. Send the player off to an intermission camera until they 
	// choose to respawn.
	if( g_pGameRules->IsMultiplayer() && ( gpGlobals->time > ( m_fDeadTime + 6 ) ) && !( m_afPhysicsFlags & PFLAG_OBSERVER ) )
	{
		// go to dead camera. 
		StartDeathCam();
	}

	if( IsObserver() )	// player is in spectator mode
		return;

	// wait for any button down,  or mp_forcerespawn is set and the respawn time is up
	if( !fAnyButtonDown
		&& !( g_pGameRules->IsMultiplayer() && forcerespawn.value > 0 && ( gpGlobals->time > ( m_fDeadTime + 5 ) ) ) )
		return;

	GetButtons().ClearAll();
	m_iRespawnFrames = 0;

	//ALERT(at_console, "Respawn\n");

	g_pGameRules->PlayerRespawn( this, !( m_afPhysicsFlags & PFLAG_OBSERVER ) );// don't copy a corpse if we're in deathcam.
	SetNextThink( -1 );
}
Exemple #17
0
/*
==============================
SUB_UseTargets

If self.delay is set, a DelayedUse entity will be created that will actually
do the SUB_UseTargets after that many seconds have passed.

Removes all entities with a targetname that match self.killtarget,
and removes them, so some events can remove other triggers.

Search for (string)targetname in all entities that
match (string)self.target and call their .use function (if they have one)

==============================
*/
void CBaseDelay::SUB_UseTargets( CBaseEntity *pActivator, USE_TYPE useType, float value )
{
	//
	// exit immediatly if we don't have a target or kill target
	//
	if( !HasTarget() && !m_iszKillTarget )
		return;

	//
	// check for a delay
	//
	if( m_flDelay != 0 )
	{
		// create a temp object to fire at a later time
		auto pTemp = static_cast<CBaseDelay*>( UTIL_CreateNamedEntity( "DelayedUse" ) );

		pTemp->SetNextThink( gpGlobals->time + m_flDelay );

		pTemp->SetThink( &CBaseDelay::DelayThink );

		// Save the useType
		pTemp->GetButtons().Set( ( int ) useType );
		pTemp->m_iszKillTarget = m_iszKillTarget;
		pTemp->m_flDelay = 0; // prevent "recursion"
		pTemp->SetTarget( GetTarget() );

		// HACKHACK
		// This wasn't in the release build of Half-Life.  We should have moved m_hActivator into this class
		// but changing member variable hierarchy would break save/restore without some ugly code.
		// This code is not as ugly as that code
		if( pActivator && pActivator->IsPlayer() )		// If a player activates, then save it
		{
			pTemp->SetOwner( pActivator );
		}
		else
		{
			pTemp->SetOwner( NULL );
		}

		return;
	}

	//
	// kill the killtargets
	//

	if( m_iszKillTarget )
	{
		CBaseEntity* pKillTarget = nullptr;

		ALERT( at_aiconsole, "KillTarget: %s\n", STRING( m_iszKillTarget ) );
		while( ( pKillTarget = UTIL_FindEntityByTargetname( pKillTarget, STRING( m_iszKillTarget ) ) ) != nullptr )
		{
			UTIL_Remove( pKillTarget );

			ALERT( at_aiconsole, "killing %s\n", pKillTarget->GetClassname() );
		}
	}

	//
	// fire targets
	//
	if( HasTarget() )
	{
		FireTargets( GetTarget(), pActivator, this, useType, value );
	}
}
Exemple #18
0
int main(void)
{
	// Initialize I/O
	DDRB  = 0x3e; // 00111110
	PORTB = 0x01; // 00000001
	DDRC  = 0x20; // 00100000
	PORTC = 0x03; // 00000011
	DDRD  = 0xff; // 11111111
	PORTD = 0xff; // 11111111

	// Load saved state, if any
	Load();

	// Setup the display timer...
	
	// prescaler 1/8; at 1MHz system clock, this gives us an overflow
	// at 488 Hz, providing a per-digit refresh rate of 97.6 Hz.
	TCCR0A = 0;
	TCCR0B = (1<<CS01); 

	// Output compare value B - controls blanking.
	// In full brightness mode, we'll make this happen immediately before the refresh,
	// In lower brightness modes, we'll make it happen sooner.
	OCR0A = pgm_read_byte(&brighttable[bright]);

	// Enable overflow and compare match interrupts
    TIMSK0 = (1<<TOIE0) | (1<<OCIE0A);


	// Setup the RTC...
	gMin = 0;
	gSec = 0;

    // select asynchronous operation of Timer2
	ASSR = (1<<AS2);        

	// select prescaler: 32.768 kHz / 128 = 1 sec between each overflow
	TCCR2A = 0;
    TCCR2B = (1<<CS22) | (1<<CS20);             
	
    // wait for TCN2UB and TCR2UB to be cleared
	while((ASSR & 0x01) | (ASSR & 0x04));      
	 
    // clear interrupt-flags
	TIFR2 = 0xFF;           
    

	// init the state machine
	enum State state = ST_TIME;
	enum State prevstate = ST_TIME;
	uint8_t remaining = 0;
	uint8_t cmode = 0;

    // Enable interrupts
	sei();

	// Do some stuff
	for(;;)
	{
		uint8_t buttons = GetButtons();

		if ((buttons & BUTTON_RIGHT) && (state < ST_BRIGHT)) {
			prevstate = state;
			remaining = count;
			cmode = 0;
			buttons = 0;
			state = ST_RUN_PRIME;
		} 

	newstate:
		switch(state)
		{
		case ST_TIME:
			DisplayNum(stime[0], HIGH_POS, 0, 3);
			display[COLON_POS] = COLON;
			DisplayNum(stime[1], LOW_POS, 0, 0);
			if (buttons & BUTTON_LEFT) {
				state = ST_DELAY;
			} else if (buttons & BUTTON_UP) {
				state = ST_TIME_SET_MINS;
			}
			break;
		case ST_DELAY:
			DisplayNum(delay[0], HIGH_POS, 0, 3);
			display[COLON_POS] = LOWDOT;
			DisplayNum(delay[1], LOW_POS, 0, 0);
			if (buttons & BUTTON_LEFT) {
				state = ST_COUNT;
			} else if (buttons & BUTTON_UP) {
				state = ST_DELAY_SET_MINS;
			}
			break;
		case ST_COUNT:
			DisplayAlnum('\xC6', count, 0);
			if (buttons & BUTTON_LEFT) {
				state = ST_MLU;
			} else if (buttons & BUTTON_UP) {
				state = ST_COUNT_SET;
			}
			break;
		case ST_MLU:
			DisplayAlnum('\xC7', mlu, 0);
			if (buttons & BUTTON_LEFT) {
				state = ST_BRIGHT;
			} else if (buttons & BUTTON_UP) {
				state = ST_MLU_SET;
			}
			break;
/* I'll put this in once there's more than one option ;)
		case ST_OPTIONS:
			display[0] = '\xC0';	// 00111111 = 'O'
			display[1] = '\x8C';	// 01110011 = 'P'
			display[2] = EMPTY;
			display[3] = '0x87';	// 01111000 = 't'
			display[4] = '0x92';	// 01101101 = 'S'
			if (buttons & BUTTON_LEFT) {
				state = ST_TIME;
			} else if (buttons & BUTTON_UP) {
				state = ST_BRIGHT;
			}
			break;
*/
		case ST_BRIGHT:
			DisplayAlnum('\x83', 4 - bright, 0); // 10000011 = 'b'
			if (buttons & BUTTON_LEFT) {
				state = ST_TIME;
			} else if (buttons & BUTTON_UP) {
				bright = (bright - 1) & 3;
				OCR0A = pgm_read_byte(&brighttable[bright]);
			} else if (buttons & BUTTON_RIGHT) {
				Save();
				state = ST_SAVED;
				remaining = 15;
			}
			break;
		case ST_SAVED:
			display[0] = '\x92'; // 01101101 = 'S'
			display[1] = '\x88'; // 01110111 = 'A'
			display[2] = EMPTY;
			display[3] = '\xc1'; // 00111110 = 'V'
			display[4] = '\x86'; // 01111001 = 'E'
			if (--remaining == 0)
				state = ST_BRIGHT;
			break;
		case ST_TIME_SET_MINS:
			DisplayNum(stime[0], HIGH_POS, 0x40, 0);
			display[COLON_POS] = COLON;
			DisplayNum(stime[1], LOW_POS, 0, 0);
			if (EditNum(&stime[0], buttons, 100)) {
				state = ST_TIME_SET_SECS;
			}
			break;
		case ST_TIME_SET_SECS:
			DisplayNum(stime[0], HIGH_POS, 0, 0);
			display[COLON_POS] = COLON;
			DisplayNum(stime[1], LOW_POS, 0x40, 0);
			if (EditNum(&stime[1], buttons, 60)) {
				state = ST_TIME;
			}
			break;
		case ST_DELAY_SET_MINS:
			DisplayNum(delay[0], HIGH_POS, 0x40, 0);
			display[COLON_POS] = LOWDOT;
			DisplayNum(delay[1], LOW_POS, 0, 0);
			if (EditNum(&delay[0], buttons, 100)) {
				state = ST_DELAY_SET_SECS;
			}
			break;
		case ST_DELAY_SET_SECS:
			DisplayNum(delay[0], HIGH_POS, 0, 0);
			display[COLON_POS] = LOWDOT;
			DisplayNum(delay[1], LOW_POS, 0x40, 0);
			if (EditNum(&delay[1], buttons, 60)) {
				state = ST_DELAY;
			}
			break;
		case ST_COUNT_SET:
			DisplayAlnum('\xC6', count, 0x40);
			if (EditNum(&count, buttons, 100)) {
				state = ST_COUNT;
			}
			break;
		case ST_MLU_SET:
			DisplayAlnum('\xC7', mlu, 0x40);
			if (EditNum(&mlu, buttons, 60)) {
				state = ST_MLU;
			}
			break;
		case ST_RUN_PRIME:
			if (mlu > 0) {
				state = ST_MLU_PRIME;
				SHUTTER_ON();
				DisplayAlnum('\xC7', mlu, 0);
			} else {
				InitRun(&state);
				goto newstate;
			}
			break;
		case ST_RUN_AUTO:
			if (gDirection == 0) {
				// time has elapsed.  close the shutter and stop the timer.
				SHUTTER_OFF();
				clock_stop();
	
				if (remaining > 0)
				{
					if (--remaining == 0)
					{
						// we're done.
						state = prevstate;
						break;
					}
				}

				gMin = delay[0];
				gSec = delay[1];
				gDirection = -1;
				state = ST_WAIT;
				clock_start();			
				goto newstate;
			}
			// fall through
		case ST_RUN_MANUAL:
			if (cmode == 0) {
				// time left in this exposure
				DisplayNum(gMin, HIGH_POS, 0, 3);
				DisplayNum(gSec, LOW_POS, 0, 0);
			} else {
				// remaining exposures
				DisplayAlnum('\xC6', remaining, 0);
			}
			display[COLON_POS] = (TCNT2 & 0x80) ? EMPTY : COLON;
			break;
		case ST_MLU_PRIME:
			SHUTTER_OFF();
			gMin = 0;
			gSec = mlu;
			gDirection = -1;
			state = ST_MLU_WAIT;
			clock_start();
			// fall-through
		case ST_MLU_WAIT:
			DisplayAlnum('\xC7', gSec, 0);
			if (gDirection == 0)
			{
				// MLU wait period has elapsed
				clock_stop();
				InitRun(&state);
				goto newstate;
			}
			break;
		case ST_WAIT:
			if (cmode == 0) {
				// wait time
				DisplayNum(gMin, HIGH_POS, 0, 3);
				DisplayNum(gSec, LOW_POS, 0, 0);
			} else {
				// remaining exposures
				DisplayAlnum('\xC6', remaining, 0);
			}
			display[COLON_POS] = (TCNT2 & 0x80) ? EMPTY : LOWDOT;
			if (gDirection == 0)
			{
				// wait period has timed out;
				// stop the timer and start a new cycle
				clock_stop();
				state = ST_RUN_PRIME;
				goto newstate;
			}
			break;
		}

		if (state >= ST_RUN_PRIME) {
			// check keys
			if (buttons & BUTTON_RIGHT) {
				// canceled.
				clock_stop();
				SHUTTER_OFF();

				// if counting up, freeze the count here
				if (state == ST_RUN_MANUAL) {
					stime[0] = gMin;
					stime[1] = gSec;
				}
		
				state = prevstate;
			} else if ((buttons & BUTTON_LEFT) && (count > 1)) {
				// toggle display, time left vs. count left
				cmode = (cmode + 1) & 1;
			} else if (buttons & BUTTON_UP) {
				// adjust brightness
				bright = (bright - 1) & 3;
				OCR0A = pgm_read_byte(&brighttable[bright]);
			}
		}
	
		Sleep(48);	// approx 50ms at 1MHz
 	}
}