//------------------------------------------------------------------------ void CGameRules::ProcessServerHit(const HitInfo &hitInfo) { bool ok=true; // check if shooter is alive CActor *pShooter=GetActorByEntityId(hitInfo.shooterId); if (hitInfo.shooterId) { if (pShooter && pShooter->GetHealth()<=0) ok=false; } if (hitInfo.targetId) { CActor *pTarget=GetActorByEntityId(hitInfo.targetId); if (pTarget && pTarget->GetSpectatorMode()) ok=false; } if (ok) { CreateScriptHitInfo(m_scriptHitInfo, hitInfo); CallScript(m_serverStateScript, "OnHit", m_scriptHitInfo); // call hit listeners if any if (m_hitListeners.empty() == false) { for (size_t i = 0; i < m_hitListeners.size(); ) { size_t count = m_hitListeners.size(); m_hitListeners[i]->OnHit(hitInfo); if (count == m_hitListeners.size()) i++; else continue; } } if (pShooter && hitInfo.shooterId!=hitInfo.targetId && hitInfo.weaponId!=hitInfo.shooterId && hitInfo.weaponId!=hitInfo.targetId && hitInfo.damage>=0) { EntityId params[2]; params[0] = hitInfo.weaponId; params[1] = hitInfo.targetId; m_pGameplayRecorder->Event(pShooter->GetEntity(), GameplayEvent(eGE_WeaponHit, 0, 0, (void *)params)); } if (pShooter) m_pGameplayRecorder->Event(pShooter->GetEntity(), GameplayEvent(eGE_Hit, 0, 0, (void *)hitInfo.weaponId)); if (pShooter) m_pGameplayRecorder->Event(pShooter->GetEntity(), GameplayEvent(eGE_Damage, 0, hitInfo.damage, (void *)hitInfo.weaponId)); } }
//------------------------------------------------------------------------ void CGameRules::ProcessServerHit(const HitInfo &hitInfo) { bool ok=true; // check if shooter is alive CActor *pShooter=GetActorByEntityId(hitInfo.shooterId); if (hitInfo.shooterId) { if (pShooter && pShooter->GetHealth()<=0) ok=false; } if (hitInfo.targetId) { CActor *pTarget=GetActorByEntityId(hitInfo.targetId); if (pTarget && pTarget->GetSpectatorMode()) ok=false; } if (ok) { CreateScriptHitInfo(m_scriptHitInfo, hitInfo); CallScript(m_serverStateScript, "OnHit", m_scriptHitInfo); // call hit listeners if any if (m_hitListeners.empty() == false) { THitListenerVec::iterator iter = m_hitListeners.begin(); while (iter != m_hitListeners.end()) { (*iter)->OnHit(hitInfo); ++iter; } } if (pShooter && hitInfo.shooterId!=hitInfo.targetId && hitInfo.weaponId!=hitInfo.shooterId && hitInfo.weaponId!=hitInfo.targetId && hitInfo.damage>=0) { EntityId params[2]; params[0] = hitInfo.weaponId; params[1] = hitInfo.targetId; m_pGameplayRecorder->Event(pShooter->GetEntity(), GameplayEvent(eGE_WeaponHit, 0, 0, (void *)params)); } if (pShooter) m_pGameplayRecorder->Event(pShooter->GetEntity(), GameplayEvent(eGE_Hit, 0, 0, (void *)hitInfo.weaponId)); if (pShooter) m_pGameplayRecorder->Event(pShooter->GetEntity(), GameplayEvent(eGE_Damage, 0, hitInfo.damage, (void *)hitInfo.weaponId)); } }
void execute(CItem *_this) { CShotgun *fm = (CShotgun *)pWep->GetFireMode(pWep->GetCurrentFireMode()); if(fm->m_reload_was_broken) return; IEntityClass *pAmmoType = fm->GetAmmoType(); if(pWep->IsServer()) { const int ammoCount = pWep->GetAmmoCount(pAmmoType); const int inventoryCount = pWep->GetInventoryAmmoCount(pAmmoType); const int refill = fm->m_pShared->shotgunparams.partial_reload ? 1 : min(inventoryCount, fm->GetClipSize() - ammoCount); pWep->SetAmmoCount(pAmmoType, ammoCount + refill); pWep->SetInventoryAmmoCount(pAmmoType, pWep->GetInventoryAmmoCount(pAmmoType) - refill); } g_pGame->GetIGameFramework()->GetIGameplayRecorder()->Event(pWep->GetOwner(), GameplayEvent(eGE_WeaponReload, pAmmoType->GetName(), 1, (void *)(pWep->GetEntityId()))); if(!fm->m_break_reload) fm->ReloadShell(rzoomed); else fm->EndReload(rzoomed); }
IMPLEMENT_RMI(CGameRules, ClEnteredGame) { if(!gEnv->bServer && m_pGameFramework->GetClientActor()) { CActor* pActor = GetActorByChannelId(m_pGameFramework->GetClientActor()->GetChannelId()); if(pActor) { int status[2]; status[0] = GetTeam(pActor->GetEntityId()); status[1] = pActor->GetSpectatorMode(); m_pGameplayRecorder->Event(pActor->GetEntity(), GameplayEvent(eGE_Connected, 0, 0, (void*)status)); } } return true; }
//----------------------------------------------------- void CThrow::ThrowGrenade() { //Grenade speed scale is always one (for player) CPlayer *pPlayer = static_cast<CPlayer *>(m_pWeapon->GetOwnerActor()); if(pPlayer) { if(pPlayer->IsPlayer()) { m_speed_scale = 1.0f; } else if(pPlayer->GetHealth() <= 0 || pPlayer->GetGameObject()->GetAspectProfile(eEA_Physics) == eAP_Sleep) { return; //Do not throw grenade is player is death (AI "ghost grenades") } //Hide grenade in hand (FP) if(pPlayer->IsClient() && m_pWeapon->GetEntity()->GetClass() == CItem::sOffHandClass) { if(COffHand *pOffHand = static_cast<COffHand *>(m_pWeapon)) { pOffHand->AttachGrenadeToHand(pOffHand->GetCurrentFireMode()); } } } m_pWeapon->SetBusy(false); Shoot(true); m_pWeapon->SetBusy(true); // Luciano - send ammo count game event if(pPlayer) { IEntityClass *pAmmo = m_pShared->fireparams.ammo_type_class; if(pAmmo) { int ammoCount = pPlayer->GetInventory()->GetAmmoCount(pAmmo); g_pGame->GetIGameFramework()->GetIGameplayRecorder()->Event(pPlayer->GetEntity(), GameplayEvent(eGE_AmmoCount, m_pWeapon->GetEntity()/*->GetClass()*/->GetName(), float(ammoCount), (void *)(pAmmo->GetName()))); } } }
IMPLEMENT_RMI(CGameRules, ClEnteredGame) { CPlayer *pClientActor = static_cast<CPlayer *>(m_pGameFramework->GetClientActor()); if (pClientActor) { IEntity *pClientEntity = pClientActor->GetEntity(); const EntityId clientEntityId = pClientEntity->GetId(); if(!gEnv->bServer) { int status[2]; status[0] = GetTeam(clientEntityId); status[1] = pClientActor->GetSpectatorMode(); m_pGameplayRecorder->Event(pClientEntity, GameplayEvent(eGE_Connected, 0, 0, (void *)status)); } } return true; }
//------------------------------------------------------------------------ int CScriptBind_Action::SendGameplayEvent(IFunctionHandler* pH, ScriptHandle entityId, int event) { const char *desc=0; float value=0.0f; ScriptHandle hdl; const char *str_data=0; if (pH->GetParamCount()>2 && pH->GetParamType(3)==svtString) pH->GetParam(3, desc); if (pH->GetParamCount()>3 && pH->GetParamType(4)==svtNumber) pH->GetParam(4, value); if (pH->GetParamCount()>4 && pH->GetParamType(5)==svtPointer) pH->GetParam(5, hdl); if (pH->GetParamCount()>5 && pH->GetParamType(6)==svtString) pH->GetParam(6, str_data); IEntity* pEntity = gEnv->pEntitySystem->GetEntity((EntityId)entityId.n); CCryAction::GetCryAction()->GetIGameplayRecorder()->Event(pEntity, GameplayEvent(event, desc, value, hdl.ptr, str_data )); return pH->EndFunction(); }
//------------------------------------------------------------------------ bool CDetonate::Detonate(bool net) { bool detonatedAll = true; if (m_pWeapon->IsServer()) { CActor *pOwner=m_pWeapon->GetOwnerActor(); if (!pOwner) return false; if (IFireMode* pFM = m_pWeapon->GetFireMode(m_pWeapon->GetCurrentFireMode())) { std::vector<EntityId> undetonatedList; undetonatedList.clear(); while(EntityId projectileId = pFM->RemoveProjectileId()) { if (CProjectile *pProjectile = g_pGame->GetWeaponSystem()->GetProjectile(projectileId)) { if(pProjectile->Detonate()) { CCCPOINT(DetonateFireMode_ProjectileHasBeenDetonated); g_pGame->GetIGameFramework()->GetIGameplayRecorder()->Event(m_pWeapon->GetOwner(), GameplayEvent(eGE_WeaponShot, pProjectile->GetEntity()->GetClass()->GetName(), 1, (void *)(EXPAND_PTR)m_pWeapon->GetEntityId())); } else { CCCPOINT(DetonateFireMode_ProjectileFailedToDetonate); stl::push_back_unique(undetonatedList, projectileId); } } } while(!undetonatedList.empty()) { pFM->SetProjectileId(undetonatedList.back()); undetonatedList.pop_back(); detonatedAll = false; } } } return detonatedAll; }
bool CShotgun::Shoot(bool resetAnimation, bool autoreload/* =true */, bool isRemote) { CCCPOINT(Shotgun_TryShoot); m_firePending = false; m_shotIndex++; IEntityClass* ammo = m_fireParams->fireparams.ammo_type_class; int ammoCount = m_pWeapon->GetAmmoCount(ammo); int clipSize = GetClipSize(); if (clipSize == 0) ammoCount = m_pWeapon->GetInventoryAmmoCount(ammo); CActor *pActor = m_pWeapon->GetOwnerActor(); bool playerIsShooter = pActor ? pActor->IsPlayer() : false; bool shooterIsClient = pActor ? pActor->IsClient() : false; if (!CanFire(true)) { if ((ammoCount <= 0) && (!m_reloading)) { m_pWeapon->PlayAction(GetFragmentIds().empty_clip); m_pWeapon->OnFireWhenOutOfAmmo(); CCCPOINT(Shotgun_TryShootWhileOutOfAmmo); } else { CCCPOINT(Shotgun_TryShootWhileCannotBeFired); } return false; } if (m_reloading) { if(m_pWeapon->IsBusy()) m_pWeapon->SetBusy(false); if(CanFire(true) && !m_break_reload) { m_break_reload = true; m_pWeapon->RequestCancelReload(); } CCCPOINT(Shotgun_TryShootWhileReloading); return false; } uint32 flags = CItem::eIPAF_Default; if (IsProceduralRecoilEnabled() && pActor) { pActor->ProceduralRecoil(m_fireParams->proceduralRecoilParams.duration, m_fireParams->proceduralRecoilParams.strength, m_fireParams->proceduralRecoilParams.kickIn, m_fireParams->proceduralRecoilParams.arms); } float speedOverride = -1.f; m_pWeapon->PlayAction(GetFragmentIds().fire, 0, false, flags, speedOverride); Vec3 hit = GetProbableHit(WEAPON_HIT_RANGE); Vec3 pos = GetFiringPos(hit); Vec3 fdir = GetFiringDir(hit, pos); Vec3 vel = GetFiringVelocity(fdir); Vec3 dir; const float hitDist = hit.GetDistance(pos); CheckNearMisses(hit, pos, fdir, WEAPON_HIT_RANGE, m_fireParams->shotgunparams.spread); CRY_ASSERT_MESSAGE(m_fireParams->fireparams.hitTypeId, string().Format("Invalid hit type '%s' in fire params for '%s'", m_fireParams->fireparams.hit_type.c_str(), m_pWeapon->GetEntity()->GetName())); CRY_ASSERT_MESSAGE(m_fireParams->fireparams.hitTypeId == g_pGame->GetGameRules()->GetHitTypeId(m_fireParams->fireparams.hit_type.c_str()), "Sanity Check Failed: Stored hit type id does not match the type string, possibly CacheResources wasn't called on this weapon type"); int quad = cry_random(0, 3); const int numPellets = m_fireParams->shotgunparams.pellets; std::vector<CProjectile*> projList; projList.reserve(numPellets); int ammoCost = (m_fireParams->fireparams.fake_fire_rate && playerIsShooter) ? m_fireParams->fireparams.fake_fire_rate : 1; ammoCost = min(ammoCost, ammoCount); EntityId firstAmmoId = 0; // SHOT HERE for (int i = 0; i < numPellets; i++) { CProjectile *pAmmo = m_pWeapon->SpawnAmmo(m_fireParams->fireparams.spawn_ammo_class, false); if (pAmmo) { if(!firstAmmoId) { firstAmmoId = pAmmo->GetEntityId(); } projList.push_back(pAmmo); dir = ApplySpread(fdir, m_fireParams->shotgunparams.spread, quad); quad = (quad+1)%4; int pelletDamage = m_fireParams->shotgunparams.pelletdamage; if (!playerIsShooter) pelletDamage += m_fireParams->shotgunparams.npc_additional_damage; const bool canOvercharge = m_pWeapon->GetSharedItemParams()->params.can_overcharge; const float overchargeModifier = pActor ? pActor->GetOverchargeDamageScale() : 1.0f; if (canOvercharge) { pelletDamage = int(pelletDamage * overchargeModifier); } CProjectile::SProjectileDesc projectileDesc( m_pWeapon->GetOwnerId(), m_pWeapon->GetHostId(), m_pWeapon->GetEntityId(), pelletDamage, m_fireParams->fireparams.damage_drop_min_distance, m_fireParams->fireparams.damage_drop_per_meter, m_fireParams->fireparams.damage_drop_min_damage, m_fireParams->fireparams.hitTypeId, m_fireParams->fireparams.bullet_pierceability_modifier, m_pWeapon->IsZoomed()); projectileDesc.pointBlankAmount = m_fireParams->fireparams.point_blank_amount; projectileDesc.pointBlankDistance = m_fireParams->fireparams.point_blank_distance; projectileDesc.pointBlankFalloffDistance = m_fireParams->fireparams.point_blank_falloff_distance; if (m_fireParams->fireparams.ignore_damage_falloff) projectileDesc.damageFallOffAmount = 0.0f; const Vec3 pelletDestination = pos + (dir * hitDist); pAmmo->SetParams(projectileDesc); pAmmo->SetDestination(m_pWeapon->GetDestination()); pAmmo->Launch(pos, dir, vel); pAmmo->CreateBulletTrail( pelletDestination ); pAmmo->SetKnocksTargetInfo( GetShared() ); if ((!m_fireParams->tracerparams.geometry.empty() || !m_fireParams->tracerparams.effect.empty()) && ((ammoCount == clipSize) || (ammoCount%m_fireParams->tracerparams.frequency==0))) { EmitTracer(pos, pelletDestination, &m_fireParams->tracerparams, pAmmo); } if(shooterIsClient) { pAmmo->RegisterLinkedProjectile(m_shotIndex); if(gEnv->bMultiplayer) { float damageCap = g_pGameCVars->pl_shotgunDamageCap; pAmmo->SetDamageCap(damageCap); } } m_projectileId = pAmmo->GetEntity()->GetId(); pAmmo->SetAmmoCost(ammoCost); } } if (m_pWeapon->IsServer()) { const char *ammoName = ammo != NULL ? ammo->GetName() : NULL; g_pGame->GetIGameFramework()->GetIGameplayRecorder()->Event(m_pWeapon->GetOwner(), GameplayEvent(eGE_WeaponShot, ammoName, m_fireParams->shotgunparams.pellets, (void *)(EXPAND_PTR)m_pWeapon->GetEntityId())); } m_muzzleEffect.Shoot(this, hit, m_barrelId); m_fired = true; SetNextShotTime(m_next_shot + m_next_shot_dt); ammoCount -= ammoCost; if (ammoCount < m_fireParams->fireparams.minimum_ammo_count) ammoCount = 0; if (clipSize != -1) { if (clipSize != 0) m_pWeapon->SetAmmoCount(ammo, ammoCount); else m_pWeapon->SetInventoryAmmoCount(ammo, ammoCount); } OnShoot(m_pWeapon->GetOwnerId(), firstAmmoId, ammo, pos, dir, vel); const SThermalVisionParams& thermalParams = m_fireParams->thermalVisionParams; m_pWeapon->AddShootHeatPulse(pActor, thermalParams.weapon_shootHeatPulse, thermalParams.weapon_shootHeatPulseTime, thermalParams.owner_shootHeatPulse, thermalParams.owner_shootHeatPulseTime); if (OutOfAmmo()) { m_pWeapon->OnOutOfAmmo(ammo); if (autoreload) { uint32 scheduleTime = max(m_pWeapon->GetCurrentAnimationTime(eIGS_Owner), (uint)(m_next_shot*1000)); m_pWeapon->GetScheduler()->TimerAction(scheduleTime, CSchedulerAction<ScheduleReload>::Create(ScheduleReload(this, m_pWeapon)), false); m_autoReloading = true; } } m_pWeapon->RequestShoot(ammo, pos, dir, vel, hit, 1.0f, 0, false); #if defined(ANTI_CHEAT) const int numProjectiles = projList.size(); uint32 shotId = m_pWeapon->GetLastShotId(); for(int i = 0; i < numProjectiles; i++) { CProjectile * pAmmo = projList[i]; pAmmo->SetShotId(shotId); shotId -= (1 << CWeapon::GetShotIdCountOffset()); } #endif CCCPOINT(Shotgun_Fired); return true; }
void CLTagSingle::NetShootEx(const Vec3 &pos, const Vec3 &dir, const Vec3 &vel, const Vec3 &hit, float extra, int predictionHandle) { IEntityClass* ammo = m_fireParams->fireparams.ammo_type_class; int weaponAmmoCount = m_pWeapon->GetAmmoCount(ammo); int ammoCount = weaponAmmoCount; CActor* pOwnerActor = m_pWeapon->GetOwnerActor(); bool playerIsShooter = pOwnerActor ? pOwnerActor->IsPlayer() : false; if (IsProceduralRecoilEnabled() && pOwnerActor) { pOwnerActor->ProceduralRecoil(m_fireParams->proceduralRecoilParams.duration, m_fireParams->proceduralRecoilParams.strength, m_fireParams->proceduralRecoilParams.kickIn, m_fireParams->proceduralRecoilParams.arms); } m_pWeapon->PlayAction(GetFragmentIds().fire, 0, false, CItem::eIPAF_Default); CProjectile *pAmmo = m_pWeapon->SpawnAmmo(m_fireParams->fireparams.spawn_ammo_class, true); CLTAGGrenade* pGrenade = static_cast<CLTAGGrenade*>(pAmmo); if (pGrenade) { CRY_ASSERT_MESSAGE(m_fireParams->fireparams.hitTypeId, string().Format("Invalid hit type '%s' in fire params for '%s'", m_fireParams->fireparams.hit_type.c_str(), m_pWeapon->GetEntity()->GetName())); CRY_ASSERT_MESSAGE(m_fireParams->fireparams.hitTypeId == g_pGame->GetGameRules()->GetHitTypeId(m_fireParams->fireparams.hit_type.c_str()), "Sanity Check Failed: Stored hit type id does not match the type string, possibly CacheResources wasn't called on this weapon type"); pGrenade->SetParams(CProjectile::SProjectileDesc( m_pWeapon->GetOwnerId(), m_pWeapon->GetHostId(), m_pWeapon->GetEntityId(), m_fireParams->fireparams.damage, 0.f, 0.f, 0.f, m_fireParams->fireparams.hitTypeId, m_fireParams->fireparams.bullet_pierceability_modifier, m_pWeapon->IsZoomed())); // this must be done after owner is set pGrenade->InitWithAI(); pGrenade->SetDestination(m_pWeapon->GetDestination()); pGrenade->SetGrenadeType(m_grenadeType); pGrenade->Launch(pos, dir, vel, m_speed_scale); m_projectileId = pGrenade->GetEntity()->GetId(); } if (m_pWeapon->IsServer()) { const char *ammoName = ammo != NULL ? ammo->GetName() : NULL; g_pGame->GetIGameFramework()->GetIGameplayRecorder()->Event(m_pWeapon->GetOwner(), GameplayEvent(eGE_WeaponShot, ammoName, 1, (void *)(EXPAND_PTR)m_pWeapon->GetEntityId())); #ifdef SERVER_CHECKS if (pOwnerActor && m_pWeapon->IsServerSpawn(ammo)) { int inventoryAmmoCount = m_pWeapon->GetInventoryAmmoCount(ammo); int totalAmmoCount=weaponAmmoCount+inventoryAmmoCount; // this needed seeing as how this seems to use weaponAmmo or inventoryAmmo but NOT both? if (totalAmmoCount <= 0) { g_pGame->GetAntiCheatManager()->FlagActivity(eCT_ServerSpawnedAmmoUsed, pOwnerActor->GetChannelId()); } } #endif } m_muzzleEffect.Shoot(this, hit, m_barrelId); RecoilImpulse(pos, dir); m_fired = true; m_next_shot = 0.0f; ammoCount--; if(ammoCount<0) ammoCount = 0; if (m_pWeapon->IsServer()) { int clipSize = GetClipSize(); if (clipSize != -1) { if (clipSize != 0) m_pWeapon->SetAmmoCount(ammo, ammoCount); else m_pWeapon->SetInventoryAmmoCount(ammo, ammoCount); } } OnShoot(m_pWeapon->GetOwnerId(), pAmmo?pAmmo->GetEntity()->GetId():0, ammo, pos, dir, vel); if(playerIsShooter) { const SThermalVisionParams& thermalParams = m_fireParams->thermalVisionParams; m_pWeapon->AddShootHeatPulse(pOwnerActor, thermalParams.weapon_shootHeatPulse, thermalParams.weapon_shootHeatPulseTime, thermalParams.owner_shootHeatPulse, thermalParams.owner_shootHeatPulseTime); } if (OutOfAmmo()) m_pWeapon->OnOutOfAmmo(ammo); if (pAmmo && predictionHandle && pOwnerActor) { pAmmo->GetGameObject()->RegisterAsValidated(pOwnerActor->GetGameObject(), predictionHandle); pAmmo->GetGameObject()->BindToNetwork(); } else if (pAmmo && pAmmo->IsPredicted() && gEnv->IsClient() && gEnv->bServer && pOwnerActor && pOwnerActor->IsClient()) { pAmmo->GetGameObject()->BindToNetwork(); } m_pWeapon->RequireUpdate(eIUS_FireMode); }
//------------------------------------------------------------------------ void CGameRules::ProcessServerHit(const HitInfo &hitInfo) { bool ok=true; // check if shooter is alive CActor *pShooter = GetActorByEntityId(hitInfo.shooterId); CActor *pTarget = GetActorByEntityId(hitInfo.targetId); if (hitInfo.shooterId) { if (pShooter && pShooter->GetHealth()<=0) ok=false; } if (hitInfo.targetId) { if (pTarget && pTarget->GetSpectatorMode()) ok=false; } if (ok) { float fTargetHealthBeforeHit = 0.0f; if(pTarget) { fTargetHealthBeforeHit = pTarget->GetHealth(); } CreateScriptHitInfo(m_scriptHitInfo, hitInfo); //CallMonoScript<void>(m_pScriptClass, "OnHit", gEnv->pMonoScriptSystem->GetConverter()->ToManagedType(eCMT_HitInfo, &const_cast<HitInfo &>(hitInfo))); if(pTarget && !pTarget->IsDead()) { const float fCausedDamage = fTargetHealthBeforeHit - pTarget->GetHealth(); ProcessLocalHit(hitInfo, fCausedDamage); } // call hit listeners if any if (m_hitListeners.empty() == false) { for (size_t i = 0; i < m_hitListeners.size(); ) { size_t count = m_hitListeners.size(); m_hitListeners[i]->OnHit(hitInfo); if (count == m_hitListeners.size()) i++; else continue; } } if (pShooter && hitInfo.shooterId!=hitInfo.targetId && hitInfo.weaponId!=hitInfo.shooterId && hitInfo.weaponId!=hitInfo.targetId && hitInfo.damage>=0) { EntityId params[2]; params[0] = hitInfo.weaponId; params[1] = hitInfo.targetId; m_pGameplayRecorder->Event(pShooter->GetEntity(), GameplayEvent(eGE_WeaponHit, 0, 0, (void *)params)); } if (pShooter) m_pGameplayRecorder->Event(pShooter->GetEntity(), GameplayEvent(eGE_Hit, 0, 0, (void *)hitInfo.weaponId)); if (pShooter) m_pGameplayRecorder->Event(pShooter->GetEntity(), GameplayEvent(eGE_Damage, 0, hitInfo.damage, (void *)hitInfo.weaponId)); } }
//------------------------------------------------------------------------ void CShotgun::NetShootEx(const Vec3 &pos, const Vec3 &dir, const Vec3 &vel, const Vec3 &hit, float extra, int ph) { CCCPOINT(Shotgun_NetShoot); assert(0 == ph); IEntityClass* ammo = m_fireParams->fireparams.ammo_type_class; FragmentID action = m_fireParams->fireparams.no_cock ? GetFragmentIds().fire : GetFragmentIds().fire_cock; CActor *pActor = m_pWeapon->GetOwnerActor(); bool playerIsShooter = pActor?pActor->IsPlayer():false; int ammoCount = m_pWeapon->GetAmmoCount(ammo); int clipSize = GetClipSize(); if (clipSize == 0) ammoCount = m_pWeapon->GetInventoryAmmoCount(ammo); if (ammoCount == 1) action = GetFragmentIds().fire; if (IsProceduralRecoilEnabled() && pActor) { pActor->ProceduralRecoil(m_fireParams->proceduralRecoilParams.duration, m_fireParams->proceduralRecoilParams.strength, m_fireParams->proceduralRecoilParams.kickIn,m_fireParams->proceduralRecoilParams.arms); } m_pWeapon->PlayAction(action, 0, false, CItem::eIPAF_Default); Vec3 pdir; int quad = cry_random(0, 3); CRY_ASSERT_MESSAGE(m_fireParams->fireparams.hitTypeId, string().Format("Invalid hit type '%s' in fire params for '%s'", m_fireParams->fireparams.hit_type.c_str(), m_pWeapon->GetEntity()->GetName())); CRY_ASSERT_MESSAGE(m_fireParams->fireparams.hitTypeId == g_pGame->GetGameRules()->GetHitTypeId(m_fireParams->fireparams.hit_type.c_str()), "Sanity Check Failed: Stored hit type id does not match the type string, possibly CacheResources wasn't called on this weapon type"); int ammoCost = m_fireParams->fireparams.fake_fire_rate ? m_fireParams->fireparams.fake_fire_rate : 1; ammoCost = min(ammoCost, ammoCount); // SHOT HERE for (int i = 0; i < m_fireParams->shotgunparams.pellets; i++) { CProjectile *pAmmo = m_pWeapon->SpawnAmmo(m_fireParams->fireparams.spawn_ammo_class, true); if (pAmmo) { pdir = ApplySpread(dir, m_fireParams->shotgunparams.spread, quad); quad = (quad+1)%4; CProjectile::SProjectileDesc projectileDesc( m_pWeapon->GetOwnerId(), m_pWeapon->GetHostId(), m_pWeapon->GetEntityId(), m_fireParams->shotgunparams.pelletdamage, m_fireParams->fireparams.damage_drop_min_distance, m_fireParams->fireparams.damage_drop_min_damage, m_fireParams->fireparams.damage_drop_per_meter, m_fireParams->fireparams.hitTypeId, m_fireParams->fireparams.bullet_pierceability_modifier, m_pWeapon->IsZoomed()); projectileDesc.pointBlankAmount = m_fireParams->fireparams.point_blank_amount; projectileDesc.pointBlankDistance = m_fireParams->fireparams.point_blank_distance; projectileDesc.pointBlankFalloffDistance = m_fireParams->fireparams.point_blank_falloff_distance; if (m_fireParams->fireparams.ignore_damage_falloff) projectileDesc.damageFallOffAmount = 0.0f; pAmmo->SetParams(projectileDesc); pAmmo->SetDestination(m_pWeapon->GetDestination()); pAmmo->SetRemote(true); pAmmo->Launch(pos, pdir, vel); bool emit = false; if(m_pWeapon->GetStats().fp) emit = (!m_fireParams->tracerparams.geometryFP.empty() || !m_fireParams->tracerparams.effectFP.empty()) && ((ammoCount == clipSize) || (ammoCount%m_fireParams->tracerparams.frequency==0)); else emit = (!m_fireParams->tracerparams.geometry.empty() || !m_fireParams->tracerparams.effect.empty()) && ((ammoCount == clipSize) || (ammoCount%m_fireParams->tracerparams.frequency==0)); if (emit) { EmitTracer(pos, hit, &m_fireParams->tracerparams, pAmmo); } m_projectileId = pAmmo->GetEntity()->GetId(); pAmmo->SetAmmoCost(ammoCost); } } if (m_pWeapon->IsServer()) { const char *ammoName = ammo != NULL ? ammo->GetName() : NULL; g_pGame->GetIGameFramework()->GetIGameplayRecorder()->Event(m_pWeapon->GetOwner(), GameplayEvent(eGE_WeaponShot, ammoName, m_fireParams->shotgunparams.pellets, (void *)(EXPAND_PTR)m_pWeapon->GetEntityId())); } m_muzzleEffect.Shoot(this, hit, m_barrelId); m_fired = true; m_next_shot = 0.0f; ammoCount -= ammoCost; if (m_pWeapon->IsServer()) { if (clipSize != -1) { if (clipSize != 0) m_pWeapon->SetAmmoCount(ammo, ammoCount); else m_pWeapon->SetInventoryAmmoCount(ammo, ammoCount); } } OnShoot(m_pWeapon->GetOwnerId(), 0, ammo, pos, dir, vel); m_pWeapon->RequireUpdate(eIUS_FireMode); }
//------------------------------------------------------------------------ void CShotgun::NetShootEx(const Vec3 &pos, const Vec3 &dir, const Vec3 &vel, const Vec3 &hit, float extra, int ph) { assert(0 == ph); IEntityClass *ammo = m_pShared->fireparams.ammo_type_class; const char *action = m_pShared->actions.fire_cock.c_str(); CActor *pActor = m_pWeapon->GetOwnerActor(); bool playerIsShooter = pActor?pActor->IsPlayer():false; int ammoCount = m_pWeapon->GetAmmoCount(ammo); if(m_pShared->fireparams.clip_size==0) ammoCount = m_pWeapon->GetInventoryAmmoCount(ammo); if(ammoCount == 1) action = m_pShared->actions.fire.c_str(); m_pWeapon->ResetAnimation(); m_pWeapon->PlayAction(action, 0, false, CItem::eIPAF_Default|CItem::eIPAF_NoBlend); Vec3 pdir; // SHOT HERE for(int i = 0; i < m_pShared->shotgunparams.pellets; i++) { CProjectile *pAmmo = m_pWeapon->SpawnAmmo(ammo, true); if(pAmmo) { pdir = ApplySpread(dir, m_pShared->shotgunparams.spread); int hitTypeId = g_pGame->GetGameRules()->GetHitTypeId(m_pShared->fireparams.hit_type.c_str()); pAmmo->SetParams(m_pWeapon->GetOwnerId(), m_pWeapon->GetHostId(), m_pWeapon->GetEntityId(), m_pShared->shotgunparams.pelletdamage, hitTypeId, playerIsShooter?m_pShared->fireparams.damage_drop_per_meter:0.0f, m_pShared->fireparams.damage_drop_min_distance); pAmmo->SetDestination(m_pWeapon->GetDestination()); pAmmo->SetRemote(true); pAmmo->Launch(pos, pdir, vel); bool emit = false; if(m_pWeapon->GetStats().fp) emit = (!m_pShared->tracerparams.geometryFP.empty() || !m_pShared->tracerparams.effectFP.empty()) && (ammoCount==GetClipSize() || (ammoCount%m_pShared->tracerparams.frequency==0)); else emit = (!m_pShared->tracerparams.geometry.empty() || !m_pShared->tracerparams.effect.empty()) && (ammoCount==GetClipSize() || (ammoCount%m_pShared->tracerparams.frequency==0)); if(emit) EmitTracer(pos,hit,false); m_projectileId = pAmmo->GetEntity()->GetId(); } } m_pWeapon->OnShoot(m_pWeapon->GetOwnerId(), 0, ammo, pos, dir, vel); if(m_pWeapon->IsServer()) { const char *ammoName = ammo != NULL ? ammo->GetName() : NULL; g_pGame->GetIGameFramework()->GetIGameplayRecorder()->Event(m_pWeapon->GetOwner(), GameplayEvent(eGE_WeaponShot, ammoName, m_pShared->shotgunparams.pellets, (void *)m_pWeapon->GetEntityId())); } MuzzleFlashEffect(true); RejectEffect(); m_fired = true; m_next_shot = 0.0f; ammoCount--; if(m_pWeapon->IsServer()) { if(m_pShared->fireparams.clip_size != -1) { if(m_pShared->fireparams.clip_size!=0) m_pWeapon->SetAmmoCount(ammo, ammoCount); else m_pWeapon->SetInventoryAmmoCount(ammo, ammoCount); } } if((ammoCount<1) && !m_pShared->fireparams.slider_layer.empty()) { const char *slider_back_layer = m_pShared->fireparams.slider_layer.c_str(); m_pWeapon->PlayLayer(slider_back_layer, CItem::eIPAF_Default|CItem::eIPAF_NoBlend); } m_pWeapon->RequireUpdate(eIUS_FireMode); }
bool CShotgun::Shoot(bool resetAnimation, bool autoreload/* =true */, bool noSound /* =false */) { IEntityClass *ammo = m_pShared->fireparams.ammo_type_class; int ammoCount = m_pWeapon->GetAmmoCount(ammo); if(m_pShared->fireparams.clip_size==0) ammoCount = m_pWeapon->GetInventoryAmmoCount(ammo); CActor *pActor = m_pWeapon->GetOwnerActor(); bool playerIsShooter = pActor?pActor->IsPlayer():false; if(!CanFire(true)) { if((ammoCount <= 0) && (!m_reloading)) { m_pWeapon->PlayAction(m_pShared->actions.empty_clip); //Auto reload m_pWeapon->Reload(); } return false; } else if(m_pWeapon->IsWeaponLowered()) { m_pWeapon->PlayAction(m_pShared->actions.null_fire); return false; } if(m_reloading) { if(m_pWeapon->IsBusy()) m_pWeapon->SetBusy(false); if(CanFire(true) && !m_break_reload) { m_break_reload = true; m_pWeapon->RequestCancelReload(); } return false; } // Aim assistance m_pWeapon->AssistAiming(); const char *action = m_pShared->actions.fire_cock.c_str(); if(ammoCount == 1 || (m_pShared->fireparams.no_cock && m_pWeapon->IsZoomed())) action = m_pShared->actions.fire.c_str(); m_pWeapon->PlayAction(action, 0, false, CItem::eIPAF_Default|CItem::eIPAF_RestartAnimation|CItem::eIPAF_CleanBlending); Vec3 hit = GetProbableHit(WEAPON_HIT_RANGE); Vec3 pos = GetFiringPos(hit); Vec3 fdir = ApplySpread(GetFiringDir(hit, pos), GetSpread()); Vec3 vel = GetFiringVelocity(fdir); Vec3 dir; CheckNearMisses(hit, pos, fdir, WEAPON_HIT_RANGE, m_pShared->shotgunparams.spread); bool serverSpawn = m_pWeapon->IsServerSpawn(ammo); // SHOT HERE for(int i = 0; i < m_pShared->shotgunparams.pellets; i++) { CProjectile *pAmmo = m_pWeapon->SpawnAmmo(ammo, false); if(pAmmo) { dir = ApplySpread(fdir, m_pShared->shotgunparams.spread); int hitTypeId = g_pGame->GetGameRules()->GetHitTypeId(m_pShared->fireparams.hit_type.c_str()); pAmmo->SetParams(m_pWeapon->GetOwnerId(), m_pWeapon->GetHostId(), m_pWeapon->GetEntityId(), m_pShared->shotgunparams.pelletdamage, hitTypeId, playerIsShooter?m_pShared->fireparams.damage_drop_per_meter:0.0f, m_pShared->fireparams.damage_drop_min_distance); pAmmo->SetDestination(m_pWeapon->GetDestination()); pAmmo->Launch(pos, dir, vel); if((!m_pShared->tracerparams.geometry.empty() || !m_pShared->tracerparams.effect.empty()) && (ammoCount==GetClipSize() || (ammoCount%m_pShared->tracerparams.frequency==0))) { EmitTracer(pos,hit,false); } m_projectileId = pAmmo->GetEntity()->GetId(); } } m_pWeapon->OnShoot(m_pWeapon->GetOwnerId(), 0, ammo, pos, dir, vel); if(m_pWeapon->IsServer()) { const char *ammoName = ammo != NULL ? ammo->GetName() : NULL; g_pGame->GetIGameFramework()->GetIGameplayRecorder()->Event(m_pWeapon->GetOwner(), GameplayEvent(eGE_WeaponShot, ammoName, m_pShared->shotgunparams.pellets, (void *)m_pWeapon->GetEntityId())); } MuzzleFlashEffect(true); RejectEffect(); m_fired = true; m_next_shot += m_next_shot_dt; m_zoomtimeout = m_next_shot + 0.5f; ammoCount--; if(playerIsShooter) { if(pActor->InZeroG()) { IEntityPhysicalProxy *pPhysicsProxy = (IEntityPhysicalProxy *)pActor->GetEntity()->GetProxy(ENTITY_PROXY_PHYSICS); SMovementState ms; pActor->GetMovementController()->GetMovementState(ms); CPlayer *plr = (CPlayer *)pActor; if(m_recoilparams.back_impulse > 0.0f) { Vec3 impulseDir = ms.aimDirection * -1.0f; Vec3 impulsePos = ms.pos; float impulse = m_recoilparams.back_impulse; pPhysicsProxy->AddImpulse(-1, impulsePos, impulseDir * impulse * 100.0f, true, 1.0f); } if(m_recoilparams.angular_impulse > 0.0f) { float impulse = m_recoilparams.angular_impulse; pActor->AddAngularImpulse(Ang3(0,impulse,0), 1.0f); } } if(pActor->IsClient()) if(gEnv->pInput) gEnv->pInput->ForceFeedbackEvent(SFFOutputEvent(eDI_XI, eFF_Rumble_Basic, 0.15f, 0.0f, fabsf(m_recoilparams.back_impulse)*3.0f)); } if(m_pShared->fireparams.clip_size != -1) { if(m_pShared->fireparams.clip_size!=0) m_pWeapon->SetAmmoCount(ammo, ammoCount); else m_pWeapon->SetInventoryAmmoCount(ammo, ammoCount); } if((ammoCount<1) && !m_pShared->fireparams.slider_layer.empty()) { const char *slider_back_layer = m_pShared->fireparams.slider_layer.c_str(); m_pWeapon->PlayLayer(slider_back_layer, CItem::eIPAF_Default|CItem::eIPAF_NoBlend); } if(OutOfAmmo()) { m_pWeapon->OnOutOfAmmo(ammo); if(autoreload) { m_pWeapon->GetScheduler()->TimerAction(m_pWeapon->GetCurrentAnimationTime(eIGS_FirstPerson), CSchedulerAction<ScheduleReload>::Create(m_pWeapon), false); } } m_pWeapon->RequestShoot(ammo, pos, dir, vel, hit, 1.0f, 0, false); return true; }
IMPLEMENT_RMI(CGameRules, ClEnteredGame) { CPlayer *pClientActor = static_cast<CPlayer*>(m_pGameFramework->GetClientActor()); if (pClientActor) { IEntity *pClientEntity = pClientActor->GetEntity(); const EntityId clientEntityId = pClientEntity->GetId(); if(!gEnv->bServer) { int status[2]; status[0] = GetTeam(clientEntityId); status[1] = pClientActor->GetSpectatorMode(); m_pGameplayRecorder->Event(pClientEntity, GameplayEvent(eGE_Connected, 0, 0, (void*)status)); } if (g_pGame->GetHostMigrationState() != CGame::eHMS_NotMigrating) { eHostMigrationState hostMigrationState = g_pGame->GetGameLobby()->GetMatchMakingHostMigrationState(); if (hostMigrationState < eHMS_ReconnectClient) { CryLog("CGameRules::ClEnteredGame() received a left over message from previous server, ignoring it"); return true; } CryLog("CGameRules::ClEnteredGame() We have our client actor ('%s'), send migration params", pClientEntity->GetName()); // Request various bits GetGameObject()->InvokeRMI(SvHostMigrationRequestSetup(), *m_pHostMigrationParams, eRMI_ToServer); SAFE_DELETE(m_pHostMigrationParams); pClientActor->GetEntity()->SetPos(m_pHostMigrationClientParams->m_position); pClientActor->SetViewRotation(m_pHostMigrationClientParams->m_viewQuat); if (m_pHostMigrationClientParams->m_hasValidVelocity) { pe_action_set_velocity actionVel; actionVel.v = m_pHostMigrationClientParams->m_velocity; actionVel.w.zero(); IPhysicalEntity *pPhysicalEntity = pClientEntity->GetPhysics(); if (pPhysicalEntity) { pPhysicalEntity->Action(&actionVel); } } CPlayerMovementController *pPMC = static_cast<CPlayerMovementController *>(pClientActor->GetMovementController()); if (pPMC) { // Force an update through so that the aim direction gets set correctly pPMC->PostUpdate(0.f); } if (m_pHostMigrationClientParams->m_pSelectedItemClass) { CItem *pItem = pClientActor->GetItemByClass(m_pHostMigrationClientParams->m_pSelectedItemClass); if (pItem) { EntityId itemId = pItem->GetEntityId(); if (pClientActor->GetCurrentItemId() != itemId) { pClientActor->SelectItem(itemId, false); } } } m_pHostMigrationClientParams->m_doneEnteredGame = true; if (m_pHostMigrationClientParams->IsDone()) { SAFE_DELETE(m_pHostMigrationClientParams); } if (!gEnv->bServer) { // todo: ui } m_hostMigrationClientHasRejoined = true; } else { NOTIFY_UI_MP( EnteredGame() ); } } return true; }
//------------------------------------------------------------------------ bool CDetonate::Detonate(bool net) { if (m_pWeapon->IsServer()) { CActor *pOwner=m_pWeapon->GetOwnerActor(); if (!pOwner) return false; if (CWeapon *pWeapon=static_cast<CWeapon*>(pOwner->GetItemByClass(CItem::sC4Class))) { IFireMode* pFM = pWeapon->GetFireMode(pWeapon->GetCurrentFireMode()); //assert(pFM && "Detonator has not fire mode! Can not detonate C4"); if(!pFM) return false; while(EntityId projectileId=pFM->RemoveProjectileId()) { if (CProjectile *pProjectile=g_pGame->GetWeaponSystem()->GetProjectile(projectileId)) { pProjectile->Explode(true, false); g_pGame->GetIGameFramework()->GetIGameplayRecorder()->Event(pWeapon->GetOwner(), GameplayEvent(eGE_WeaponShot, pProjectile->GetEntity()->GetClass()->GetName(), 1, (void *)pWeapon->GetEntityId())); } } } } if (!net) m_pWeapon->RequestShoot(0, ZERO, ZERO, ZERO, ZERO, 1.0f, 0, false); return true; }
void CItem::AttachAccessory(const ItemString &name, bool attach, bool noanim, bool force, bool initialSetup) { if(!force && IsBusy()) return; bool anim = !noanim && m_stats.fp; SAccessoryParams *params = GetAccessoryParams(name); if(!params) return; if(attach) { if(!IsAccessoryHelperFree(params->attach_helper)) return; if(CItem *pAccessory = AddAccessory(name)) { pAccessory->Physicalize(false, false); pAccessory->SetViewMode(m_stats.viewmode); if(!initialSetup) pAccessory->m_bonusAccessoryAmmo.clear(); SetCharacterAttachment(eIGS_FirstPerson, params->attach_helper, pAccessory->GetEntity(), eIGS_FirstPerson, 0); SetBusy(true); AttachAction action(pAccessory, params); if(anim) { PlayAction(params->attach_action, 0, false, eIPAF_Default|eIPAF_NoBlend); m_scheduler.TimerAction(GetCurrentAnimationTime(eIGS_FirstPerson), CSchedulerAction<AttachAction>::Create(action), false); } else action.execute(this); } } else { if(CItem *pAccessory = GetAccessory(name)) { DetachAction action(pAccessory, params); if(anim) { StopLayer(params->attach_layer, eIPAF_Default|eIPAF_NoBlend); PlayAction(params->detach_action, 0, false, eIPAF_Default|eIPAF_NoBlend); m_scheduler.TimerAction(GetCurrentAnimationTime(eIGS_FirstPerson), CSchedulerAction<DetachAction>::Create(action), false); SetBusy(true); } else { SetBusy(true); action.execute(this); } } } //Skip all this for the offhand if(GetEntity()->GetClass()!=CItem::sOffHandClass) FixAccessories(params, attach); //Attach silencer to 2nd SOCOM ///////////////////////////////////////////////////////////// bool isDualWield = IsDualWieldMaster(); CItem *dualWield = 0; if(isDualWield) { IItem *slave = GetDualWieldSlave(); if(slave && slave->GetIWeapon()) dualWield = static_cast<CItem *>(slave); else isDualWield = false; } if(isDualWield) dualWield->AttachAccessory(name,attach,noanim); ////////////////////////////////////////////////////////////// //Luciano - send game event g_pGame->GetIGameFramework()->GetIGameplayRecorder()->Event(GetOwner(), GameplayEvent(eGE_AttachedAccessory, name, (float)attach, (void *)GetEntityId())); }
bool CSpammer::ShootRocket(EntityId target) { IEntityClass* pAmmoClass = m_fireParams->fireparams.ammo_type_class; int ammoCount = m_pWeapon->GetAmmoCount(pAmmoClass); CActor *pOwnerActor = m_pWeapon->GetOwnerActor(); const bool playerIsShooter = pOwnerActor ? pOwnerActor->IsPlayer() : false; const bool clientIsShooter = pOwnerActor ? pOwnerActor->IsClient() : false; bool bHit = false; ray_hit rayhit; rayhit.pCollider = 0; Vec3 hit = GetProbableHit(WEAPON_HIT_RANGE, &bHit, &rayhit); Vec3 pos = GetFiringPos(hit); Vec3 dir = GetFiringDir(hit, pos); Vec3 vel = GetFiringVelocity(dir); int flags = CItem::eIPAF_Default; if (IsProceduralRecoilEnabled() && pOwnerActor) { pOwnerActor->ProceduralRecoil(m_fireParams->proceduralRecoilParams.duration, m_fireParams->proceduralRecoilParams.strength, m_fireParams->proceduralRecoilParams.kickIn, m_fireParams->proceduralRecoilParams.arms); } float speedOverride = -1.f; GetWeapon()->PlayAction(GetFragmentIds().fire, 0, false, flags, speedOverride); CheckNearMisses(hit, pos, dir, (hit-pos).len(), 1.0f); CProjectile* pAmmo = m_pWeapon->SpawnAmmo(m_fireParams->fireparams.spawn_ammo_class, false); const EntityId weaponOwnerId = m_pWeapon->GetOwnerId(); EntityId ammoId = 0; if (pAmmo) { ammoId = pAmmo->GetEntityId(); CRY_ASSERT_MESSAGE(m_fireParams->fireparams.hitTypeId, string().Format("Invalid hit type '%s' in fire params for '%s'", m_fireParams->fireparams.hit_type.c_str(), m_pWeapon->GetEntity()->GetName())); CRY_ASSERT_MESSAGE(m_fireParams->fireparams.hitTypeId == g_pGame->GetGameRules()->GetHitTypeId(m_fireParams->fireparams.hit_type.c_str()), "Sanity Check Failed: Stored hit type id does not match the type string, possibly CacheResources wasn't called on this weapon type"); pAmmo->SetParams(CProjectile::SProjectileDesc( weaponOwnerId, m_pWeapon->GetHostId(), m_pWeapon->GetEntityId(), m_fireParams->fireparams.damage, m_fireParams->fireparams.damage_drop_min_distance, m_fireParams->fireparams.damage_drop_per_meter, m_fireParams->fireparams.damage_drop_min_damage, m_fireParams->fireparams.hitTypeId, m_fireParams->fireparams.bullet_pierceability_modifier, m_pWeapon->IsZoomed())); // this must be done after owner is set pAmmo->InitWithAI(); pAmmo->SetDestination(target); pAmmo->Launch(pos, dir, vel, m_speed_scale); m_projectileId = ammoId; if (clientIsShooter && pAmmo->IsPredicted() && gEnv->IsClient() && gEnv->bServer) { pAmmo->GetGameObject()->BindToNetwork(); } } if (m_pWeapon->IsServer()) { const char *ammoName = pAmmoClass != NULL ? pAmmoClass->GetName() : NULL; g_pGame->GetIGameFramework()->GetIGameplayRecorder()->Event(m_pWeapon->GetOwner(), GameplayEvent(eGE_WeaponShot, ammoName, 1, (void *)(EXPAND_PTR)m_pWeapon->GetEntityId())); } OnShoot(weaponOwnerId, ammoId, pAmmoClass, pos, dir, vel); if(playerIsShooter) { const SThermalVisionParams& thermalParams = m_fireParams->thermalVisionParams; m_pWeapon->AddShootHeatPulse(pOwnerActor, thermalParams.weapon_shootHeatPulse, thermalParams.weapon_shootHeatPulseTime, thermalParams.owner_shootHeatPulse, thermalParams.owner_shootHeatPulseTime); } m_muzzleEffect.Shoot(this, hit, m_barrelId); RecoilImpulse(pos, dir); m_fired = true; m_next_shot += m_next_shot_dt; if (++m_barrelId == m_fireParams->fireparams.barrel_count) m_barrelId = 0; ammoCount--; int clipSize = GetClipSize(); if (clipSize != -1) { if (clipSize!=0) m_pWeapon->SetAmmoCount(pAmmoClass, ammoCount); else m_pWeapon->SetInventoryAmmoCount(pAmmoClass, ammoCount); } m_pWeapon->RequestShoot(pAmmoClass, pos, dir, vel, hit, m_speed_scale, pAmmo? pAmmo->GetGameObject()->GetPredictionHandle() : 0, false); return true; }
//------------------------------------------------------------------------ void CGameRules::ClientExplosion(const ExplosionInfo &explosionInfo) { TExplosionAffectedEntities affectedEntities; if (gEnv->bServer) { CullEntitiesInExplosion(explosionInfo); pe_explosion explosion; explosion.epicenter = explosionInfo.pos; explosion.rmin = explosionInfo.minRadius; explosion.rmax = explosionInfo.radius; if (explosion.rmax==0) explosion.rmax=0.0001f; explosion.r = explosion.rmin; explosion.impulsivePressureAtR = explosionInfo.pressure; explosion.epicenterImp = explosionInfo.pos; explosion.explDir = explosionInfo.dir; explosion.nGrow = 2; explosion.rminOcc = 0.07f; // we separate the calls to SimulateExplosion so that we can define different radii for AI and physics bodies explosion.holeSize = 0.0f; explosion.nOccRes = explosion.rmax>50.0f ? 0:32; gEnv->pPhysicalWorld->SimulateExplosion( &explosion, 0, 0, ent_living); CreateScriptExplosionInfo(m_scriptExplosionInfo, explosionInfo); UpdateAffectedEntitiesSet(affectedEntities, &explosion); // check vehicles IVehicleSystem *pVehicleSystem = g_pGame->GetIGameFramework()->GetIVehicleSystem(); uint32 vcount = pVehicleSystem->GetVehicleCount(); if (vcount > 0) { IVehicleIteratorPtr iter = g_pGame->GetIGameFramework()->GetIVehicleSystem()->CreateVehicleIterator(); while (IVehicle* pVehicle = iter->Next()) { if(IEntity *pEntity = pVehicle->GetEntity()) { AABB aabb; pEntity->GetWorldBounds(aabb); IPhysicalEntity* pEnt = pEntity->GetPhysics(); if (pEnt && aabb.GetDistanceSqr(explosionInfo.pos) <= explosionInfo.radius*explosionInfo.radius) { float affected = gEnv->pPhysicalWorld->CalculateExplosionExposure(&explosion, pEnt); AddOrUpdateAffectedEntity(affectedEntities, pEntity, affected); } } } } explosion.rmin = explosionInfo.minPhysRadius; explosion.rmax = explosionInfo.physRadius; if (explosion.rmax==0) explosion.rmax=0.0001f; explosion.r = explosion.rmin; explosion.holeSize = explosionInfo.hole_size; explosion.nOccRes = -1; // makes second call re-use occlusion info gEnv->pPhysicalWorld->SimulateExplosion( &explosion, 0, 0, ent_rigid|ent_sleeping_rigid|ent_independent|ent_static ); UpdateAffectedEntitiesSet(affectedEntities, &explosion); CommitAffectedEntitiesSet(m_scriptExplosionInfo, affectedEntities); float fSuitEnergyBeforeExplosion = 0.0f; float fHealthBeforeExplosion = 0.0f; IActor *pClientActor = g_pGame->GetIGameFramework()->GetClientActor(); if(pClientActor) { fSuitEnergyBeforeExplosion = static_cast<CPlayer *>(pClientActor)->GetNanoSuit()->GetSuitEnergy(); fHealthBeforeExplosion = pClientActor->GetHealth(); } CallScript(m_serverStateScript, "OnExplosion", m_scriptExplosionInfo); if(pClientActor) { float fDeltaSuitEnergy = fSuitEnergyBeforeExplosion - static_cast<CPlayer *>(pClientActor)->GetNanoSuit()->GetSuitEnergy(); float fDeltaHealth = fHealthBeforeExplosion - pClientActor->GetHealth(); if(fDeltaSuitEnergy >= 50.0f || fDeltaHealth >= 20.0f) { SAFE_SOUNDMOODS_FUNC(AddSoundMood(SOUNDMOOD_EXPLOSION,MIN(fDeltaSuitEnergy+fDeltaHealth,100.0f))); } } if(!gEnv->bMultiplayer && g_pGameCVars->g_spRecordGameplay) { float distance = (explosion.epicenter-pClientActor->GetEntity()->GetWorldPos()).len(); m_pGameplayRecorder->Event(pClientActor->GetEntity(), GameplayEvent(eGE_Explosion, 0, distance, 0)); } // call hit listeners if any if (m_hitListeners.empty() == false) { THitListenerVec::iterator iter = m_hitListeners.begin(); while (iter != m_hitListeners.end()) { (*iter)->OnServerExplosion(explosionInfo); ++iter; } } } if (gEnv->bClient) { if (explosionInfo.pParticleEffect) explosionInfo.pParticleEffect->Spawn(true, IParticleEffect::ParticleLoc(explosionInfo.pos, explosionInfo.dir, explosionInfo.effect_scale)); if (!gEnv->bServer) { CreateScriptExplosionInfo(m_scriptExplosionInfo, explosionInfo); } else { affectedEntities.clear(); CommitAffectedEntitiesSet(m_scriptExplosionInfo, affectedEntities); } CallScript(m_clientStateScript, "OnExplosion", m_scriptExplosionInfo); // call hit listeners if any if (m_hitListeners.empty() == false) { THitListenerVec::iterator iter = m_hitListeners.begin(); while (iter != m_hitListeners.end()) { (*iter)->OnExplosion(explosionInfo); ++iter; } } } ProcessClientExplosionScreenFX(explosionInfo); ProcessExplosionMaterialFX(explosionInfo); IEntity *pShooter = m_pEntitySystem->GetEntity(explosionInfo.shooterId); if (gEnv->pAISystem && !gEnv->bMultiplayer) { IAIObject *pShooterAI(pShooter!=NULL ? pShooter->GetAI() : NULL); gEnv->pAISystem->ExplosionEvent(explosionInfo.pos,explosionInfo.radius, pShooterAI); } }