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