예제 #1
0
//-----------------------------------------------------------------------------
// Purpose: Idle updates the position of the build placement model
//-----------------------------------------------------------------------------
void CWeaponBuilder::WeaponIdle( void )
{
	CBaseTFPlayer *pOwner = ToBaseTFPlayer( GetOwner() );
	if ( !pOwner )
		return;

	// If we're in placement mode, update the placement model
	switch( m_iBuildState )
	{
	case BS_PLACING:
	case BS_PLACING_INVALID:
		{
			if ( UpdatePlacement() )
			{
				SetCurrentState( BS_PLACING );
			}
			else
			{
				SetCurrentState( BS_PLACING_INVALID );
			}
		}
		break;

	default:
		break;
	}

	if ( HasWeaponIdleTimeElapsed() )
	{
		SendWeaponAnim( ACT_VM_IDLE );
	}
}
예제 #2
0
//-----------------------------------------------------------------------------
// Purpose: Move the placement model to the current position. Return false if it's an invalid position
//-----------------------------------------------------------------------------
bool CWeaponBuilder::UpdatePlacement( void )
{
	if ( !m_hObjectBeingBuilt )
		return false;

	return m_hObjectBeingBuilt->UpdatePlacement( ToBaseTFPlayer(GetOwner()) );
}
//-----------------------------------------------------------------------------
// New technologies: 
//-----------------------------------------------------------------------------
void CWeaponCombat_ChargeablePlasma::GainedNewTechnology( CBaseTechnology *pTechnology )
{
	BaseClass::GainedNewTechnology( pTechnology );

	CBaseTFPlayer *pPlayer = ToBaseTFPlayer( (CBaseEntity*)GetOwner() );
	if ( pPlayer )
	{
		// Charge-up mode?
		if ( pPlayer->HasNamedTechnology( "com_comboshield_charge" ) )
		{
			m_bHasCharge = true;
		}
		else
		{
			m_bHasCharge = false;
		}

		// Burst shot mode?
		if ( pPlayer->HasNamedTechnology( "com_comboshield_tripleshot" ) )
		{
			m_bHasBurstShot = true;
		}
		else
		{
			m_bHasBurstShot = false;
		}
	}
}
예제 #4
0
//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
void CWeaponBuilder::ItemPostFrame( void )
{
	CBaseTFPlayer *pOwner = ToBaseTFPlayer( GetOwner() );
	if ( !pOwner )
		return;

	// Ignore input while the player's building anything
	if ( pOwner->IsBuilding() )
		return;

	// Switch away if I'm not in placement mode
	if ( m_iBuildState != BS_PLACING && m_iBuildState != BS_PLACING_INVALID )
	{
		pOwner->SwitchToNextBestWeapon( NULL );
		return;
	}

	if (( pOwner->m_nButtons & IN_ATTACK ) && (m_flNextPrimaryAttack <= gpGlobals->curtime) )
	{
		PrimaryAttack();
	}

	// Allow shield post frame 
	AllowShieldPostFrame( true );

	WeaponIdle();
}
예제 #5
0
//-----------------------------------------------------------------------------
// Purpose: The player holding this weapon has just gained new technology.
//			Check to see if it affects the medikit
//-----------------------------------------------------------------------------
void CWeaponBuilder::GainedNewTechnology( CBaseTechnology *pTechnology )
{
	CBaseTFPlayer *pPlayer = ToBaseTFPlayer( GetOwner() );
	if ( pPlayer )
	{
		// Force a recalculation of the state for this object
		SetCurrentObject( m_iCurrentObject );
	}
}
//-----------------------------------------------------------------------------
// Purpose: Handle deploying, undeploying, firing, etc.
// TODO: Add a deploy to the firing!  Currently no reloading!
//-----------------------------------------------------------------------------
void CWeaponRocketLauncher::ItemPostFrame( void )
{
	// Get the player.
	CBaseTFPlayer *pPlayer = ToBaseTFPlayer( GetOwner() );
	if ( !pPlayer )
		return;

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

#if !defined( CLIENT_DLL )
	if ( !HasPrimaryAmmo() && ( m_flNextPrimaryAttack <= gpGlobals->curtime ) )
	{
		pPlayer->SwitchToNextBestWeapon( NULL );
	}
#endif

	// Handle Firing
	if ( GetShieldState() == SS_DOWN && !m_bInReload )
	{
		// Attempting to fire.
		if ( ( pPlayer->m_nButtons & IN_ATTACK ) && ( m_flNextPrimaryAttack <= gpGlobals->curtime ) )
		{
			if ( m_iClip1 > 0 )
			{
				PrimaryAttack();
			}
			else
			{
				Reload();
			}
		}

		// Reload button (or fire button when we're out of ammo)
		if ( m_flNextPrimaryAttack <= gpGlobals->curtime ) 
		{
			if ( pPlayer->m_nButtons & IN_RELOAD ) 
			{
				Reload();
			}
			else if ( !((pPlayer->m_nButtons & IN_ATTACK) || (pPlayer->m_nButtons & IN_ATTACK2) || (pPlayer->m_nButtons & IN_RELOAD)) )
			{
				if ( !m_iClip1 && HasPrimaryAmmo() )
				{
					Reload();
				}
			}
		}
	}

	// Prevent shield post frame if we're not ready to attack, or we're charging
	AllowShieldPostFrame( m_flNextPrimaryAttack <= gpGlobals->curtime || m_bInReload );
}
//-----------------------------------------------------------------------------
// Purpose: Reset all the player's resource banks
//-----------------------------------------------------------------------------
void CInfoInputResetBanks::InputResetAll( inputdata_t &inputdata )
{
	for ( int i = 1; i <= gpGlobals->maxClients; i++ )
	{
		CBaseTFPlayer *pPlayer = ToBaseTFPlayer( UTIL_PlayerByIndex(i) );
		if ( pPlayer )
		{
			ResetPlayersBank( pPlayer );
		}
	}
}
//-----------------------------------------------------------------------------
// Purpose: Play sound to all players
//-----------------------------------------------------------------------------
void CInfoInputPlaySound::InputPlaySoundToAll( inputdata_t &inputdata )
{
	for ( int i = 1; i <= gpGlobals->maxClients; i++ )
	{
		CBaseTFPlayer *pPlayer = ToBaseTFPlayer( UTIL_PlayerByIndex(i) );
		if ( pPlayer )
		{
			PlaySoundToPlayer( pPlayer );
		}
	}
}
예제 #9
0
//-----------------------------------------------------------------------------
// Purpose: Player holding this weapon has aborted the build of an object
//-----------------------------------------------------------------------------
void CWeaponBuilder::StoppedBuilding( int iObjectType )
{
	CBaseTFPlayer *pPlayer = ToBaseTFPlayer( GetOwner() );
	if ( pPlayer )
	{
		// Force a recalculation of the state for this object
		SetCurrentObject( m_iCurrentObject );
		SetCurrentState( BS_IDLE );

		WeaponSound( SPECIAL2 );
	}
}
예제 #10
0
//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
void CWeaponBuilder::UpdateOnRemove( void )
{
	// Tell the player he's lost his build weapon
	CBaseTFPlayer *pOwner = ToBaseTFPlayer( GetOwner() );
	if ( pOwner && pOwner->GetWeaponBuilder() == this )
	{
		pOwner->SetWeaponBuilder( NULL );
	}

	// Chain at end to mimic destructor unwind order
	BaseClass::UpdateOnRemove();
}
예제 #11
0
//-----------------------------------------------------------------------------
// Purpose: Run through all the Bots in the game and let them think.
//-----------------------------------------------------------------------------
void Bot_RunAll( void )
{
	for ( int i = 1; i <= gpGlobals->maxClients; i++ )
	{
		CBaseTFPlayer *pPlayer = ToBaseTFPlayer( UTIL_PlayerByIndex( i ) );

		if ( pPlayer && (pPlayer->GetFlags() & FL_FAKECLIENT) )
		{
			Bot_Think( pPlayer );
		}
	}
}
//-----------------------------------------------------------------------------
// Purpose: Bash enemies in front of me with my shield
//-----------------------------------------------------------------------------
void CWeaponCombatShield::ShieldBash( void )
{
#if 0
	// ROBIN: Disabled shield bash
	return;

	// Get any players in front of me
	CBaseTFPlayer *pOwner = ToBaseTFPlayer( GetOwner() );
	if ( !pOwner )
		return;

	// Get the target point and location
	Vector vecAiming;
	Vector vecSrc = pOwner->Weapon_ShootPosition( pOwner->GetOrigin() );	
	pOwner->EyeVectors( &vecAiming );

	// Find a player in range of this player, and make sure they're healable
	trace_t tr;
	Vector vecEnd = vecSrc + (vecAiming * SHIELD_BASH_RANGE);
	UTIL_TraceLine( vecSrc, vecEnd, MASK_SHOT, pOwner->edict(), COLLISION_GROUP_NONE, &tr);
	if (tr.fraction != 1.0)
	{
		CBaseEntity *pEntity = CBaseEntity::Instance(tr.u.ent);
		if ( pEntity )
		{
			CBaseTFPlayer *pPlayer = ToBaseTFPlayer( pEntity );
			if ( pPlayer && (pPlayer != pOwner) )
			{
				// Target needs to be on the eneny team
				if ( pPlayer->IsAlive() && !pPlayer->InSameTeam( pOwner ) )
				{
					// Ok, we have an enemy player
					pPlayer->TakeShieldBash( pOwner );
				}
			}
		}
	}
#endif
}
예제 #13
0
//-----------------------------------------------------------------------------
// Purpose: The player holding this weapon has just finished building an object
//-----------------------------------------------------------------------------
void CWeaponBuilder::FinishedObject( void )
{
	CBaseTFPlayer *pPlayer = ToBaseTFPlayer( GetOwner() );
	if ( pPlayer )
	{
		// We're no longer building anything...
		m_hObjectBeingBuilt = NULL;

		// Force a recalculation of the state for this object
		SetCurrentObject( m_iCurrentObject );
		SetCurrentState( BS_IDLE );
	}
}
//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
void CWeaponCombatLaserRifle::ItemPostFrame( void )
{
	CBaseTFPlayer *pOwner = ToBaseTFPlayer( GetOwner() );
	if (!pOwner)
		return;

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

	RecalculateAccuracy();

	// Handle firing
	if ( GetShieldState() == SS_DOWN && !m_bInReload )
	{
		if ( (pOwner->m_nButtons & IN_ATTACK ) && (m_flNextPrimaryAttack <= gpGlobals->curtime) )
		{
			if ( m_iClip1 > 0 )
			{
				// Fire the plasma shot
				PrimaryAttack();
			}
			else
			{
				Reload();
			}
		}

		// Reload button (or fire button when we're out of ammo)
		if ( m_flNextPrimaryAttack <= gpGlobals->curtime ) 
		{
			if ( pOwner->m_nButtons & IN_RELOAD ) 
			{
				Reload();
			}
			else if ( !((pOwner->m_nButtons & IN_ATTACK) || (pOwner->m_nButtons & IN_ATTACK2) || (pOwner->m_nButtons & IN_RELOAD)) )
			{
				if ( !m_iClip1 && HasPrimaryAmmo() )
				{
					Reload();
				}
			}
		}
	}

	// Prevent shield post frame if we're not ready to attack, or we're charging
	AllowShieldPostFrame( m_flNextPrimaryAttack <= gpGlobals->curtime || m_bInReload );
}
//-----------------------------------------------------------------------------
// Purpose: Check to see if the shield state should change
//-----------------------------------------------------------------------------
void CWeaponCombatShield::UpdateShieldState( void )
{
	CBaseTFPlayer *pOwner = ToBaseTFPlayer( GetOwner() );
	if ( !pOwner )
		return;

	// Check to see if I should move out of the current state
	switch ( m_iShieldState )
	{
	default:
	case SS_DOWN:
	case SS_UP:
		break;

	case SS_RAISING:
			if ( gpGlobals->curtime > m_flShieldRaisedTime )
			{
				SetShieldState( SS_UP );
			}
			break;
	case SS_LOWERING:
		if ( gpGlobals->curtime > m_flShieldLoweredTime )
		{
			SetShieldState( SS_DOWN );
		}
		break;

	case SS_PARRYING:
		if ( gpGlobals->curtime > m_flShieldParryEndTime )
		{
			SetShieldState( SS_PARRYING_FINISH_SWING );
		}
		break;

	case SS_PARRYING_FINISH_SWING:
		if ( gpGlobals->curtime > m_flShieldParrySwingEndTime )
		{
			SetShieldState( SS_UNAVAILABLE );
		}
		break;

	case SS_UNAVAILABLE:
		if ( gpGlobals->curtime > m_flShieldUnavailableEndTime )
		{
			SetShieldState( SS_DOWN );
		}
		break;
	};
}
예제 #16
0
//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
void CWeaponMortar::MortarDestroyed( void )
{
	CBaseTFPlayer *pPlayer = ToBaseTFPlayer( GetOwner() );
	if ( pPlayer )
	{
		ClientPrint( pPlayer, HUD_PRINTCENTER, "\n\n\n\n\n\n\n\n\n\nMortar Destroyed!" );
	}

	if ( pPlayer && pPlayer->GetActiveWeapon() == this )
	{
		SendWeaponAnim( ACT_SLAM_TRIPMINE_DRAW );
	}

	MortarObjectRemoved();
}
예제 #17
0
//-----------------------------------------------------------------------------
// Purpose: Records that a player has left the zone, and updates it's state
//			according, maybe starting to change team.
// Input  : *pOther - the entity that left the zone
//-----------------------------------------------------------------------------
void CControlZone::EndTouch( CBaseEntity *pOther )
{
	CBaseTFPlayer *pl = ToBaseTFPlayer( pOther );
	if ( !pl )
		return;

	CHandle< CBaseTFPlayer > hHandle;
	hHandle = pl;
	m_ZonePlayerList.FindAndRemove( hHandle );

	ReevaluateControllingTeam();

	// Unset this player's current zone if it's this one
	if ( pl->GetCurrentZone() == this )
		pl->SetCurrentZone( NULL );
}
예제 #18
0
//-----------------------------------------------------------------------------
// Purpose: Records that a player has entered the zone, and updates it's state
//			according, maybe starting to change team.
// Input  : *pOther - the entity that left the zone
//-----------------------------------------------------------------------------
void CControlZone::StartTouch( CBaseEntity *pOther )
{
	CBaseTFPlayer *pl = ToBaseTFPlayer( pOther );
	if ( !pl )
		return;

	CHandle< CBaseTFPlayer > hHandle;
	hHandle = pl;

	m_ZonePlayerList.AddToTail( hHandle );

	ReevaluateControllingTeam();

	// Set this player's current zone to this zone
	pl->SetCurrentZone( this );
}
예제 #19
0
//-----------------------------------------------------------------------------
// Purpose: Start placing the object
//-----------------------------------------------------------------------------
void CWeaponBuilder::StartPlacement( void )
{
	StopPlacement();

	// Create the slab
	m_hObjectBeingBuilt = (CBaseObject*)CreateEntityByName( GetObjectInfo( m_iCurrentObject )->m_pClassName );
	if ( m_hObjectBeingBuilt )
	{
		m_hObjectBeingBuilt->Spawn();
		m_hObjectBeingBuilt->StartPlacement( ToBaseTFPlayer( GetOwner() ) );
		UpdatePlacement();

		// Stomp this here in the same frame we make the object, so prevent clientside warnings that it's under attack
		m_hObjectBeingBuilt->m_iHealth = OBJECT_CONSTRUCTION_STARTINGHEALTH;
	}
}
//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
bool CWeaponCombatShield::Holster( CBaseCombatWeapon *pSwitchingTo )
{
	CBaseTFPlayer *player = ToBaseTFPlayer( GetOwner() );
	if ( player )
	{
		player->SetBlocking( false );
		player->SetParrying( false );

		if ( m_iShieldState != SS_DOWN && 
			 m_iShieldState != SS_UNAVAILABLE )
		{
			SetShieldState( SS_LOWERING );
		}
	}

	return true;
}
예제 #21
0
//-----------------------------------------------------------------------------
// Purpose: Set the deployed mortar's firing round
//-----------------------------------------------------------------------------
void CWeaponMortar::SetRoundType( int iRoundType )
{
	if ( m_hDeployedMortar == NULL )
		return;

	// Make sure we've got the technology for this round type
	if ( MortarAmmoTechs[ iRoundType ] && MortarAmmoTechs[ iRoundType ][0] )
	{
		CBaseTFPlayer *pPlayer = ToBaseTFPlayer( GetOwner() );
		if ( !pPlayer )
			return;
		// Does the player have the technology?
		if ( pPlayer->HasNamedTechnology( MortarAmmoTechs[ iRoundType ] ) == false )
			return;
	}

	m_hDeployedMortar->m_iRoundType = iRoundType;
}
//-----------------------------------------------------------------------------
// Purpose: The player holding this weapon has just gained new technology.
//-----------------------------------------------------------------------------
void CWeaponCombatShield::GainedNewTechnology( CBaseTechnology *pTechnology )
{
	BaseClass::GainedNewTechnology( pTechnology );

	CBaseTFPlayer *pPlayer = ToBaseTFPlayer( GetOwner() );
	if ( pPlayer )
	{
		// Has a parry?
		if ( pPlayer->HasNamedTechnology( "com_comboshield_parry" ) )
		{
			m_bHasShieldParry = true;
		}
		else
		{
			m_bHasShieldParry = false;
		}
	}
}
예제 #23
0
//-----------------------------------------------------------------------------
// Purpose: The player holding this weapon has just gained new technology.
//			Check to see if it affects the mortar
//-----------------------------------------------------------------------------
void CWeaponMortar::GainedNewTechnology( CBaseTechnology *pTechnology )
{
	CBaseTFPlayer *pPlayer = ToBaseTFPlayer( GetOwner() );
	if ( pPlayer )
	{
		// Range upgraded?
		if ( pPlayer->HasNamedTechnology("mortar_range") )
			m_bRangeUpgraded = true;
		else
			m_bRangeUpgraded = false;

		// Accuracy upgraded?
		if ( pPlayer->HasNamedTechnology("mortar_accuracy") )
			m_bAccuracyUpgraded = true;
		else
			m_bAccuracyUpgraded = false;
	}
}
예제 #24
0
//-----------------------------------------------------------------------------
// Purpose: Set the builder to the specified object
//-----------------------------------------------------------------------------
void CWeaponBuilder::SetCurrentObject( int iObject )
{
	// Fixup for invalid objects
	if (iObject < 0)
		iObject = BUILDER_INVALID_OBJECT;

	CBaseTFPlayer *pOwner = ToBaseTFPlayer( GetOwner() );
	if ( !pOwner )
		return;

	int i;

	// If -1 was passed in, set to our first available object
	if ( iObject == BUILDER_INVALID_OBJECT )
	{
		for ( i = 0; i < OBJ_LAST; i++ )
		{
			if ( m_bObjectValidity[i] )
			{
				iObject = i;
				break;
			}
		}
	}

	// Recalculate the buildability of each object (for propagation to the client)
	for ( i=0; i < m_bObjectBuildability.Count(); i++ )
		m_bObjectBuildability.Set( i, 0 );

	for ( i = 0; i < OBJ_LAST; i++ )
	{
		if ( m_bObjectValidity[i] && pOwner->CanBuild(i) == CB_CAN_BUILD )
		{
			m_bObjectBuildability.Set( i, true );
		}
	}

	m_iCurrentObject = iObject;
	m_iCurrentObjectState = pOwner->CanBuild( m_iCurrentObject );
	m_flStartTime = 0;
	m_flTotalTime = 0;
}
예제 #25
0
//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
void CHarpoon::ImpaleTarget( CBaseEntity *pOther )
{
	// Impale!
	EmitSound( "Harpoon.Impale" );

	// Calculate our impale offset
	m_vecOffset = (pOther->GetAbsOrigin() - GetAbsOrigin());
	m_angOffset = (pOther->GetAbsAngles() - GetAbsAngles());

	FollowEntity( pOther );

	// Do some damage to the target
	if ( pOther->m_takedamage )
	{
		CBaseTFPlayer *pOwner = ToBaseTFPlayer( GetOwnerEntity() );
		if ( !pOwner )
			return;

		pOther->TakeDamage( CTakeDamageInfo( this, pOwner, weapon_harpoon_damage.GetFloat(), DMG_GENERIC ) );
	}
}
//-----------------------------------------------------------------------------
// Purpose: Attempt to block the incoming attack, and return the damage it 
//			should do after the block, if any.
//-----------------------------------------------------------------------------
float CWeaponCombatShield::AttemptToBlock( float flDamage )
{
	CBaseTFPlayer *pPlayer = ToBaseTFPlayer( GetOwner() );
	if ( !pPlayer || !weapon_combat_shield_factor.GetFloat() )
		return 0;

	// Block as much of the damage as we can
	float flPowerNeeded = flDamage * weapon_combat_shield_factor.GetFloat();
	flPowerNeeded = RemapVal( flPowerNeeded, 0, weapon_combat_shield_health.GetFloat(), 0, 1 );
	float flPowerUsed = min( flPowerNeeded, GetShieldHealth() );

#ifndef CLIENT_DLL
	RemoveShieldHealth( flPowerUsed );

	// Start recharging shortly after taking damage
	SetThink( ShieldRechargeThink );
	SetNextThink( gpGlobals->curtime + weapon_combat_shield_rechargetime.GetFloat() );
#endif

	// Failed to block it all?
	if ( flPowerUsed < flPowerNeeded )
	{
#ifndef CLIENT_DLL
		// Force the shield to drop if it's up
		if ( GetShieldState() == SS_UP )
		{
			// Play sound & anim
			SendWeaponAnim( ACT_VM_HAULBACK );
			WeaponSound( SPECIAL2 );
			SetShieldState( SS_LOWERING );
		}
#endif

		return ( flDamage - (flPowerUsed * (1.0 / weapon_combat_shield_factor.GetFloat())) );
	}

	return 0;
}
예제 #27
0
//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
void CWeaponMortar::PrimaryAttack( void )
{
	CBaseTFPlayer *pPlayer = ToBaseTFPlayer( GetOwner() );
	if ( !pPlayer )
		return;
	// Can't attack if taking EMP damage
	if ( !ComputeEMPFireState() )
		return;
	if ( IsOwnerEMPed() )
		return;
	if ( m_hDeployedMortar == NULL )
		return;

	if ( m_hDeployedMortar->FireMortar( m_flFiringPower, m_flFiringAccuracy, m_bRangeUpgraded, m_bAccuracyUpgraded ) )
	{
		WeaponSound( SINGLE );
	}

	m_flNextPrimaryAttack = gpGlobals->curtime + 0.5;
	m_flNextSecondaryAttack = gpGlobals->curtime + 0.5;

	CheckRemoveDisguise();
}
//-----------------------------------------------------------------------------
// Purpose: I've been bashed by another player's shield
//-----------------------------------------------------------------------------
bool CWeaponCombatShield::TakeShieldBash( CBaseTFPlayer *pBasher )
{
	CBaseTFPlayer *pOwner = ToBaseTFPlayer( GetOwner() );
	if ( !pOwner )
		return false;

	// If I'm blocking, drop my block and prevent me from doing anything
	if ( GetShieldState() == SS_UP ||
		 GetShieldState() == SS_RAISING ||
		 GetShieldState() == SS_LOWERING )
	{
		// Make the shield unavailable
		SetShieldState( SS_UNAVAILABLE );
		SendWeaponAnim( ACT_VM_HITCENTER );

		m_flShieldUnavailableEndTime = gpGlobals->curtime + 2.0;

		// Play a sound	
		EmitSound( "WeaponCombatShield.TakeBash" );		
		return true;
	}

	return false;
}
//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
void CWeaponLaserRifle::PrimaryAttack( void )
{
	CBaseTFPlayer *pPlayer = ToBaseTFPlayer( m_hOwner );
	if ( !pPlayer )
		return;
	
	if ( !ComputeEMPFireState() )
		return;

	WeaponSound(SINGLE);

	PlayAttackAnimation( GetPrimaryAttackActivity() );

	pPlayer->m_fEffects |= EF_MUZZLEFLASH;

	// Fire the beam: BLOW OFF AUTOAIM
	Vector vecSrc	 = pPlayer->Weapon_ShootPosition( pPlayer->GetOrigin() );
	Vector vecAiming, right, up;
	pPlayer->EyeVectors( &vecAiming, &right, &up);

	Vector vecSpread = VECTOR_CONE_4DEGREES;

	// Get endpoint
	float x, y, z;
	do {
		x = random->RandomFloat(-0.5,0.5) + random->RandomFloat(-0.5,0.5);
		y = random->RandomFloat(-0.5,0.5) + random->RandomFloat(-0.5,0.5);
		z = x*x+y*y;
	} while (z > 1);
	Vector vecDir = vecAiming + x * vecSpread.x * right + y * vecSpread.y * up;
	Vector vecEnd = vecSrc + vecDir * weapon_laserrifle_range.GetFloat();

	trace_t tr;
	float damagefactor = TFGameRules()->WeaponTraceLine(vecSrc, vecEnd, MASK_SHOT, pPlayer, DMG_ENERGYBEAM, &tr);

	// Hit target?
	if (tr.fraction != 1.0)
	{
		CBaseEntity *pEntity = CBaseEntity::Instance(tr.u.ent);
		if ( pEntity )
		{
			ClearMultiDamage();
			float flDamage = GetDamage( (tr.endpos - vecSrc).Length(), tr.hitgroup );
			flDamage *= damagefactor;  
			pEntity->TraceAttack( CTakeDamageInfo( pPlayer, pPlayer, flDamage, DMG_ENERGYBEAM ), vecDir, &tr );
			ApplyMultiDamage( pPlayer, pPlayer );
		}

		g_pEffects->EnergySplash( tr.endpos, tr.plane.normal );
	}

	// Get hacked gun position
	AngleVectors( pPlayer->EyeAngles() + pPlayer->m_Local.m_vecPunchAngle, NULL, &right, NULL );
	Vector vecTracerSrc = vecSrc + Vector (0,0,-8) + right * 12 + vecDir * 16;

	// Laser beam
	CBroadcastRecipientFilter filter;
	te->BeamPoints( filter, 0.0,
					&vecTracerSrc, 
					&tr.endpos, 
					m_iSpriteTexture, 
					0,		// Halo index
					0,		// Start frame
					0,		// Frame rate
					0.2,	// Life
					15,		// Width
					15,		// EndWidth
					0,		// FadeLength
					0,		// Amplitude
					200,	// r
					200,	// g
					255,	// b
					255,	// a
					255	);	// speed

	pPlayer->m_iAmmo[m_iPrimaryAmmoType]--;
	m_flNextPrimaryAttack = gpGlobals->curtime + GetFireRate();

	CheckRemoveDisguise();
}
//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
void CWeaponCombat_ChargeablePlasma::ItemPostFrame( void )
{
	CBaseTFPlayer *pOwner = ToBaseTFPlayer( GetOwner() );
	if (!pOwner)
		return;

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

	// If burst shots are firing, ignore input
	if ( m_iBurstShotsRemaining > 0 )
	{
		if ( gpGlobals->curtime < m_flNextBurstShotTime )
			return;

		if ( m_iClip1 > 0 )
		{
			PrimaryAttack();
		}

		m_iBurstShotsRemaining--;
		m_flNextBurstShotTime = gpGlobals->curtime + BURST_FIRE_RATE;
		m_flNextPrimaryAttack = gpGlobals->curtime + GetFireRate();
		return;
	}

	// Handle charge firing
	if ( m_iClip1 > 0 && GetShieldState() == SS_DOWN && !m_bInReload )
	{
		if ( (pOwner->m_nButtons & IN_ATTACK ) )
		{
			if (m_bHasCharge)
			{
				if ( !m_bCharging && (m_flNextPrimaryAttack <= gpGlobals->curtime) )
				{
					m_bCharging = true;
					m_flChargeStartTime = gpGlobals->curtime;

					// Get a lock target right now
					m_hLockTarget = GetLockTarget();
				}
			}
			else
			{
				// Fire the plasma shot
				if (m_flNextPrimaryAttack <= gpGlobals->curtime)
					PrimaryAttack();
			}
		}
		else if ( m_bCharging )
		{
			m_bCharging = false;

			// Fire the plasma shot
			PrimaryAttack();

			// We might be firing a burst shot
			if (m_bHasBurstShot)
			{
				if ( m_flPower >= (MAX_CHARGED_TIME * 0.5) )
				{
					if ( m_flPower >= MAX_CHARGED_TIME )
					{
						m_iBurstShotsRemaining = 2;
					}
					else
					{
						m_iBurstShotsRemaining = 1;
					}

					m_flNextBurstShotTime = gpGlobals->curtime + BURST_FIRE_RATE;
				}
			}
		}
	}

	// Reload button
	if ( m_iBurstShotsRemaining == 0 && !m_bCharging )
	{
		if ( pOwner->m_nButtons & IN_RELOAD && UsesClipsForAmmo1() && !m_bInReload )
		{
			Reload();
		}
	}

	// Prevent shield post frame if we're not ready to attack, or we're charging
	AllowShieldPostFrame( !m_bCharging && ((m_flNextPrimaryAttack <= gpGlobals->curtime) || m_bInReload) );
}