Beispiel #1
0
//this function basically returns a smoothed movement vector, for better movement responsivness in small spaces
const Vec3 &CPlayerInput::FilterMovement(const Vec3 &desired)
{
	float frameTimeCap(min(gEnv->pTimer->GetFrameTime(),0.033f));
	float inputAccel(g_pGameCVars->pl_inputAccel);

	Vec3 oldFilteredMovement = m_filteredDeltaMovement;

	if (desired.len2()<0.01f)
	{
		m_filteredDeltaMovement.zero();
	}
	else if (inputAccel<=0.0f)
	{
		m_filteredDeltaMovement = desired;
	}
	else
	{
		Vec3 delta(desired - m_filteredDeltaMovement);

		float len(delta.len());
		if (len<=1.0f)
			delta = delta * (1.0f - len*0.55f);

		m_filteredDeltaMovement += delta * min(frameTimeCap * inputAccel,1.0f);
	}

	if (oldFilteredMovement.GetDistance(m_filteredDeltaMovement) > 0.001f)
		m_pPlayer->GetGameObject()->ChangedNetworkState( INPUT_ASPECT );

	return m_filteredDeltaMovement;
}
bool CLaser::GetProbableHit(EntityId weaponId, const IFireMode* pFireMode, Vec3& hit)
{
	if (!m_laserBeam.IsLaserActivated())
		return false;

	if(gEnv->bMultiplayer)
	{
		CWeapon* pParentWeapon = GetWeapon();
		if (pParentWeapon && pParentWeapon->IsZoomed())
		{
			return false;
		}
	}

	CWeapon* pWeapon = GetWeapon();
	int slot = pWeapon->IsOwnerFP() ? eIGS_FirstPerson : eIGS_ThirdPerson;

	Vec3 lastBeamHit = m_laserBeam.GetLastHit();
	Vec3 currentBeamPosition = pWeapon->GetSlotHelperPos(slot, "weapon_term", true);
	Matrix33 rotation = pWeapon->GetSlotHelperRotation(slot, "weapon_term", true);
	Vec3 currentBeamDirection = rotation.GetColumn1();

	const CFireMode* pCFireMode = static_cast<const CFireMode*>(pFireMode);
	const CSingle* pSingle = crygti_cast<const CSingle*>(pCFireMode);
	if (pSingle && pSingle->GetShared()->fireparams.laser_beam_uses_spread)
	{
		currentBeamDirection = pSingle->ApplySpread(currentBeamDirection, pSingle->GetSpread());
	}

	float distanceToLastHit = lastBeamHit.GetDistance(currentBeamPosition);
	hit = currentBeamPosition + currentBeamDirection * distanceToLastHit;

	return true;
}
float SearchGroup::CalculateScore(SearchSpot& searchSpot, EntityId entityID, SearchSpotQuery* query, Vec3& targetCurrentPos) const
{
	assert(query);

	Agent agent(entityID);
	if (agent.IsValid())
	{
		const Vec3 spotPosition = searchSpot.GetPos();
		const Vec3 agentPosition = agent.GetPos();

		const float agentToSpotDistance = agentPosition.GetDistance(spotPosition);
		if (agentToSpotDistance < query->minDistanceFromAgent)
		{
			return -100.0f;
		}

		float closenessToAgentScore = 0.0f;
		closenessToAgentScore = 1.0f - clamp_tpl(agentToSpotDistance, 1.0f, 50.0f) / 50.0f;
		const float closenessToTargetScore = 1.0f - clamp_tpl(spotPosition.GetDistance(m_targetPos),    1.0f, 50.0f) / 50.0f;

		float closenessToTargetCurrentPosScore = 0.0f;
		if (!targetCurrentPos.IsZeroFast())
		{
			closenessToTargetCurrentPosScore = 1.0f - clamp_tpl(spotPosition.GetDistance(targetCurrentPos), 1.0f, 50.0f) / 50.0f;
		}

		return
			closenessToAgentScore  * query->closenessToAgentWeight +
			closenessToTargetScore * query->closenessToTargetWeight +
			closenessToTargetCurrentPosScore * query->closenessToTargetCurrentPosWeight;
	}
	else
	{
		return -100.0f;
	}
}
void CSpammer::UpdatePotentialTargets()
{
	const float minLockOnDistance = m_fireParams->spammerParams.minLockOnDistance;
	const float maxLockOnDistance = m_fireParams->spammerParams.maxLockOnDistance;
	const float maxAngleCos = cry_cosf(DEG2RAD(m_fireParams->spammerParams.targetingTolerance));

	const CAutoAimManager& autoAimManager = g_pGame->GetAutoAimManager();
	const TAutoaimTargets& aaTargets = autoAimManager.GetAutoAimTargets();
	const int targetCount = aaTargets.size();

	const Vec3 probableHit = Vec3Constants<float>::fVec3_Zero;
	const Vec3 weaponPos = GetWeaponPosition(probableHit);
	const Vec3 weaponFwd = GetWeaponDirection(weaponPos, probableHit);

	m_potentialTargets.Clear();

	CPlayerVisTable::SVisibilityParams queryTargetParams(0);
	const bool flat2DMode = m_fireParams->spammerParams.targetingFlatMode;

	for (int i = 0; i < targetCount; ++i)
	{
		const SAutoaimTarget& target = aaTargets[i];
		CRY_ASSERT(target.entityId != m_pWeapon->GetOwnerId());

		if (!target.HasFlagSet(eAATF_AIHostile))
			continue;

		IEntity* pTargetEntity = gEnv->pEntitySystem->GetEntity(target.entityId);
		if (!pTargetEntity)
			continue;
		CActor* pActor = target.pActorWeak.lock().get();

		AABB bounds;
		pTargetEntity->GetWorldBounds(bounds);
		Vec3 targetPos = bounds.GetCenter();
		Vec3 targetDistVec = (targetPos - weaponPos).normalized();
		float distance = targetPos.GetDistance(weaponPos);

		if (distance <= minLockOnDistance || distance >= maxLockOnDistance)
			continue;

		float alignment;
		if (!flat2DMode)
		{
			alignment = weaponFwd * targetDistVec;
		}
		else
		{
			const CCamera& viewCamera = gEnv->pSystem->GetViewCamera();
			if (!viewCamera.IsPointVisible(targetPos))
				continue;

			alignment = Vec3(weaponFwd.x, weaponFwd.y, 0.0f).GetNormalizedSafe() * Vec3(targetDistVec.x, targetDistVec.y, 0.0f).GetNormalizedSafe();
		}

		if (alignment <= maxAngleCos)
			continue;

		const SpammerTarget finalTargetInfo = GetVisibilityTestTarget(pTargetEntity, target.entityId, pActor, bounds);

		const int kAutoaimVisibilityLatency = 0;
		queryTargetParams.targetEntityId = finalTargetInfo.targetId;
		if (!g_pGame->GetPlayerVisTable()->CanLocalPlayerSee(queryTargetParams, kAutoaimVisibilityLatency))
			continue;

		float priority = 1.0f;
		priority *= finalTargetInfo.radius;
		priority /= m_targetsAssigned.GetNumLockOns(target.entityId)+1;
		const float m = 1.0f / (1.0f - maxAngleCos);
		priority *= m * alignment + (1.0f - m);
		priority *= 0.1f;
		priority = min(priority, 1.0f);

		m_potentialTargets.AddTarget(target.entityId, priority);
	}

	float n = 0.0f;
	size_t num = m_potentialTargets.m_potentialTargets.size();
	for (size_t i = 0; i < num; ++i)
	{
		n = max(n, m_potentialTargets.m_potentialTargets[i].m_probability);
	}
	m_potentialTargets.m_totalProbability = 0.0f;
	for (size_t i = 0; num && i < m_potentialTargets.m_potentialTargets.size(); ++i)
	{
		m_potentialTargets.m_potentialTargets[i].m_probability /= n + FLT_EPSILON;
		m_potentialTargets.m_totalProbability += m_potentialTargets.m_potentialTargets[i].m_probability;
	}
}
Beispiel #5
0
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;
}