Ejemplo n.º 1
0
	void Init(IEntity &entity, const float blendTime)
	{
		m_targetTime = blendTime;
		m_lastTime   = 0.0f;
		m_invalid    = false;

		m_delta.zero();
		m_deltaRot.SetIdentity();

		IActor* pActor = gEnv->pGame->GetIGameFramework()->GetIActorSystem()->GetActor(entity.GetId());
		m_pAnimatedCharacter = pActor ? pActor->GetAnimatedCharacter() : NULL;
	}
Ejemplo n.º 2
0
//--------------------------------------------------------------------------------------------------
// Name: SpawnParticlesOnSkeleton
// Desc: Spawn particles on Skeleton
//--------------------------------------------------------------------------------------------------
void CGameEffect::SpawnParticlesOnSkeleton(IEntity* pEntity, IParticleEmitter* pParticleEmitter, uint32 numParticles,float maxHeightScale) const
{
	if((pEntity) && (numParticles>0) && (pParticleEmitter) && (maxHeightScale>0.0f))
	{
		ICharacterInstance* pCharacter = pEntity->GetCharacter(0);
		if(pCharacter)
		{
			IDefaultSkeleton& rIDefaultSkeleton = pCharacter->GetIDefaultSkeleton();
			ISkeletonPose* pPose = pCharacter->GetISkeletonPose();
			if(pPose)
			{
				Vec3 animPos;
				Quat animRot;

				IActor* pActor = gEnv->pGame->GetIGameFramework()->GetIActorSystem()->GetActor(pEntity->GetId());
				if(pActor) // First try to get animation data
				{
					QuatT animLoc = pActor->GetAnimatedCharacter()->GetAnimLocation();
					animPos = animLoc.t;
					animRot = animLoc.q;
				}
				else // If no actor, then use entity data
				{
					animPos = pEntity->GetWorldPos();
					animRot = pEntity->GetWorldRotation();
				}

				animRot.Invert();

				AABB bbox;
				pEntity->GetLocalBounds(bbox);
				float bbHeight = bbox.max.z - bbox.min.z;
				// Avoid division by 0
				if(bbHeight == 0)
				{
					bbHeight = 0.0001f;
				}

				const uint32 numJoints = rIDefaultSkeleton.GetJointCount();

				for (uint32 i = 0; i < numParticles; ++i)
				{
					int id = cry_random(0U, numJoints - 1);
					int parentId = rIDefaultSkeleton.GetJointParentIDByID(id);

					if(parentId>0)
					{
						QuatT boneQuat = pPose->GetAbsJointByID(id);
						QuatT parentBoneQuat= pPose->GetAbsJointByID(parentId);
						float lerpScale = cry_random(0.0f, 1.0f);

						QuatTS loc(IDENTITY);
						loc.t = LERP(boneQuat.t,parentBoneQuat.t,lerpScale);

						float heightScale = ((loc.t.z - bbox.min.z) / bbHeight);
						if(heightScale < maxHeightScale)
						{
							loc.t = loc.t * animRot;
							loc.t = loc.t + animPos;

							pParticleEmitter->EmitParticle(NULL, NULL, &loc);
						}
					}
				}
			}
		}
	}
}//-------------------------------------------------------------------------------------------------
Ejemplo n.º 3
0
void CVehicleDamageBehaviorBlowTire::DamagePlayers()
{
	// check for the nasty case when the player is shooting at the vehicle tires while prone 
	// under or behind the car, In that case the player should get killed by the vehicle, 
	// otherwise he gets stuck forever. Note that he should only get killed when the tier
	// is actually destroyed and not by collision resulting by the impulse added by just 
	// shooting at the tiers. Unfortunately using physics for doing this check is not reliable
	// enough so we have to check it explicitly
	
	IEntityPhysicalProxy *pPhysicsProxy = (IEntityPhysicalProxy*)m_pVehicle->GetEntity()->GetProxy(ENTITY_PROXY_PHYSICS);
	if (!pPhysicsProxy)
		return;

	AABB bbox;
	pPhysicsProxy->GetWorldBounds( bbox );

	IPhysicalWorld *pWorld = gEnv->pSystem->GetIPhysicalWorld();
	IPhysicalEntity **ppColliders;
	// check entities in collision with the car
	int cnt = pWorld->GetEntitiesInBox( bbox.min,bbox.max, ppColliders,ent_living);
	for (int i = 0; i < cnt; i++)
	{

		IEntity *pEntity = gEnv->pEntitySystem->GetEntityFromPhysics( ppColliders[i] );
		if (!pEntity)
			continue;
		
		// skip the vehicle itself
		if (pEntity==m_pVehicle->GetEntity())
			continue;

		IPhysicalEntity *pPhysEnt = pEntity->GetPhysics();
		if (!pPhysEnt) 
			continue;

		IActor* pActor = gEnv->pGame->GetIGameFramework()->GetIActorSystem()->GetActor(pEntity->GetId());            
		if(!pActor)
			continue;

		//Jan M.: the player is killed when he entered the vehicle while prone although he is still passenger!
		if(m_pVehicle == pActor->GetLinkedVehicle())
			continue;

		//the player must be prone under the vehicle
		IAnimatedCharacter * animatedCharacter=pActor->GetAnimatedCharacter();
		if (!animatedCharacter)
			continue;

		int stance = animatedCharacter->GetCurrentStance();
		if (stance!=STANCE_PRONE)
			continue;

		pe_player_dimensions dim;
		if (!pPhysEnt->GetParams(&dim))
			continue;
		// position returned is at entity's feet, add head position from physics
		Vec3 vPos1=pEntity->GetPos();
		vPos1.z = vPos1.z + dim.heightHead;

		float fZ=bbox.GetCenter().z;
		if (vPos1.z>fZ)
			continue; // not under the vehicle

		// at this point we have a collision with the car moving down and the guy prone under the car, it is safe
		// to assume he has been squished so let's kill him.
		if (gEnv->bServer && pActor->GetHealth()>0)
		{
			// adding a server hit to make it working in MP
			IGameRules *pGameRules = gEnv->pGame->GetIGameFramework()->GetIGameRulesSystem()->GetCurrentGameRules();
			if (pGameRules)
			{
				HitInfo hit;

				EntityId shooterId=m_pVehicle->GetEntityId();
				if (m_pVehicle->GetDriver())
					shooterId=m_pVehicle->GetDriver()->GetEntityId();					

				hit.targetId = pEntity->GetId();      
				hit.shooterId = shooterId;
				hit.weaponId = m_pVehicle->GetEntityId();
				hit.damage = 1000.f;
				hit.type = 0;
				hit.pos = pActor->GetEntity()->GetWorldPos();

				pGameRules->ServerHit(hit); 
			}  
		} 
	} //i
}
//------------------------------------------------------------------------
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;
}