Beispiel #1
0
IASW_Spawnable_NPC* CASW_Spawner::SpawnAlien( const char *szAlienClassName, const Vector &vecHullMins, const Vector &vecHullMaxs )
{
  
	IASW_Spawnable_NPC *pSpawnable = BaseClass::SpawnAlien( szAlienClassName, vecHullMins, vecHullMaxs );
 
	if ( pSpawnable )
	{
		m_nCurrentLiveAliens++;

		if (!m_bInfiniteAliens)
		{
			m_nNumAliens--;
			if (m_nNumAliens <= 0)
			{
				SpawnedAllAliens();
			}
		}
		else
		{
			ASWFailAdvice()->OnAlienSpawnedInfinite();
		}
	}
 
	return pSpawnable;
}
void CASW_Sentry_Top::OnUsedQuarterAmmo( void )
{
	if ( gpGlobals->curtime - m_flTimeFirstFired < 30.0f )
	{
		ASWFailAdvice()->OnSentryUsedWell();	
	}
}
void CASW_Shieldbug::TraceAttack( const CTakeDamageInfo &info, const Vector &vecDir, trace_t *ptr )
{
	//Msg( "Shieldbug hit on hitbox %d hitgroup %d\n", ptr->hitbox, ptr->hitgroup );

	if ( info.GetDamageType() != DMG_BLAST && BlockedDamage( info, vecDir, ptr ) )	// m_bDefending && 
	{
#ifdef GAME_DLL
		m_fLastHurtTime = gpGlobals->curtime;
		CheckForShieldbugHint(info);
		ASWFailAdvice()->OnShiedbugBlocked();
#endif
		/*
		Vector position = info.GetDamagePosition() + m_LagCompensation.GetLagCompensationOffset();		

		// make sure the position is actually at our edge
		
		Vector vecPosDir = position - GetAbsOrigin();
		vecPosDir.NormalizeInPlace();
		position = GetAbsOrigin() + vecPosDir * 40.0f;
		*/
		Vector vecSparkPos = ptr->endpos;
		Vector vecSparkDir = -vecDir;
		CPVSFilter filter( vecSparkPos );	
		te->Sparks( filter, 0.0, &vecSparkPos, 1, 1, &vecSparkDir );

		return;
	}

	BaseClass::TraceAttack(info, vecDir, ptr);
}
void CASW_Weapon_HealGrenade::PrimaryAttack( void )
{	
	CASW_Player *pPlayer = GetCommander();
	if (!pPlayer)
		return;

	CASW_Marine *pMarine = GetMarine();
#ifndef CLIENT_DLL
	bool bThisActive = (pMarine && pMarine->GetActiveWeapon() == this);
#endif

	if ( !pMarine )
		return;

	// MUST call sound before removing a round from the clip of a CMachineGun
	WeaponSound(SINGLE);

	// sets the animation on the weapon model iteself
	SendWeaponAnim( GetPrimaryAttackActivity() );

	// sets the animation on the marine holding this weapon
	//pMarine->SetAnimation( PLAYER_ATTACK1 );
#ifndef CLIENT_DLL
	Vector	vecSrc		= pMarine->Weapon_ShootPosition( );
	Vector	vecAiming	= pPlayer->GetAutoaimVectorForMarine(pMarine, GetAutoAimAmount(), GetVerticalAdjustOnlyAutoAimAmount());	// 45 degrees = 0.707106781187

	if ( !pMarine->IsInhabited() && vecSrc.DistTo( pMarine->m_vecOffhandItemSpot ) < 150.0f )
	{
		vecSrc.x = pMarine->m_vecOffhandItemSpot.x;
		vecSrc.y = pMarine->m_vecOffhandItemSpot.y;
		vecSrc.z += 50.0f;
	}

	QAngle ang = pPlayer->EyeAngles();
	ang.x = 0;
	ang.z = 0;
	CShotManipulator Manipulator( vecAiming );
	AngularImpulse rotSpeed(0,0,720);

	// create a pellet at some random spread direction			
	Vector newVel = Manipulator.ApplySpread(GetBulletSpread());
	if ( pMarine->GetWaterLevel() != 3 )
	{
		CreateProjectile( vecSrc, ang, newVel, rotSpeed, pMarine );
		pMarine->OnWeaponFired( this, 1 );
	}

	pMarine->GetMarineSpeech()->Chatter(CHATTER_MEDKIT);
#endif

	// decrement ammo
	m_iClip1 -= 1;

#ifndef CLIENT_DLL
	// destroy if empty
	if ( UsesClipsForAmmo1() && !m_iClip1 ) 
	{
		ASWFailAdvice()->OnMedSatchelEmpty();

		pMarine->GetMarineSpeech()->Chatter( CHATTER_MEDS_NONE );

		if ( pMarine )
		{
			pMarine->Weapon_Detach(this);
			if ( bThisActive )
				pMarine->SwitchToNextBestWeapon(NULL);
		}
		Kill();

		return;
	}
#endif

	m_flSoonestPrimaryAttack = gpGlobals->curtime + GetRefireTime();
	if (m_iClip1 > 0)		// only force the fire wait time if we have ammo for another shot
		m_flNextPrimaryAttack = gpGlobals->curtime + GetFireRate();
	else
		m_flNextPrimaryAttack = gpGlobals->curtime;

	//m_flLastFireTime = gpGlobals->curtime;
}
void CASW_HealGrenade_Projectile::DoAOE( CBaseEntity *pEntity )
{
	CASW_Marine *pTargetMarine = static_cast< CASW_Marine* >( pEntity );
	if ( !pTargetMarine )
		return;

	CASW_Marine *pMarine = dynamic_cast< CASW_Marine* >( GetOwnerEntity() ); // Carful! This might be null

	float flBaseHealAmount = m_flHealPerSecond * ( gpGlobals->curtime - m_flLastDoAOE );

	// At full health... multiplier is 1 + 0. At empty health multiplier is 1 + 3.0.
	float fHealthPercent = pTargetMarine->IsInfested() ? 0.0f : static_cast< float >( pTargetMarine->GetHealth() ) / pTargetMarine->GetMaxHealth();
	float flLowHealthMultiplier = ( 1.0f + 3.0f * ( 1.0f - fHealthPercent ) );
	float flHealAmount = MIN( flBaseHealAmount * flLowHealthMultiplier, pTargetMarine->GetMaxHealth() - ( pTargetMarine->GetHealth() + pTargetMarine->m_iSlowHealAmount ) );

	float flHealUsed = flHealAmount;

	if ( flHealAmount > 0.0f )
	{
		bool bHealedBefore = false;

		for ( int i = 0; i < m_hHealedEntities.Count(); ++i )
		{
			if ( m_hHealedEntities[ i ].Get() == pEntity )
			{
				bHealedBefore = true;
				break;
			}
		}

		if ( !bHealedBefore )
		{
			// Add it to the list of things we've healed at least once
			m_hHealedEntities.AddToTail( pEntity );

			// Fire event
			IGameEvent * event = gameeventmanager->CreateEvent( "player_heal" );
			if ( event )
			{
				CASW_Player *pPlayer = NULL;
				if ( pMarine )
				{
					pPlayer = pMarine->GetCommander();
				}
				event->SetInt( "userid", ( pPlayer ? pPlayer->GetUserID() : 0 ) );
				event->SetInt( "entindex", pTargetMarine->entindex() );
				gameeventmanager->FireEvent( event );
			}

			if ( pMarine )
			{
				CASW_Marine_Resource *pMR = pMarine->GetMarineResource();
				if ( pMR && !pMR->m_bAwardedHealBeaconAchievement && m_hHealedEntities.Count() >= 4 && pMarine->IsInhabited() && pMarine->GetCommander() )
				{
					pMR->m_bAwardedHealBeaconAchievement = true;
					pMarine->GetCommander()->AwardAchievement( ACHIEVEMENT_ASW_GROUP_HEAL );
				}
			}
		}

		pTargetMarine->AddSlowHeal( flHealAmount, 1, pMarine, this );

		float flHalfHealTotal = m_flHealAmountTotal / 2.0f;

		if ( m_flHealAmountLeft > flHalfHealTotal && ( m_flHealAmountLeft - flHealAmount ) <= flHalfHealTotal )
		{
			ASWFailAdvice()->OnHealGrenadeUsedWell();
		}

		m_flHealAmountLeft -= flHealUsed;

		if ( m_flHealAmountLeft <= 0.0f )
		{
			m_flTimeBurnOut = gpGlobals->curtime;
		}
	
		if ( ASWGameRules()->GetInfoHeal() && pMarine )
		{
			ASWGameRules()->GetInfoHeal()->OnMarineHealed( pMarine, pTargetMarine, NULL );
		}
	}

	if ( pTargetMarine->IsInfested() )
	{
		float fCurePercent = GetInfestationCureAmount();

		// cure infestation
		if ( fCurePercent > 0.0f )
		{
			// Cure infestation at 1/20th normal rate per second (the full 20 seconds or amount used does the full cure)
			pTargetMarine->CureInfestation( pMarine, 1.0f - ( ( 1.0f - fCurePercent ) * ( flHealUsed / m_flHealAmountTotal ) * ( gpGlobals->curtime - m_flLastDoAOE ) ) );
		}
	}
}
void CASW_HealGrenade_Projectile::OnBurnout( void )
{
	ASWFailAdvice()->OnMarineOverhealed( m_flHealAmountLeft );
}
	void CASW_Weapon_Medical_Satchel::GiveHealthTo( CASW_Marine *pTarget )
	{
		if ( !pTarget || m_iClip1 <= 0 )
			return;

		if ( pTarget->GetHealth() >= pTarget->GetMaxHealth() )		// already on full health
			return;

		if ( pTarget->GetHealth() <= 0 )		// target is dead!
			return;

		if ( pTarget->m_bSlowHeal )			// already healing
			return;

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

		if ( pMarine->GetFlags() & FL_FROZEN )	// don't allow this if the marine is frozen
			return;

		// check if we're close enough
		Vector diff = pMarine->GetAbsOrigin() - pTarget->GetAbsOrigin();
		if ( diff.Length() > MAX_HEAL_DISTANCE_SERVER )	// add a bit of leeway to account for lag
			return;

		bool bMedic = pMarine && pMarine->GetMarineProfile() && pMarine->GetMarineProfile()->CanUseFirstAid();

		//pMarine->DoAnimationEvent(PLAYERANIMEVENT_HEAL);
		WeaponSound(SINGLE);

		int iHealAmount = GetHealAmount();
		pTarget->AddSlowHeal(iHealAmount, 1, pMarine, this );

		// Fire event
		IGameEvent * event = gameeventmanager->CreateEvent( "player_heal" );
		if ( event )
		{
			CASW_Player *pPlayer = GetCommander();
			event->SetInt( "userid", ( pPlayer ? pPlayer->GetUserID() : 0 ) );
			event->SetInt( "entindex", pTarget->entindex() );
			gameeventmanager->FireEvent( event );
		}

		ASWFailAdvice()->OnMarineHealed();

		if ( ASWGameRules()->GetInfoHeal() )
		{
			ASWGameRules()->GetInfoHeal()->OnMarineHealed( GetMarine(), pTarget, this );
		}

		m_iClip1 -= 1;

		if ( bMedic )
		{
			if (pTarget->IsInfested())
			{
				float fCurePercent = GetInfestationCureAmount();
				// cure infestation
				if ( fCurePercent > 0 && fCurePercent < 100 )
				{
					pTarget->CureInfestation(pMarine, fCurePercent);
				}
			}

			bool bSkipChatter = pTarget->IsInfested();
			int iTotalMeds = GetTotalMeds();
			if ( m_iClip1 <= 0 )
			{
				if ( iTotalMeds <= 0 )
				{
					ASWFailAdvice()->OnMedSatchelEmpty();

					pMarine->GetMarineSpeech()->Chatter( CHATTER_MEDS_NONE );
					bSkipChatter = true;
				}
				
				DestroyIfEmpty( false, true );	// out of medical charges, remove this item
			}
			else if ( iTotalMeds <= 1 )
			{
				if ( pMarine->GetMarineSpeech()->Chatter( CHATTER_MEDS_LOW ) )
				{
					bSkipChatter = true;
				}
			}
			if ( !bSkipChatter )
			{
				// try and do a special chatter?
				bool bSkipChatter = false;
				if (pMarine->GetMarineSpeech()->AllowCalmConversations(CONV_HEALING_CRASH))
				{
					if (!pTarget->m_bDoneWoundedRebuke && pTarget->GetMarineResource() && pTarget->GetMarineResource()->m_bTakenWoundDamage)
					{
						// marine has been wounded and this is our first heal after the fact - good chance of the medic saying something
						if (random->RandomFloat() < asw_marine_special_heal_chatter_chance.GetFloat() * 3)
						{
							if (CASW_MarineSpeech::StartConversation(CONV_SERIOUS_INJURY, pMarine, pTarget))
							{
								bSkipChatter = true;
								pTarget->m_bDoneWoundedRebuke = true;
							}
						}
					}

					// if we didn't complaint about a serious injury, check for doing a different kind of conv
					float fRand = random->RandomFloat();
					if (!bSkipChatter && fRand < asw_marine_special_heal_chatter_chance.GetFloat())
					{
						if (pTarget->GetMarineProfile() && pTarget->GetMarineProfile()->m_VoiceType == ASW_VOICE_CRASH
							&& pMarine->GetMarineProfile() && pMarine->GetMarineProfile()->m_VoiceType == ASW_VOICE_BASTILLE)	// bastille healing crash
						{
							if (random->RandomFloat() < 0.5f)
							{
								if (CASW_MarineSpeech::StartConversation(CONV_HEALING_CRASH, pMarine, pTarget))
									bSkipChatter = true;						
							}
							else
							{
								if (CASW_MarineSpeech::StartConversation(CONV_MEDIC_COMPLAIN, pMarine, pTarget))
									bSkipChatter = true;
							}
						}
						else
						{
							if (CASW_MarineSpeech::StartConversation(CONV_MEDIC_COMPLAIN, pMarine, pTarget))
								bSkipChatter = true;
						}
					}
				}
				if (!bSkipChatter)
					pMarine->GetMarineSpeech()->Chatter(CHATTER_HEALING);
			}
		}	
	}
