//------------------------------------------------------------------------ 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 CVehicleDamageBehaviorBurn::Update(const float deltaTime) { m_timeCounter -= deltaTime; if (m_timeCounter <= 0.0f) { CGameRules *pGameRules = g_pGame->GetGameRules(); if (pGameRules && gEnv->bServer) { Vec3 worldPos; if (m_pHelper) worldPos = m_pHelper->GetWorldTM().GetTranslation(); else worldPos = m_pVehicle->GetEntity()->GetWorldTM().GetTranslation(); SEntityProximityQuery query; query.box = AABB(worldPos-Vec3(m_radius), worldPos+Vec3(m_radius)); gEnv->pEntitySystem->QueryProximity(query); IEntity* pEntity = 0; for (int i = 0; i < query.nCount; ++i) { if ((pEntity = query.pEntities[i]) && pEntity->GetPhysics()) { float damage = (pEntity->GetId() == m_pVehicle->GetEntityId()) ? m_selfDamage : m_damage; // SNH: need to check vertical distance here as the QueryProximity() call seems to work in 2d only Vec3 pos = pEntity->GetWorldPos(); if(abs(pos.z - worldPos.z) < m_radius) { if (damage > 0.f) { HitInfo hitInfo(m_shooterId, pEntity->GetId(), m_pVehicle->GetEntityId(), -1, m_radius); hitInfo.damage = damage; hitInfo.pos = worldPos; hitInfo.type = pGameRules->GetHitTypeId("fire"); pGameRules->ServerHit(hitInfo); } } } } if (gEnv->pAISystem) gEnv->pAISystem->RegisterDamageRegion(this, Sphere(worldPos, m_radius)); } m_timeCounter = m_interval; } m_pVehicle->NeedsUpdate(); }
//------------------------------------------------------------------------ void CRock::HandleEvent(const SGameObjectEvent &event) { CProjectile::HandleEvent(event); if (event.event == eGFE_OnCollision) { if (m_destroying) return; EventPhysCollision *pCollision = reinterpret_cast<EventPhysCollision *>(event.ptr); if (!pCollision) return; IEntity *pTarget = pCollision->iForeignData[1]==PHYS_FOREIGN_ID_ENTITY ? (IEntity*)pCollision->pForeignData[1]:0; if (!pTarget || pTarget->GetId()==m_ownerId || pTarget->GetId()==GetEntityId()) return; Vec3 dir(0, 0, 0); if (pCollision->vloc[0].GetLengthSquared() > 1e-6f) dir = pCollision->vloc[0].GetNormalized(); CGameRules *pGameRules = g_pGame->GetGameRules(); HitInfo hitInfo(m_ownerId, pTarget?pTarget->GetId():0, m_weaponId, m_fmId, 0.0f, pGameRules->GetHitMaterialIdFromSurfaceId(pCollision->idmat[1]), pCollision->partid[1], pGameRules->GetHitTypeId("melee"), pCollision->pt, dir, pCollision->n); hitInfo.remote = IsRemote(); hitInfo.projectileId = GetEntityId(); if (!hitInfo.remote) hitInfo.seq=m_seq; hitInfo.damage = m_damage; if (m_weaponId) { CWeapon *pWeapon=GetWeapon(); if (pWeapon && pWeapon->GetForcedHitMaterial() != -1) hitInfo.material=pGameRules->GetHitMaterialIdFromSurfaceId(pWeapon->GetForcedHitMaterial()); } pGameRules->ClientHit(hitInfo); if(m_damage>10) m_damage =(int)(m_damage*0.5f); } }
void CBurnEffectManager::ApplySurroundingDamage(float deltaTime) { const float damageTime = 0.5f; m_damageTimeOut -= deltaTime; if (m_damageTimeOut > 0.0f) return; m_damageTimeOut += damageTime; CGameRules* pGameRules = g_pGame->GetGameRules(); if (pGameRules) { for (TBurnPoints::iterator it = m_burnPoints.begin(); it != m_burnPoints.end(); ++it) { const int hitType = it->m_hitType; const float damagePerSecond = it->m_shootByPlayer ? it->m_pBurnParams->m_damagePerSecond : it->m_pBurnParams->m_damagePerSecond_AI; const float damage = damagePerSecond * damageTime * it->m_accumulation; if (damage == 0.0f) continue; const Vec3 radius = Vec3(it->m_radius, it->m_radius, it->m_radius); SEntityProximityQuery query; query.box.min = it->m_position - radius; query.box.max = it->m_position + radius; gEnv->pEntitySystem->QueryProximity(query); for (int i = 0; i < query.nCount; ++i) { if (IEntity* pEntity = query.pEntities[i]) { if (ShouldBurnPointInflictDamageOntoEntity(*it, pEntity)) { HitInfo hitInfo(0, pEntity->GetId(), 0, damagePerSecond, 0.0f, 0, 0, hitType, it->m_position, Vec3(ZERO), Vec3(ZERO)); pGameRules->ClientHit(hitInfo); } } } } } }
void CDangerousRigidBody::ProcessEvent( SEntityEvent& event ) { switch(event.event) { case ENTITY_EVENT_COLLISION: { if(m_dangerous) { EventPhysCollision *pCollision = (EventPhysCollision *)(event.nParam[0]); if(pCollision->pEntity[0] && pCollision->pEntity[1]) { IPhysicalEntity* pOtherEntityPhysics = GetEntity()->GetPhysics() != pCollision->pEntity[0] ? pCollision->pEntity[0] : pCollision->pEntity[1]; if( IEntity* pOtherEntity = gEnv->pEntitySystem->GetEntityFromPhysics(pOtherEntityPhysics) ) { EntityId localClientId = gEnv->pGame->GetIGameFramework()->GetClientActorId(); if(pOtherEntity->GetId() == localClientId) //Handle collision locally { float currentTime = gEnv->pTimer->GetFrameStartTime().GetSeconds(); if(currentTime - m_lastHitTime > m_timeBetweenHits) { CGameRules* pGameRules = g_pGame->GetGameRules(); bool sameTeam = m_activatorTeam && (pGameRules->GetTeam(localClientId) == m_activatorTeam); float damageDealt = !sameTeam ? m_damageDealt : g_pGameCVars->g_friendlyfireratio * m_damageDealt; Vec3 rigidBodyPos = GetEntity()->GetWorldPos(); HitInfo hitInfo(0, localClientId, 0, damageDealt, 0.0f, 0, 0, sDangerousRigidBodyHitTypeId, rigidBodyPos, (pOtherEntity->GetWorldPos()-rigidBodyPos).GetNormalized(), Vec3(ZERO)); pGameRules->ClientHit(hitInfo); m_lastHitTime = currentTime; } } } } } } break; case ENTITY_EVENT_RESET: { Reset(); } break; } }
void CWaterPuddle::ApplyHit(const SActorData& actorData, EntityId shooterId, EntityId weaponId, float damage, int hitTypeId, float waterLevel, IParticleEffect* hitEffect) { CGameRules* pGameRules = g_pGame->GetGameRules(); const Vec3 hitPosition = actorData.position + Vec3Constants<float>::fVec3_OneZ; const Vec3 hitDirection = hitPosition.GetNormalized(); HitInfo hitInfo(shooterId, actorData.entityId, weaponId, damage, 0.0f, -1, -1, hitTypeId, hitPosition, hitDirection, -hitDirection); hitInfo.projectileId = GetEntityId(); hitInfo.aimed = false; pGameRules->ClientHit(hitInfo); const EntityEffects::SEffectSpawnParams effectSpawnParams(Vec3(actorData.position.x, actorData.position.y, waterLevel)); EntityEffects::SpawnParticleFX(hitEffect, effectSpawnParams); }
void CVTOLVehicleManager::DestructionDamageRatioReached(IVehicle* pVehicle, SVTOLInfo& info, float frameTime) { pVehicle->ClientEvictAllPassengers(); LockSeats(pVehicle, true); IPhysicalEntity* pPhysics = pVehicle->GetEntity()->GetPhysics(); if(pPhysics) { DestroyVTOL(pVehicle->GetEntity(), info); CGameRules::SModuleRMIEntityParams params; params.m_listenerIndex = m_moduleRMIIndex; params.m_entityId = info.entityId; params.m_data = eRMITypeSingleEntity_vtol_destroyed; // RMI will patch entityIDs between clients g_pGame->GetGameRules()->GetGameObject()->InvokeRMIWithDependentObject(CGameRules::ClModuleRMISingleEntity(), params, eRMI_ToRemoteClients, info.entityId); } //Damage any players inside CGameRules* pGameRules = g_pGame->GetGameRules(); CVehicleMovementMPVTOL* pMovement = static_cast<CVehicleMovementMPVTOL*>(pVehicle->GetMovement()); if (pGameRules && pMovement) { EntityId destroyerId = pMovement->GetDestroyerId(); HitInfo hitInfo(destroyerId, 0, pVehicle->GetEntityId(), g_pGameCVars->g_VTOLOnDestructionPlayerDamage, 0, 0, 0, CGameRules::EHitType::VTOLExplosion); TPlayerList& currentPlayerList = info.playersInside; TPlayerList::const_iterator iter = currentPlayerList.begin(); TPlayerList::const_iterator end = currentPlayerList.end(); while(iter != end) { hitInfo.targetId = *iter; pGameRules->ServerHit(hitInfo); ++iter; } } }
Foam::pointIndexHit Foam::octree<Type>::findLine ( const point& treeStart, const point& treeEnd ) const { // Initialize to a miss pointIndexHit hitInfo(false, treeStart, -1); const vector dir(treeEnd - treeStart); // Current line segment to search point start(treeStart); point end(treeEnd); while (true) { // Find nearest treeLeaf intersected by line point leafIntPoint; const treeLeaf<Type>* leafPtr = findLeafLine ( start, end, leafIntPoint ); if (!leafPtr) { // Reached end of string of treeLeaves to be searched. Return // whatever we have found so far. break; } // Inside treeLeaf find nearest intersection scalar minS = GREAT; const labelList& indices = leafPtr->indices(); forAll(indices, elemI) { label index = indices[elemI]; point pt; bool hit = shapes().intersects(index, start, end, pt); if (hit) { // Check whether intersection nearer p scalar s = (pt - treeStart) & dir; if (s < minS) { minS = s; // Update hit info hitInfo.setHit(); hitInfo.setPoint(pt); hitInfo.setIndex(index); // Update segment to search end = pt; } } } if (hitInfo.hit()) { // Found intersected shape. break; } // Start from end of current leaf start = leafIntPoint; }
void CTacBullet::HandleEvent(const SGameObjectEvent &event) { if (m_destroying) return; CProjectile::HandleEvent(event); if (event.event == eGFE_OnCollision) { EventPhysCollision *pCollision = reinterpret_cast<EventPhysCollision *>(event.ptr); if (!pCollision) return; IEntity *pTarget = pCollision->iForeignData[1]==PHYS_FOREIGN_ID_ENTITY ? (IEntity*)pCollision->pForeignData[1]:0; if (pTarget) { CGameRules *pGameRules = g_pGame->GetGameRules(); EntityId targetId = pTarget->GetId(); CActor *pActor = (CActor *)gEnv->pGame->GetIGameFramework()->GetIActorSystem()->GetActor(targetId); if(pActor && pActor->CanSleep()) { if(pActor->GetLinkedVehicle() && !gEnv->bMultiplayer) { SleepTargetInVehicle(m_ownerId,pActor); } else if(IEntity* pOwnerEntity = gEnv->pEntitySystem->GetEntity(m_ownerId)) { if (pTarget->GetAI() && !pTarget->GetAI()->IsFriendly(pOwnerEntity->GetAI(), false)) { float sleepTime = 30.0f; if(m_pAmmoParams) sleepTime = m_pAmmoParams->sleepTime; SimpleHitInfo info(m_ownerId, targetId, m_weaponId, 1, sleepTime); // 0=tag,1=tac info.remote=IsRemote(); pGameRules->ClientSimpleHit(info); } } } else { Vec3 dir(0, 0, 0); if (pCollision->vloc[0].GetLengthSquared() > 1e-6f) dir = pCollision->vloc[0].GetNormalized(); HitInfo hitInfo(m_ownerId, pTarget->GetId(), m_weaponId, (float)m_damage, 0.0f, pGameRules->GetHitMaterialIdFromSurfaceId(pCollision->idmat[1]), pCollision->partid[1], m_hitTypeId, pCollision->pt, dir, pCollision->n); hitInfo.remote = IsRemote(); hitInfo.projectileId = GetEntityId(); hitInfo.bulletType = m_pAmmoParams->bulletType; pGameRules->ClientHit(hitInfo); } } else if (pCollision->pEntity[0]->GetType() == PE_PARTICLE) { float bouncy, friction; uint32 pierceabilityMat; gEnv->pPhysicalWorld->GetSurfaceParameters(pCollision->idmat[1], bouncy, friction, pierceabilityMat); pierceabilityMat&=sf_pierceable_mask; pe_params_particle params; if(pCollision->pEntity[0]->GetParams(¶ms)==0) SetDefaultParticleParams(¶ms); if (pierceabilityMat>params.iPierceability && pCollision->idCollider!=-1) return; } Destroy(); } }
void Foam::searchableSurfaceCollection::findNearest ( const pointField& samples, scalarField& minDistSqr, List<pointIndexHit>& nearestInfo, labelList& nearestSurf ) const { // Initialise nearestInfo.setSize(samples.size()); nearestInfo = pointIndexHit(); nearestSurf.setSize(samples.size()); nearestSurf = -1; List<pointIndexHit> hitInfo(samples.size()); const scalarField localMinDistSqr(samples.size(), GREAT); forAll(subGeom_, surfI) { subGeom_[surfI].findNearest ( cmptDivide // Transform then divide ( transform_[surfI].localPosition(samples), scale_[surfI] ), localMinDistSqr, hitInfo ); forAll(hitInfo, pointI) { if (hitInfo[pointI].hit()) { // Rework back into global coordinate sys. Multiply then // transform point globalPt = transform_[surfI].globalPosition ( cmptMultiply ( hitInfo[pointI].rawPoint(), scale_[surfI] ) ); scalar distSqr = magSqr(globalPt - samples[pointI]); if (distSqr < minDistSqr[pointI]) { minDistSqr[pointI] = distSqr; nearestInfo[pointI].setPoint(globalPt); nearestInfo[pointI].setHit(); nearestInfo[pointI].setIndex ( hitInfo[pointI].index() + indexOffset_[surfI] ); nearestSurf[pointI] = surfI; } } } }
//------------------------------------------------------------------------ void CBullet::HandleEvent(const SGameObjectEvent &event) { FUNCTION_PROFILER(GetISystem(), PROFILE_GAME); CProjectile::HandleEvent(event); if (event.event == eGFE_OnCollision) { if (m_destroying) return; EventPhysCollision *pCollision = reinterpret_cast<EventPhysCollision *>(event.ptr); if (!pCollision) return; IEntity *pTarget = pCollision->iForeignData[1]==PHYS_FOREIGN_ID_ENTITY ? (IEntity*)pCollision->pForeignData[1]:0; //Only process hits that have a target if(pTarget) { Vec3 dir(0, 0, 0); if (pCollision->vloc[0].GetLengthSquared() > 1e-6f) dir = pCollision->vloc[0].GetNormalized(); CGameRules *pGameRules = g_pGame->GetGameRules(); IActor* pActor = g_pGame->GetIGameFramework()->GetIActorSystem()->GetActor(m_ownerId); bool ok = true; if(!gEnv->bMultiplayer && pActor && pActor->IsPlayer()) { IActor* pAITarget = g_pGame->GetIGameFramework()->GetIActorSystem()->GetActor(pTarget->GetId()); if(pAITarget && pTarget->GetAI() && pTarget->GetAI()->IsFriendly(pActor->GetEntity()->GetAI(), false)) { pGameRules->SetEntityToIgnore(pTarget->GetId()); ok = false; } } if(ok) { HitInfo hitInfo(m_ownerId, pTarget->GetId(), m_weaponId, (float)m_damage, 0.0f, pGameRules->GetHitMaterialIdFromSurfaceId(pCollision->idmat[1]), pCollision->partid[1], m_hitTypeId, pCollision->pt, dir, pCollision->n); hitInfo.remote = IsRemote(); hitInfo.projectileId = GetEntityId(); hitInfo.bulletType = m_pAmmoParams->bulletType; pGameRules->ClientHit(hitInfo); // Notify AI if (gEnv->pAISystem && !gEnv->bMultiplayer) { static int htMelee = pGameRules->GetHitTypeId("melee"); if (m_ownerId && m_hitTypeId != htMelee) { ISurfaceType *pSurfaceType = pGameRules->GetHitMaterial(hitInfo.material); const ISurfaceType::SSurfaceTypeAIParams* pParams = pSurfaceType ? pSurfaceType->GetAIParams() : 0; const float radius = pParams ? pParams->fImpactRadius : 2.5f; const float soundRadius = pParams ? pParams->fImpactSoundRadius : 20.0f; // Associate event with vehicle if the shooter is in a vehicle (tank cannon shot, etc) EntityId ownerId = m_ownerId; if (pActor && pActor->GetLinkedVehicle() && pActor->GetLinkedVehicle()->GetEntityId()) ownerId = pActor->GetLinkedVehicle()->GetEntityId(); SAIStimulus stim(AISTIM_BULLET_HIT, 0, ownerId, 0, pCollision->pt, ZERO, radius); gEnv->pAISystem->RegisterStimulus(stim); SAIStimulus stimSound(AISTIM_SOUND, AISOUND_COLLISION_LOUD, ownerId, 0, pCollision->pt, ZERO, soundRadius, AISTIMPROC_FILTER_LINK_WITH_PREVIOUS); gEnv->pAISystem->RegisterStimulus(stimSound); } } } } else { // Notify AI // The above case only catches entity vs. entity hits, the AI is interested in all hits. if (gEnv->pAISystem && !gEnv->bMultiplayer) { CGameRules *pGameRules = g_pGame->GetGameRules(); static int htMelee = pGameRules->GetHitTypeId("melee"); if (m_ownerId && m_hitTypeId != htMelee) { int material = pGameRules->GetHitMaterialIdFromSurfaceId(pCollision->idmat[1]); ISurfaceType *pSurfaceType = pGameRules->GetHitMaterial(material); const ISurfaceType::SSurfaceTypeAIParams* pParams = pSurfaceType ? pSurfaceType->GetAIParams() : 0; const float radius = pParams ? pParams->fImpactRadius : 2.5f; const float soundRadius = pParams ? pParams->fImpactSoundRadius : 20.0f; // 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(m_ownerId); if (pActor && pActor->GetLinkedVehicle() && pActor->GetLinkedVehicle()->GetEntityId()) ownerId = pActor->GetLinkedVehicle()->GetEntityId(); SAIStimulus stim(AISTIM_BULLET_HIT, 0, ownerId, 0, pCollision->pt, ZERO, radius); gEnv->pAISystem->RegisterStimulus(stim); SAIStimulus stimSound(AISTIM_SOUND, AISOUND_COLLISION_LOUD, ownerId, 0, pCollision->pt, ZERO, soundRadius, AISTIMPROC_FILTER_LINK_WITH_PREVIOUS); gEnv->pAISystem->RegisterStimulus(stimSound); } } } if (pCollision->pEntity[0]->GetType() == PE_PARTICLE) { float bouncy, friction; uint32 pierceabilityMat; gEnv->pPhysicalWorld->GetSurfaceParameters(pCollision->idmat[1], bouncy, friction, pierceabilityMat); pierceabilityMat&=sf_pierceable_mask; pe_params_particle params; if(pCollision->pEntity[0]->GetParams(¶ms)==0) SetDefaultParticleParams(¶ms); //Under water trail Vec3 pos=pCollision->pt; if ((pCollision->idmat[1] == CBullet::m_waterMaterialId) && (pCollision->pEntity[1]!=gEnv->pPhysicalWorld->AddGlobalArea() || !gEnv->p3DEngine->GetVisAreaFromPos(pos))) { //Reduce drastically bullet velocity (to be able to see the trail effect) //pe_params_particle pparams; //if(m_pPhysicalEntity->GetParams(&pparams)==0) //SetDefaultParticleParams(&pparams); //pparams.velocity = 25.0f; //m_pPhysicalEntity->SetParams(&pparams); if(m_trailUnderWaterId<0) { //Check terrain/against water level float terrainHeight = gEnv->p3DEngine->GetTerrainElevation(pCollision->pt.x,pCollision->pt.y); float waterLevel = gEnv->p3DEngine->GetWaterLevel(&(pCollision->pt)); if(waterLevel>terrainHeight) { TrailEffect(true,true); return; } } } if (pierceabilityMat<=params.iPierceability || pCollision->idCollider==-1) //Do not destroy if collides water Destroy(); } } }
void ray::hit(body *b, const vec3 &n, float d, int id) { // interpolate distance [0..1] between points vec3 p = _p0 + (_p1 - _p0) * d; _hitCache.push_back(hitInfo(b, p, n, d)); }