void CMelee::Impulse(const Vec3 &pt, const Vec3 &dir, const Vec3 &normal, IPhysicalEntity *pCollider, EntityId collidedEntityId, int partId, int ipart, int surfaceIdx, int hitTypeID, int iPrim) { if (pCollider && m_pMeleeParams->meleeparams.impulse>0.001f) { CActor* pOwnerActor = m_pWeapon->GetOwnerActor(); const SPlayerMelee& meleeCVars = g_pGameCVars->pl_melee; const SMeleeParams& meleeParams = m_pMeleeParams->meleeparams; float impulse = meleeParams.impulse; bool aiShooter = pOwnerActor ? !pOwnerActor->IsPlayer() : true; bool delayImpulse = false; float impulseScale = 1.0f; //[kirill] add impulse to phys proxy - to make sure it's applied to cylinder as well (not only skeleton) - so that entity gets pushed // if no pEntity - do it old way IEntity * pEntity = gEnv->pEntitySystem->GetEntity(collidedEntityId); IGameFramework* pGameFramework = g_pGame->GetIGameFramework(); CActor* pTargetActor = static_cast<CActor*>(pGameFramework->GetIActorSystem()->GetActor(collidedEntityId)); if (pEntity && pTargetActor) { //If it's an entity, use the specific impulses if needed, and apply to physics proxy if ( meleeCVars.impulses_enable != SPlayerMelee::ei_Disabled ) { impulse = meleeParams.impulse_actor; bool aiTarget = !pTargetActor->IsPlayer(); if (aiShooter && !aiTarget) { float impulse_ai_to_player = GetImpulseAiToPlayer(); if (impulse_ai_to_player != -1.f) { impulse = impulse_ai_to_player; } } //Delay a bit on death actors, when switching from alive to death, impulses don't apply //I schedule an impulse here, to get rid off the ugly .lua code which was calculating impulses on its own if (pTargetActor->IsDead()) { if (meleeCVars.impulses_enable != SPlayerMelee::ei_OnlyToAlive) { delayImpulse = true; const float actorCustomScale = 1.0f; impulseScale *= actorCustomScale; } else { impulse = 0.0f; } } else if (meleeCVars.impulses_enable == SPlayerMelee::ei_OnlyToDead) { // Always allow impulses for melee from AI to local player // [*DavidR | 27/Oct/2010] Not sure about this if (!(aiShooter && !aiTarget)) impulse = 0.0f; } } else if (pGameFramework->GetIVehicleSystem()->GetVehicle(collidedEntityId)) { impulse = m_pMeleeParams->meleeparams.impulse_vehicle; impulseScale = 1.0f; } } const float fScaledImpulse = impulse * impulseScale; if (fScaledImpulse > 0.0f) { if (!delayImpulse) { m_collisionHelper.Impulse(pCollider, pt, dir * fScaledImpulse, partId, ipart, hitTypeID); } else { //Force up impulse, to make the enemy fly a bit Vec3 newDir = (dir.z < 0.0f) ? Vec3(dir.x, dir.y, 0.1f) : dir; newDir.Normalize(); newDir.x *= fScaledImpulse; newDir.y *= fScaledImpulse; newDir.z *= impulse; if( pTargetActor ) { pe_action_impulse imp; imp.iApplyTime = 0; imp.impulse = newDir; //imp.ipart = ipart; imp.partid = partId; imp.point = pt; pTargetActor->GetImpulseHander()->SetOnRagdollPhysicalizedImpulse( imp ); } else { m_pWeapon->GetScheduler()->TimerAction(100, CSchedulerAction<DelayedImpulse>::Create(DelayedImpulse(*this, collidedEntityId, pt, newDir, partId, ipart, hitTypeID)), true); } } } // scar bullet // m = 0.0125 // v = 800 // energy: 4000 // in this case the mass of the active collider is a player part // so we must solve for v given the same energy as a scar bullet float speed = cry_sqrtf(4000.0f/(80.0f*0.5f)); // 80.0f is the mass of the player if( IRenderNode *pBrush = (IRenderNode*)pCollider->GetForeignData(PHYS_FOREIGN_ID_STATIC) ) { speed = 0.003f; } m_collisionHelper.GenerateArtificialCollision(m_pWeapon->GetOwner(), pCollider, pt, normal, dir * speed, partId, ipart, surfaceIdx, iPrim); } }