void CASW_Weapon_Assault_Shotgun::SecondaryAttack()
{
	// Only the player fires this way so we can cast
	CASW_Player *pPlayer = GetCommander();
	if (!pPlayer)
		return;

	CASW_Marine *pMarine = GetMarine();

	if (!pMarine)
		return;

	//Must have ammo
	bool bUsesSecondary = UsesSecondaryAmmo();
	bool bUsesClips = UsesClipsForAmmo2();
	int iAmmoCount = pMarine->GetAmmoCount(m_iSecondaryAmmoType);
	bool bInWater = ( pMarine->GetWaterLevel() == 3 );
	if ( (bUsesSecondary &&  
			(   ( bUsesClips && m_iClip2 <= 0) ||
			    ( !bUsesClips && iAmmoCount<=0 )
				) )
				 || bInWater || m_bInReload )
	{
		SendWeaponAnim( ACT_VM_DRYFIRE );
		BaseClass::WeaponSound( EMPTY );
		m_flNextSecondaryAttack = gpGlobals->curtime + 0.5f;
		return;
	}

	BaseClass::WeaponSound( SPECIAL1 );		
			
#ifndef CLIENT_DLL
	pMarine->GetMarineSpeech()->Chatter(CHATTER_GRENADE);
	Vector vecSrc = pMarine->Weapon_ShootPosition();
	Vector	vecThrow;
	// check for turning on lag compensation
	if (pPlayer && pMarine->IsInhabited())
	{
		CASW_Lag_Compensation::RequestLagCompensation( pPlayer, pPlayer->GetCurrentUserCommand() );
	}

	vecThrow = UTIL_LaunchVector(vecSrc, pPlayer->GetCrosshairTracePos(), asw_vindicator_grenade_gravity.GetFloat()) * 8.0f * asw_vindicator_grenade_velocity.GetFloat();
	QAngle angAiming = pPlayer->EyeAnglesWithCursorRoll();

	float fGrenadeDamage = MarineSkills()->GetSkillBasedValueByMarine(pMarine, ASW_MARINE_SKILL_GRENADES, ASW_MARINE_SUBSKILL_GRENADE_INCENDIARY_DMG);
	float fGrenadeRadius = MarineSkills()->GetSkillBasedValueByMarine(pMarine, ASW_MARINE_SKILL_GRENADES, ASW_MARINE_SUBSKILL_GRENADE_RADIUS);
	if (asw_debug_marine_damage.GetBool())
	{
		Msg("Grenade damage = %f radius = %f\n", fGrenadeDamage, fGrenadeRadius);
	}
	// check the grenade fits where we want to spawn it
	Ray_t ray;
	trace_t pm;
	ray.Init( pMarine->WorldSpaceCenter(), vecSrc, -Vector(4,4,4), Vector(4,4,4) );
	UTIL_TraceRay( ray, MASK_SOLID, pMarine, COLLISION_GROUP_PROJECTILE, &pm );
	if (pm.fraction < 1.0f)
		vecSrc = pm.endpos;

	CASW_Grenade_Vindicator::Vindicator_Grenade_Create( 
		fGrenadeDamage,
		fGrenadeRadius,
		vecSrc, angAiming, vecThrow, AngularImpulse(0,0,0), pMarine, this );

	pMarine->OnWeaponFired( this, 1, true );
#endif

	SendWeaponAnim( GetPrimaryAttackActivity() );

	pMarine->DoAnimationEvent( PLAYERANIMEVENT_FIRE_GUN_PRIMARY );

	// Decrease ammo
	if ( bUsesClips )
	{
		m_iClip2 -= 1;
	}
	else
	{
		pMarine->RemoveAmmo( 1, m_iSecondaryAmmoType );
	}

#ifndef CLIENT_DLL
	ASWFailAdvice()->OnMarineUsedSecondary();

	CEffectData	data;
	data.m_vOrigin = GetAbsOrigin();
	//data.m_vNormal = dir;
	//data.m_flScale = (float)amount;
	CPASFilter filter( data.m_vOrigin );
	filter.SetIgnorePredictionCull(true);
	DispatchParticleEffect( "muzzleflash_grenadelauncher_main", PATTACH_POINT_FOLLOW, this, "muzzle", false, -1, &filter );
#endif

	// Can shoot again immediately
	m_flNextPrimaryAttack = gpGlobals->curtime + 0.5f;

	// Can blow up after a short delay (so have time to release mouse button)
	m_flNextSecondaryAttack = gpGlobals->curtime + 1.0f;
}