コード例 #1
0
// -----------------------------------------------------------------------------
// Purpose:
// Note: Think function to delay the impact decal until the animation is finished 
//       playing.
// -----------------------------------------------------------------------------
void CTFWeaponBaseMelee::Smack( void )
{
	trace_t trace;

	CBasePlayer *pPlayer = GetPlayerOwner();
	if ( !pPlayer )
		return;

#if !defined (CLIENT_DLL)
	// Move other players back to history positions based on local player's lag
	lagcompensation->StartLagCompensation( pPlayer, pPlayer->GetCurrentCommand() );
#endif

	// We hit, setup the smack.
	if ( DoSwingTrace( trace ) )
	{
		// Hit sound - immediate.
		if( trace.m_pEnt->IsPlayer()  )
		{
			WeaponSound( MELEE_HIT );
		}
		else
		{
			WeaponSound( MELEE_HIT_WORLD );
		}

		// Get the current player.
		CTFPlayer *pPlayer = GetTFPlayerOwner();
		if ( !pPlayer )
			return;

		Vector vecForward; 
		AngleVectors( pPlayer->EyeAngles(), &vecForward );
		Vector vecSwingStart = pPlayer->Weapon_ShootPosition();
		Vector vecSwingEnd = vecSwingStart + vecForward * 48;

#ifndef CLIENT_DLL
		// Do Damage.
		int iCustomDamage = TF_DMG_CUSTOM_NONE;
		float flDamage = GetMeleeDamage( trace.m_pEnt, iCustomDamage );
		int iDmgType = DMG_BULLET | DMG_NEVERGIB | DMG_CLUB;
		if ( IsCurrentAttackACrit() )
		{
			// TODO: Not removing the old critical path yet, but the new custom damage is marking criticals as well for melee now.
			iDmgType |= DMG_CRITICAL;
		}
		CTFWeaponBase *pWpn = pPlayer->GetActiveTFWeapon();
		CTFUbersaw *pUbersaw = dynamic_cast<CTFUbersaw*>(pWpn);
		CWeaponMedigun *pMedigun = static_cast<CWeaponMedigun*>(pPlayer->Weapon_OwnsThisID(TF_WEAPON_MEDIGUN));
		if (pMedigun && pUbersaw)
		{
			if(trace.m_pEnt->IsPlayer() && trace.m_pEnt->GetTeamNumber() != pPlayer->GetTeamNumber())
			{
				pMedigun->AddCharge();
			}
		}
		CWeaponKritzkrieg *pKritzkrieg = static_cast<CWeaponKritzkrieg*>(pPlayer->Weapon_OwnsThisID(TF_WEAPON_KRITZKRIEG));
		if (pKritzkrieg && pUbersaw)
		{
			if(trace.m_pEnt->IsPlayer() && trace.m_pEnt->GetTeamNumber() != pPlayer->GetTeamNumber())
			{
				pKritzkrieg->AddCharge();
			}
		}
		CTakeDamageInfo info( pPlayer, pPlayer, flDamage, iDmgType, iCustomDamage );
		CalculateMeleeDamageForce( &info, vecForward, vecSwingEnd, 1.0f / flDamage * tf_meleeattackforcescale.GetFloat() );
		trace.m_pEnt->DispatchTraceAttack( info, vecForward, &trace ); 
		ApplyMultiDamage();

		OnEntityHit( trace.m_pEnt );
#endif
		// Don't impact trace friendly players or objects
		if ( trace.m_pEnt && trace.m_pEnt->GetTeamNumber() != pPlayer->GetTeamNumber() )
		{
#ifdef CLIENT_DLL
			UTIL_ImpactTrace( &trace, DMG_CLUB );
#endif
			m_bConnected = true;
		}

	}

#if !defined (CLIENT_DLL)
	lagcompensation->FinishLagCompensation( pPlayer );
#endif
}
コード例 #2
0
//------------------------------------------------------------------------
int CMelee::Hit(const Vec3 &pt, const Vec3 &dir, const Vec3 &normal, IPhysicalEntity *pCollider, EntityId collidedEntityId, int partId, int ipart, int surfaceIdx, bool remote)
{
	MeleeDebugLog ("CMelee<%p> HitPointDirNormal(remote=%s)", this, remote ? "true" : "false");
	int hitTypeID = 0;

	CActor *pOwnerActor = m_pWeapon->GetOwnerActor();

	if (pOwnerActor)
	{	
		IActor* pTargetActor = g_pGame->GetIGameFramework()->GetIActorSystem()->GetActor(collidedEntityId);
		IEntity* pTarget = pTargetActor ? pTargetActor->GetEntity() : gEnv->pEntitySystem->GetEntity(collidedEntityId);
		IEntity* pOwnerEntity = pOwnerActor->GetEntity();
		IAIObject* pOwnerAI = pOwnerEntity->GetAI();
		
		float damageScale = 1.0f;
		bool silentHit = false;

		if(pTargetActor)
		{
			IAnimatedCharacter* pTargetAC = pTargetActor->GetAnimatedCharacter();
			IAnimatedCharacter* pOwnerAC = pOwnerActor->GetAnimatedCharacter();

			if(pTargetAC && pOwnerAC)
			{
				Vec3 targetFacing(pTargetAC->GetAnimLocation().GetColumn1());
				Vec3 ownerFacing(pOwnerAC->GetAnimLocation().GetColumn1());
				float ownerFacingDot = ownerFacing.Dot(targetFacing);
				float fromBehindDot = cos_tpl(DEG2RAD(g_pGameCVars->pl_melee.angle_limit_from_behind));

				if(ownerFacingDot > fromBehindDot)
				{
#ifndef _RELEASE
					if (g_pGameCVars->g_LogDamage)
					{
						CryLog ("[DAMAGE] %s '%s' is%s meleeing %s '%s' from behind (because %f > %f)",
							pOwnerActor->GetEntity()->GetClass()->GetName(), pOwnerActor->GetEntity()->GetName(), silentHit ? " silently" : "",
							pTargetActor->GetEntity()->GetClass()->GetName(), pTargetActor->GetEntity()->GetName(),
							ownerFacingDot, fromBehindDot);
					}
#endif

					damageScale *= g_pGameCVars->pl_melee.damage_multiplier_from_behind;
				}
			}
		}


		// Send target stimuli
		if (!gEnv->bMultiplayer)
		{
			IAISystem *pAISystem = gEnv->pAISystem;
			ITargetTrackManager *pTargetTrackManager = pAISystem ? pAISystem->GetTargetTrackManager() : NULL;
			if (pTargetTrackManager && pOwnerAI)
			{
				IAIObject *pTargetAI = pTarget ? pTarget->GetAI() : NULL;
				if (pTargetAI)
				{
					const tAIObjectID aiOwnerId = pOwnerAI->GetAIObjectID();
					const tAIObjectID aiTargetId = pTargetAI->GetAIObjectID();

					TargetTrackHelpers::SStimulusEvent eventInfo;
					eventInfo.vPos = pt;
					eventInfo.eStimulusType = TargetTrackHelpers::eEST_Generic;
					eventInfo.eTargetThreat = AITHREAT_AGGRESSIVE;
					pTargetTrackManager->HandleStimulusEventForAgent(aiTargetId, aiOwnerId, "MeleeHit",eventInfo);
					pTargetTrackManager->HandleStimulusEventInRange(aiOwnerId, "MeleeHitNear", eventInfo, 5.0f);
				}
			}
		}

		//Check if is a friendly hit, in that case FX and Hit will be skipped
		bool isFriendlyHit = (pOwnerEntity && pTarget) ? IsFriendlyHit(pOwnerEntity, pTarget) : false;

		if(!isFriendlyHit)
		{
			CPlayer * pAttackerPlayer = pOwnerActor->IsPlayer() ? static_cast<CPlayer*>(pOwnerActor) : NULL;
			float damage = m_pMeleeParams->meleeparams.damage_ai;

			if(pOwnerActor->IsPlayer())
			{
				damage = m_slideKick ? m_pMeleeParams->meleeparams.slide_damage : GetMeleeDamage();
			}

#ifndef _RELEASE
			if (pTargetActor && g_pGameCVars->g_LogDamage)
			{
				CryLog ("[DAMAGE] %s '%s' is%s meleeing %s '%s' applying damage = %.3f x %.3f = %.3f",
					pOwnerActor->GetEntity()->GetClass()->GetName(), pOwnerActor->GetEntity()->GetName(), silentHit ? " silently" : "",
					pTargetActor->GetEntity()->GetClass()->GetName(), pTargetActor->GetEntity()->GetName(),
					damage, damageScale, damage * damageScale);
			}
#endif

			//Generate Hit
			if(pTarget)
			{
				CGameRules *pGameRules = g_pGame->GetGameRules();
				CRY_ASSERT_MESSAGE(pGameRules, "No game rules! Melee can not apply hit damage");

				if (pGameRules)
				{
					hitTypeID = silentHit ? CGameRules::EHitType::SilentMelee : m_hitTypeID;
					HitInfo info(m_pWeapon->GetOwnerId(), pTarget->GetId(), m_pWeapon->GetEntityId(),
						damage * damageScale, 0.0f, surfaceIdx, partId, hitTypeID, pt, dir, normal);

					if (m_pMeleeParams->meleeparams.knockdown_chance>0 && Random(100) < m_pMeleeParams->meleeparams.knockdown_chance)
						info.knocksDown = true;

					info.remote = remote;

					pGameRules->ClientHit(info);
				}

				if (pAttackerPlayer && pAttackerPlayer->IsClient())
				{
					const Vec3 posOffset = (pt - pTarget->GetWorldPos());
					SMeleeHitParams params;

					params.m_boostedMelee = false;
					params.m_hitNormal = normal;
					params.m_hitOffset = posOffset;
					params.m_surfaceIdx = surfaceIdx;
					params.m_targetId = pTarget->GetId();

					pAttackerPlayer->OnMeleeHit(params);
				}
			}
			else
			{
				//Play Material FX
				PlayHitMaterialEffect(pt, normal, false, surfaceIdx);
			}
		}

		if (pTarget)
		{
			CActor *pCTargetActor = static_cast<CActor*>(pTargetActor);
			CPlayer* pTargetPlayer = (pTargetActor && pTargetActor->IsPlayer()) ? static_cast<CPlayer*>(pTargetActor) : NULL;

			if(pTargetPlayer && pTargetPlayer->IsClient())
			{
				if(m_pMeleeParams->meleeparams.trigger_client_reaction)
				{
					pTargetPlayer->TriggerMeleeReaction();
				}
			}
		}
	}

	return hitTypeID;
}