//------------------------------------------------------------------------ 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); } } }
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); }
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); }
//------------------------------------------ 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); } } } } }