//------------------------------------------------------------------------
void CCannonBall::ProcessHit(CGameRules& gameRules, const EventPhysCollision& collision, IEntity& target, float damage, int hitMatId, const Vec3& hitDir)
{
	if(damage > 0.f)
	{
		EntityId targetId = target.GetId();
		bool alreadyHit = CheckForPreviousHit(targetId, damage);

		if(!alreadyHit)
		{
			HitInfo hitInfo(m_ownerId ? m_ownerId : m_hostId, targetId, m_weaponId,
				damage, 0.0f, hitMatId, collision.partid[1],
				m_hitTypeId, collision.pt, hitDir, collision.n);

			hitInfo.remote = IsRemote();
			hitInfo.projectileId = GetEntityId();
			hitInfo.bulletType = m_pAmmoParams->bulletType;
			hitInfo.knocksDown = CheckAnyProjectileFlags(ePFlag_knocksTarget) && ( damage > m_minDamageForKnockDown );
			hitInfo.knocksDownLeg = m_chanceToKnockDownLeg>0 && damage>m_minDamageForKnockDownLeg && m_chanceToKnockDownLeg>(int)Random(100);
			hitInfo.penetrationCount = m_penetrationCount;
			hitInfo.hitViaProxy = CheckAnyProjectileFlags(ePFlag_firedViaProxy);
			hitInfo.aimed = CheckAnyProjectileFlags(ePFlag_aimedShot);

			IPhysicalEntity* pPhysicalEntity = collision.pEntity[1];
			if (pPhysicalEntity && pPhysicalEntity->GetType() == PE_ROPE)
			{
				hitInfo.partId = GetRopeBoneId(collision, target, pPhysicalEntity);
			}

			gameRules.ClientHit(hitInfo);

			ReportHit(targetId);
		}
	}
}
Esempio n. 2
0
void CC4Projectile::OnServerExplosion( const ExplosionInfo& explosionInfo )
{
	if(gEnv->bMultiplayer)
	{
		//Check for explosions
		IPhysicalEntity *pPE = GetEntity()->GetPhysics();
		if(pPE)
		{
			float affected = gEnv->pSystem->GetIPhysicalWorld()->IsAffectedByExplosion(pPE);
			if(affected > 0.001f && m_hitPoints > 0 && !CheckAnyProjectileFlags(ePFlag_destroying))
			{
				//Only enemy explosions
				if(CGameRules* pGameRules = g_pGame->GetGameRules())
				{
					EntityId explosionTeamId = pGameRules->GetTeam(explosionInfo.shooterId);
					if(explosionTeamId != m_teamId)
					{
						m_armed = true;
						Detonate();
						return;
					}
				}		
			}
		}
	}

	CProjectile::OnServerExplosion(explosionInfo);
}
Esempio n. 3
0
void CC4Projectile::OnHit( const HitInfo& hitInfo)
{
	if(gEnv->bMultiplayer)
	{
		if(hitInfo.targetId == GetEntityId() && m_hitPoints > 0 && !CheckAnyProjectileFlags(ePFlag_destroying))
		{
			if(CGameRules* pGameRules = g_pGame->GetGameRules())
			{
				EntityId shooterTeamId = pGameRules->GetTeam(hitInfo.shooterId);
				if(m_teamId == 0 || shooterTeamId != m_teamId)
				{
					m_hitPoints -= (int)hitInfo.damage;
					if(m_hitPoints <= 0)
					{
						//We need to be armed or detonate won't work. As this is the last frame before the C4 vanishes, it won't have any knock-on.
						m_armed = true;

						//We need the damage to be credited to the person that shot the C4, which means the owner will be temporarily set to
						//	the shooter for the duration of the Detonate call.

						EntityId originalOwnerId = m_ownerId;

						m_ownerId = hitInfo.shooterId;
						
						Detonate();

						m_ownerId = originalOwnerId;
					}
				}
			}
		}

		return;
	}

	CProjectile::OnHit(hitInfo);
}
Esempio n. 4
0
//------------------------------------------
void CC4Projectile::HandleEvent(const SGameObjectEvent &event)
{
	if (CheckAnyProjectileFlags(ePFlag_destroying))
		return;

	CProjectile::HandleEvent(event);

	if (event.event == eGFE_OnCollision)
	{
		EventPhysCollision *pCollision = (EventPhysCollision *)event.ptr;

		if(pCollision && pCollision->pEntity[0]->GetType()==PE_PARTICLE)
		{
			float bouncy, friction;
			uint32 pierceabilityMat;
			gEnv->pPhysicalWorld->GetSurfaceParameters(pCollision->idmat[1], bouncy, friction, pierceabilityMat);
			pierceabilityMat &= sf_pierceable_mask;
			uint32 pierceabilityProj = GetAmmoParams().pParticleParams ? GetAmmoParams().pParticleParams->iPierceability : 13;
			if (pierceabilityMat > pierceabilityProj)
				return;

			if(gEnv->bMultiplayer)
			{
				// Don't stick to weapons.
				if(pCollision->iForeignData[1]==PHYS_FOREIGN_ID_ENTITY)
				{
					if(IEntity* pEntity = (IEntity*)pCollision->pForeignData[1])
					{
						if(IItem* pItem = g_pGame->GetIGameFramework()->GetIItemSystem()->GetItem(pEntity->GetId()))
						{
							if(pItem->GetIWeapon())
							{
								return;
							}
						}
					}
				}
			}

			// Notify AI system about the C4.
			if (gEnv->pAISystem)
			{
				// Associate event with vehicle if the shooter is in a vehicle (tank cannon shot, etc)
				EntityId ownerId = m_ownerId;
				IActor* pActor = g_pGame->GetIGameFramework()->GetIActorSystem()->GetActor(ownerId);
				if (pActor && pActor->GetLinkedVehicle() && pActor->GetLinkedVehicle()->GetEntityId())
					ownerId = pActor->GetLinkedVehicle()->GetEntityId();

				SAIStimulus stim(AISTIM_EXPLOSION, 0, ownerId, GetEntityId(),
					GetEntity()->GetWorldPos(), ZERO, 12.0f, AISTIMPROC_ONLY_IF_VISIBLE);
				gEnv->pAISystem->RegisterStimulus(stim);

				SAIStimulus soundStim(AISTIM_SOUND, AISOUND_COLLISION, ownerId, GetEntityId(),
					GetEntity()->GetWorldPos(), ZERO, 8.0f);
				gEnv->pAISystem->RegisterStimulus(soundStim);
			}
		}

		if (gEnv->bServer && !m_stickyProjectile.IsStuck())
			m_stickyProjectile.Stick(
				CStickyProjectile::SStickParams(this, pCollision, CStickyProjectile::eO_AlignToSurface));
	}
}
//------------------------------------------------------------------------
void CCannonBall::HandleEvent(const SGameObjectEvent &event)
{
	FUNCTION_PROFILER(GetISystem(), PROFILE_GAME);

	BaseClass::HandleEvent(event);

	if (event.event == eGFE_OnCollision)
	{
		if (CheckAnyProjectileFlags(ePFlag_destroying))
			return;

		EventPhysCollision *pCollision = reinterpret_cast<EventPhysCollision *>(event.ptr);
		if (!pCollision)
			return;

		float finalDamage = GetFinalDamage(pCollision->pt);
		if (finalDamage <= 0.0f)
			m_alive = false;
        
		IEntity *pTarget = pCollision->iForeignData[1]==PHYS_FOREIGN_ID_ENTITY ? (IEntity*)pCollision->pForeignData[1]:0;
		CGameRules *pGameRules = g_pGame->GetGameRules();
		const int hitMatId = pCollision->idmat[1];

		Vec3 hitDir(ZERO);
		if (pCollision->vloc[0].GetLengthSquared() > 1e-6f)
		{
			hitDir = pCollision->vloc[0].GetNormalized();
		}

		const bool bProcessCollisionEvent = ProcessCollisionEvent(pTarget);
		if (bProcessCollisionEvent)
		{
			//================================= Process Hit =====================================
			//Only process hits that have a target
			if(pTarget)
			{
				if(FilterFriendlyAIHit(pTarget) == false)
				{
					ProcessHit(*pGameRules, *pCollision, *pTarget, finalDamage, hitMatId, hitDir);
				}
			}
			//====================================~ Process Hit ======================================

			//==================================== Notify AI    ======================================
			if (gEnv->pAISystem)
			{
				if (gEnv->pEntitySystem->GetEntity(m_ownerId))
				{
					ISurfaceType *pSurfaceType = gEnv->p3DEngine->GetMaterialManager()->GetSurfaceType(hitMatId);
					const ISurfaceType::SSurfaceTypeAIParams* pParams = pSurfaceType ? pSurfaceType->GetAIParams() : 0;
					const float radius = pParams ? pParams->fImpactRadius : 2.5f;
					const float soundRadius = pParams ? pParams->fImpactSoundRadius : 20.0f;

					SAIStimulus stim(AISTIM_BULLET_HIT, 0, m_ownerId, pTarget ? pTarget->GetId() : 0, pCollision->pt, pCollision->vloc[0].GetNormalizedSafe(ZERO), radius);
					gEnv->pAISystem->RegisterStimulus(stim);

					SAIStimulus stimSound(AISTIM_SOUND, AISTIM_BULLET_HIT, m_ownerId, 0, pCollision->pt, ZERO, soundRadius);
					gEnv->pAISystem->RegisterStimulus(stim);
				}
			}
			//=========================================~ Notify AI ===============================
		}

		//========================================= Surface Pierceability ==============================
		if (pCollision->pEntity[0]->GetType() == PE_PARTICLE)
		{
			const SPierceabilityParams& pierceabilityParams = m_pAmmoParams->pierceabilityParams;

			//If collided water
			if( s_materialLookup.IsMaterial( pCollision->idmat[1], CProjectile::SMaterialLookUp::eType_Water ) )
			{
				if(pierceabilityParams.DestroyOnWaterImpact())
				{
					DestroyAtHitPosition(pCollision->pt);
				}
				else
				{
					EmitUnderwaterTracer(pCollision->pt, pCollision->pt + (pCollision->vloc[0].GetNormalizedSafe() * 100.0f));
				}
			}
			else if (m_pAmmoParams->bounceableBullet == 0)
			{
				float bouncy, friction;
				uint32 pierceabilityMat;
				gEnv->pPhysicalWorld->GetSurfaceParameters(pCollision->idmat[1], bouncy, friction, pierceabilityMat);
				pierceabilityMat &= sf_pierceable_mask;
				
				const bool terrainHit = (pCollision->idCollider == -1);

				bool thouShallNotPass = terrainHit;
				if (!CheckAnyProjectileFlags(ePFlag_ownerIsPlayer))
					thouShallNotPass = thouShallNotPass || pierceabilityParams.DestroyOnImpact(pierceabilityMat);

				if (!thouShallNotPass)
					HandlePierceableSurface(pCollision, pTarget, hitDir, bProcessCollisionEvent);

				const bool destroy = thouShallNotPass || ShouldDestroyCannonBall();
				if (destroy)
				{
					DestroyAtHitPosition(pCollision->pt);
				}
			}
		}
	}
}