//------------------------------------------------------------------------
int CInventory::FindPrev(IEntityClass *pClass, const char *category, int firstSlot, bool wrap) const
{
	IEntitySystem *pEntitySystem = gEnv->pEntitySystem;
	for (int i = (firstSlot > -1)?firstSlot+1:0; i < m_stats.slots.size(); i++)
	{
		IEntity *pEntity = pEntitySystem->GetEntity(m_stats.slots[firstSlot-i]);
		bool ok=true;
		if (pEntity->GetClass() != pClass)
			ok=false;
		if (ok && category && category[0] && strcmp(m_pGameFrameWork->GetIItemSystem()->GetItemCategory(pEntity->GetClass()->GetName()), category))
			ok=false;

		if (ok)
			return i;
	}

	if (wrap && firstSlot > 0)
	{
		int count = GetCount();
		for (int i = 0; i < firstSlot; i++)
		{
			IEntity *pEntity = pEntitySystem->GetEntity(m_stats.slots[count-i+firstSlot]);
			bool ok=true;
			if (pEntity->GetClass() != pClass)
				ok=false;
			if (ok && category && category[0] && strcmp(m_pGameFrameWork->GetIItemSystem()->GetItemCategory(pEntity->GetClass()->GetName()), category))
				ok=false;

			if (ok)
				return i;
		}
	}

	return -1;
}
	//CGameRules::IHitInfo
	virtual void OnHit(const HitInfo &hitInfo)
	{
		if(GetPortBool(&m_actInfo, EIP_Enable) == false)
			return;

		EntityId shooter = GetPortEntityId(&m_actInfo, EIP_ShooterId);

		if(shooter != 0 && shooter != hitInfo.shooterId)
			return;

		EntityId target = GetPortEntityId(&m_actInfo, EIP_TargetId);

		if(target != 0 && target != hitInfo.targetId)
			return;

		IEntitySystem *pEntitySys = gEnv->pEntitySystem;
		IEntity *pTempEntity;

		// check weapon match
		const string &weapon = GetPortString(&m_actInfo, EIP_Weapon);

		if(weapon.empty() == false)
		{
			pTempEntity = pEntitySys->GetEntity(hitInfo.weaponId);

			if(pTempEntity == 0 || weapon.compare(pTempEntity->GetClass()->GetName()) != 0)
				return;
		}

		// check ammo match
		const string &ammo = GetPortString(&m_actInfo, EIP_Ammo);

		if(ammo.empty() == false)
		{
			pTempEntity = pEntitySys->GetEntity(hitInfo.projectileId);

			if(pTempEntity == 0 || ammo.compare(pTempEntity->GetClass()->GetName()) != 0)
				return;
		}

		ActivateOutput(&m_actInfo, EOP_ShooterId, hitInfo.shooterId);
		ActivateOutput(&m_actInfo, EOP_TargetId, hitInfo.targetId);
		ActivateOutput(&m_actInfo, EOP_WeaponId, hitInfo.weaponId);
		ActivateOutput(&m_actInfo, EOP_ProjectileId, hitInfo.projectileId);
		ActivateOutput(&m_actInfo, EOP_HitPos, hitInfo.pos);
		ActivateOutput(&m_actInfo, EOP_HitDir, hitInfo.dir);
		ActivateOutput(&m_actInfo, EOP_HitNormal, hitInfo.normal);
		ActivateOutput(&m_actInfo, EOP_Damage, hitInfo.damage);
		ISurfaceType *pSurface = g_pGame->GetGameRules()->GetHitMaterial(hitInfo.material);
		ActivateOutput(&m_actInfo, EOP_Material, string(pSurface ? pSurface->GetName() : ""));
		const char *hitType = "";

		if(CGameRules *pGR = g_pGame->GetGameRules())
			hitType = pGR->GetHitType(hitInfo.type);

		ActivateOutput(&m_actInfo, EOP_HitType, string(hitType));
	}
	virtual void OnExplosion(const ExplosionInfo &explosionInfo)
	{
		if(GetPortBool(&m_actInfo, EIP_Enable) == false)
			return;

		EntityId shooter = GetPortEntityId(&m_actInfo, EIP_ShooterId);

		if(shooter != 0 && shooter != explosionInfo.shooterId)
			return;

		EntityId impactTarget = GetPortEntityId(&m_actInfo, EIP_ImpactTargetId);

		if(impactTarget != 0 && explosionInfo.impact && impactTarget != explosionInfo.impact_targetId)
			return;

		IEntitySystem *pEntitySys = gEnv->pEntitySystem;
		IEntity *pTempEntity = pEntitySys->GetEntity(explosionInfo.weaponId);

		// check ammo match
		const string &ammo = GetPortString(&m_actInfo, EIP_Ammo);

		if(ammo.empty() == false)
		{
			if(pTempEntity == 0 || ammo.compare(pTempEntity->GetClass()->GetName()) != 0)
				return;
		}

		string ammoClass = pTempEntity ? pTempEntity->GetClass()->GetName() : "";
		ActivateOutput(&m_actInfo, EOP_ShooterId, explosionInfo.shooterId);
		ActivateOutput(&m_actInfo, EOP_Ammo, ammoClass);
		ActivateOutput(&m_actInfo, EOP_Pos, explosionInfo.pos);
		ActivateOutput(&m_actInfo, EOP_Dir, explosionInfo.dir);
		ActivateOutput(&m_actInfo, EOP_Radius, explosionInfo.radius);
		ActivateOutput(&m_actInfo, EOP_Damage, explosionInfo.damage);
		ActivateOutput(&m_actInfo, EOP_Pressure, explosionInfo.pressure);
		ActivateOutput(&m_actInfo, EOP_HoleSize, explosionInfo.hole_size);
		const char *hitType = 0;

		if(CGameRules *pGR = g_pGame->GetGameRules())
			hitType = pGR->GetHitType(explosionInfo.type);

		hitType = hitType ? hitType : "";
		ActivateOutput(&m_actInfo, EOP_Type, string(hitType));

		if(explosionInfo.impact)
		{
			ActivateOutput(&m_actInfo, EOP_ImpactTargetId, explosionInfo.impact_targetId);
			ActivateOutput(&m_actInfo, EOP_ImpactNormal, explosionInfo.impact_normal);
			ActivateOutput(&m_actInfo, EOP_ImpactVelocity, explosionInfo.impact_velocity);
		}
	}
//---------------------------------------
void CAreaAnnouncer::Init()
{
	Reset();

	//Scan for areas
	IEntityClass* pTargetClass = gEnv->pEntitySystem->GetClassRegistry()->FindClass("AreaBox");
	CRY_ASSERT_MESSAGE(pTargetClass, "Unable to find Target class AreaBox");

	if(pTargetClass)
	{
		IEntityIt* it = gEnv->pEntitySystem->GetEntityIterator();
		while ( !it->IsEnd() )
		{
			IEntity* pEntity = it->Next();
			if(pEntity->GetClass() == pTargetClass)
			{
				//check entityName
				IEntityAreaProxy *pArea = (IEntityAreaProxy*)pEntity->GetProxy(ENTITY_PROXY_AREA);
				if (pArea)
				{
					LoadAnnouncementArea(pEntity, pEntity->GetName());
				}
			}
		}
		it->Release();
	}

	CGameRules *pGameRules = g_pGame->GetGameRules();
	pGameRules->RegisterRevivedListener(this);
}
Beispiel #5
0
bool SkillKill::IsKickedCarKill(CPlayer* pKicker, CPlayer* pTargetPlayer, EntityId vehicleId)
{
    if(pKicker->IsClient() && g_pGameCVars->g_mpKickableCars)
        {
            if (IVehicle* pKickedVehicle = g_pGame->GetIGameFramework()->GetIVehicleSystem()->GetVehicle(vehicleId))
                {
                    if (CVehicleMovementBase* pMovement = StaticCast_CVehicleMovementBase(pKickedVehicle->GetMovement()))
                        {
                            if (const SVehicleMovementLargeObjectInfo* info = pMovement->GetLargeObjectInfo())
                                {
                                    if (info->kicker && info->kicker == pKicker->GetEntityId())
                                        {
                                            return true;
                                        }
                                }
                        }
                }
            else
                {
                    static const IEntityClass* pDestroyedVehicleClass = gEnv->pEntitySystem->GetClassRegistry()->FindClass("DestroyedVehicle");
                    CRY_ASSERT(pDestroyedVehicleClass);
                    IEntity* pEntity = gEnv->pEntitySystem->GetEntity(vehicleId);
                    return pEntity && pEntity->GetClass() == pDestroyedVehicleClass;
                }
        }

    return false;
}
//------------------------------------------------------------------------
void CDetonate::StartFire()
{
	if (CanFire(false))
	{
		CActor *pOwner=m_pWeapon->GetOwnerActor();

		CCCPOINT(DetonateFireMode_StartFireOK);
		m_pWeapon->RequireUpdate(eIUS_FireMode);
		m_detonationTimer = 0.1f;
		m_pWeapon->PlayAction(GetFragmentIds().fire);
		m_pWeapon->RequestDetonate();
	}
	else
	{
#if !defined(_RELEASE)
		IFireMode* pFM = m_pWeapon->GetFireMode(m_pWeapon->GetCurrentFireMode());
		EntityId projectileId = pFM ? pFM->GetProjectileId() : 0;
		IEntity * projectile = gEnv->pEntitySystem->GetEntity(projectileId);

		CryLog ("[Detonate] Failure to detonate %s '%s' (timer = %.4f, can detonate = %s, fire mode = '%s') projectile = %u (%s '%s')",
						m_pWeapon->GetEntity()->GetClass()->GetName(),
						m_pWeapon->GetEntity()->GetName(),
						m_detonationTimer,
						m_canDetonate ? "TRUE" : "FALSE",
						pFM ? pFM->GetName() : "NONE",
						projectileId,
						projectile ? projectile->GetClass()->GetName() : "NONE",
						projectile ? projectile->GetName() : "N/A");
#endif

		CCCPOINT_IF(m_detonationTimer > 0.0f, DetonateFireMode_CannotFire_TimerNotReachedZero);
		CCCPOINT(DetonateFireMode_CannotFire);
	}
}
//------------------------------------------------------------------------
int CInventory::GetCountOfClass(const char *className) const
{
	int count = 0;

	IEntitySystem *pEntitySystem = gEnv->pEntitySystem;
	
	IEntityClass* pClass = (className != NULL) ? pEntitySystem->GetClassRegistry()->FindClass( className ) : NULL;
	if (pClass)
	{
		for (TInventoryCIt it = m_stats.slots.begin(); it != m_stats.slots.end(); ++it)
		{
			IEntity *pEntity = pEntitySystem->GetEntity(*it);
			if ((pEntity != NULL) && (pEntity->GetClass() == pClass))
			{
					++count;
			}
		}
		TInventoryVectorEx::const_iterator endEx = m_stats.accessorySlots.end();
		for (TInventoryVectorEx::const_iterator cit = m_stats.accessorySlots.begin(); cit!=endEx; ++cit)
		{
			if (*cit == pClass)
			{
				count++;
			}
		}
	}

	return count;
}
Beispiel #8
0
//------------------------------------------------------------------------
int  CWeaponSystem::QueryProjectiles(SProjectileQuery &q)
{
	IEntityClass *pClass = q.ammoName?gEnv->pEntitySystem->GetClassRegistry()->FindClass(q.ammoName):0;
	m_queryResults.resize(0);

	if(q.box.IsEmpty())
	{
		for(TProjectileMap::iterator it = m_projectiles.begin(); it!=m_projectiles.end(); ++it)
		{
			IEntity *pEntity = it->second->GetEntity();

			if(pClass == 0 || pEntity->GetClass() == pClass)
				m_queryResults.push_back(pEntity);
		}
	}
	else
	{
		for(TProjectileMap::iterator it = m_projectiles.begin(); it!=m_projectiles.end(); ++it)
		{
			IEntity *pEntity = it->second->GetEntity();

			if(q.box.IsContainPoint(pEntity->GetWorldPos()))
			{
				m_queryResults.push_back(pEntity);
			}
		}
	}

	q.nCount = int(m_queryResults.size());

	if(q.nCount)
		q.pResults = &m_queryResults[0];

	return q.nCount;
}
EEntityType GetEntityType(EntityId id)
{
	int type = eET_Unknown;

	IEntitySystem *pEntitySystem = gEnv->pEntitySystem;
	if (pEntitySystem)
	{
		IEntity *pEntity = pEntitySystem->GetEntity(id);
		if (pEntity)
		{
			type = eET_Valid;

			IEntityClass *pClass = pEntity->GetClass();
			if (pClass)
			{
				const char* className = pClass->GetName();

				// Check AI
				if (pEntity->GetAI())
				{
					type |= eET_AI;
				}
				
				// Check actor
				IActorSystem *pActorSystem = gEnv->pGame->GetIGameFramework()->GetIActorSystem();
				if (pActorSystem)
				{
					IActor *pActor = pActorSystem->GetActor(id);
					if (pActor)
					{
						type |= eET_Actor;
					}
				}

				// Check vehicle
				IVehicleSystem *pVehicleSystem = gEnv->pGame->GetIGameFramework()->GetIVehicleSystem();
				if (pVehicleSystem)
				{
					if (pVehicleSystem->IsVehicleClass(className))
					{
						type |= eET_Vehicle;
					}
				}

				// Check item
				IItemSystem *pItemSystem = gEnv->pGame->GetIGameFramework()->GetIItemSystem();
				if (pItemSystem)
				{
					if (pItemSystem->IsItemClass(className))
					{
						type |= eET_Item;
					}
				}
			}
		}
	}

	return (EEntityType)type;
}
Beispiel #10
0
//------------------------------------------------------------------------
void CItem::ReAttachAccessory(EntityId id)
{
	IEntity *pEntity = gEnv->pEntitySystem->GetEntity(id);

	if(pEntity)
	{
		ItemString className = pEntity->GetClass()->GetName();
		m_accessories[className] = id;
		ReAttachAccessory(className);
	}
}
//------------------------------------------------------------------------
const char* CInventory::GetItemString(int slotId) const
{
	if (slotId<0 || slotId>=m_stats.slots.size())
		return "";

	EntityId ItemId = GetItem(slotId);
	IEntity* pEntity =	gEnv->pEntitySystem->GetEntity(ItemId);
	if(pEntity)
		return pEntity->GetClass()->GetName();
	else
		return "";
}
Beispiel #12
0
void CBurnEffectManager::AddBurnPoint(
	const EventPhysCollision& pCollision, SMikeBulletParams* pBurnBulletParams, int hitType, bool shooterIsPlayer,
	const uint8 shooterFactionID)
{
	int surfaceType = pCollision.idmat[1];

	CGameRules* pGameRules = g_pGame->GetGameRules();
	IEntity* pEntity = pCollision.iForeignData[1] == PHYS_FOREIGN_ID_ENTITY ? (IEntity*)pCollision.pForeignData[1] : NULL;
	
	const SMikeBulletParams::SBurnParams* pBurnParams = NULL;
	EntityId entityId = 0;
	
	if(pEntity)
	{
		pBurnParams = pBurnBulletParams->GetBurnClassParams(pEntity->GetClass());
		entityId = pEntity->GetId();
	}

	if(!pBurnParams)
	{
		entityId = 0;
		pBurnParams = pBurnBulletParams->GetBurnSurfaceParams(surfaceType);
	}
	
	// Burn-points are 'recycled/shared' between entities, so we can only differentiate
	// between factions. This limits the 'hit detection' to a per factions basis also.
	TBurnPoints::iterator best = entityId ? FindBurnPointOnEntity(entityId, shooterFactionID) : FindClosestBurnPoint(pCollision.pt, surfaceType, shooterFactionID);

	if (best != m_burnPoints.end())
	{
		best->m_accumulation += best->m_pBurnParams->m_buildUp;
		best->m_accumulationDelay = best->m_pBurnParams->m_dissipationDelay;
	}
	else
	{
		SBurnPoint burnPoint;
		burnPoint.m_pBurnParams = pBurnParams;
		burnPoint.m_effect = 0;
		burnPoint.m_accumulation = burnPoint.m_pBurnParams->m_buildUp;
		burnPoint.m_accumulationDelay = burnPoint.m_pBurnParams->m_dissipationDelay;
		burnPoint.m_radius = pBurnParams->m_radius;
		burnPoint.m_position = pCollision.pt;
		burnPoint.m_surfaceType = surfaceType;
		burnPoint.m_attachedEntityId = entityId;
		burnPoint.m_hitType = hitType;
		burnPoint.m_shootByPlayer = shooterIsPlayer;
		burnPoint.m_shooterFactionID = shooterFactionID;
		PushNewBurnPoint(pCollision, &burnPoint);
	}

	SpawnImpactEffect(pCollision, pBurnParams->m_impactEffectName.c_str());
}
Beispiel #13
0
//-----------------------------------------------------------------------
bool CSpectacularKill::CanSpectacularKillOn(const CActor* pTarget) const
{
	const SSpectacularKillCVars& skCVars = g_pGameCVars->g_spectacularKill;

	bool bReturn = false;

	if (pTarget)
	{
		IEntity* pTargetEntity = pTarget->GetEntity();
		// Check params existence for the target class
		const SSpectacularKillParams* pTargetParams = GetParamsForClass(pTargetEntity->GetClass());
		if (pTargetParams)
		{
			// Check redundancy, number of anims
			const float fElapsedSinceLastKill = gEnv->pTimer->GetFrameStartTime().GetSeconds() - s_lastKillInfo.timeStamp;
			if (fElapsedSinceLastKill > skCVars.minTimeBetweenKills)
			{
				const int numAnims = static_cast<int>(pTargetParams->animations.size());
				if (numAnims > 0)
				{
					const SSpectacularKillAnimation& animData = pTargetParams->animations[0];
					if ((numAnims > 1) || ((fElapsedSinceLastKill > skCVars.minTimeBetweenSameKills) ||
						(animData.killerAnimation.compare(s_lastKillInfo.killerAnim) != 0)))
					{
						// Check distance with the player
						IEntity* pLocalPlayerEntity = gEnv->pEntitySystem->GetEntity(g_pGame->GetIGameFramework()->GetClientActorId());
						CRY_ASSERT(pLocalPlayerEntity);
						if (!pLocalPlayerEntity || (skCVars.sqMaxDistanceFromPlayer < 0.0f) || 
							(pLocalPlayerEntity->GetWorldPos().GetSquaredDistance(pTarget->GetEntity()->GetWorldPos()) < skCVars.sqMaxDistanceFromPlayer))
						{
							// Check if target is not invulnerable
							bool bIsInvulnerable = false;
							if (IScriptTable* pTargetScript = pTargetEntity->GetScriptTable())
							{
								HSCRIPTFUNCTION isInvulnerableFunc = NULL;
								if (pTargetScript->GetValue("IsInvulnerable", isInvulnerableFunc) && isInvulnerableFunc)
									Script::CallReturn(gEnv->pScriptSystem, isInvulnerableFunc, pTargetScript, bIsInvulnerable);
							}
							if(!bIsInvulnerable)
							{
								// Check player's visTable to maximize the opportunities for him to actually see this?
								bReturn = true;
							}
						}
					}
				}
			}
		}
	}

	return bReturn;
}
Beispiel #14
0
void CMPTutorial::OnEntityAddedToRadar(EntityId id)
{
	// if the entity is an enemy player, show the prompt.
	if(m_events[eTE_EnemySpotted].m_status != eMS_Checking)
		return;

	IEntity* pEntity = gEnv->pEntitySystem->GetEntity(id);
	if(pEntity && pEntity->GetClass() == m_pPlayerClass)
	{
		if(g_pGame->GetGameRules()->GetTeam(id) != g_pGame->GetGameRules()->GetTeam(g_pGame->GetIGameFramework()->GetClientActor()->GetEntityId()))
		{
			TriggerEvent(eTE_EnemySpotted);
		}
	}
}
CInventory::EInventorySlots CInventory::GetSlotFromEntityID( EntityId entityID ) const
{
	IEntity* pEntity = gEnv->pEntitySystem->GetEntity(entityID);

	if (pEntity)
	{
		const char* category = m_pGameFrameWork->GetIItemSystem()->GetItemCategory(pEntity->GetClass()->GetName());

		if (!category || category[0]=='\0')
			return eInventorySlot_Last;

		TCategoriesToSlot::const_iterator catToSlotCit = m_stats.categoriesToSlot.find(CONST_TEMP_STRING(category));
		if (catToSlotCit == m_stats.categoriesToSlot.end())
			return eInventorySlot_Last;

		return catToSlotCit->second;
	}

	return eInventorySlot_Last;
}
Beispiel #16
0
bool CMonoEntityExtension::Init(IGameObject *pGameObject)
{
	SetGameObject(pGameObject);

	pGameObject->EnablePhysicsEvent( true, eEPE_OnPostStepImmediate );

	if (!GetGameObject()->BindToNetwork())
		return false;

	IEntity *pEntity = GetEntity();
	IEntityClass *pEntityClass = pEntity->GetClass();

	m_pScript = g_pScriptSystem->InstantiateScript(pEntityClass->GetName(), eScriptFlag_Entity);

	IMonoClass *pEntityInfoClass = g_pScriptSystem->GetCryBraryAssembly()->GetClass("EntityInitializationParams", "CryEngine.Native");

	SMonoEntityInfo entityInfo(pEntity);

	IMonoArray *pArgs = CreateMonoArray(1);
	pArgs->InsertMonoObject(pEntityInfoClass->BoxObject(&entityInfo));

	g_pScriptSystem->InitializeScriptInstance(m_pScript, pArgs);
	pArgs->Release();

	int numProperties;
	auto pProperties = static_cast<CEntityPropertyHandler *>(pEntityClass->GetPropertyHandler())->GetQueuedProperties(pEntity->GetId(), numProperties);

	if(pProperties)
	{
		for(int i = 0; i < numProperties; i++)
		{
			auto queuedProperty = pProperties[i];

			SetPropertyValue(queuedProperty.propertyInfo, queuedProperty.value.c_str());
		}
	}

	m_bInitialized = true;

	return true;
}
Beispiel #17
0
void CMonoEntityExtension::FullSerialize(TSerialize ser)
{
	IEntity *pEntity = GetEntity();

	ser.BeginGroup("Properties");
	auto pPropertyHandler = static_cast<CEntityPropertyHandler *>(pEntity->GetClass()->GetPropertyHandler());
	for(int i = 0; i < pPropertyHandler->GetPropertyCount(); i++)
	{
		if(ser.IsWriting())
		{
			IEntityPropertyHandler::SPropertyInfo propertyInfo;
			pPropertyHandler->GetPropertyInfo(i, propertyInfo);

			ser.Value(propertyInfo.name, pPropertyHandler->GetProperty(pEntity, i));
		}
		else
		{
			IEntityPropertyHandler::SPropertyInfo propertyInfo;
			pPropertyHandler->GetPropertyInfo(i, propertyInfo);

			char *propertyValue = nullptr;
			ser.ValueChar(propertyInfo.name, propertyValue, 0);

			pPropertyHandler->SetProperty(pEntity, i, propertyValue);
		}
	}

	ser.EndGroup();

	ser.BeginGroup("ManagedEntity");

	IMonoArray *pArgs = CreateMonoArray(1);
	pArgs->InsertNativePointer(&ser);

	m_pScript->GetClass()->InvokeArray(m_pScript->GetManagedObject(), "InternalFullSerialize", pArgs);
	pArgs->Release();

	ser.EndGroup();
}
void CVicinityDependentObjectMover::ActivateOutputPortBool( const char* szPortName )
{
	IEntity* pEntity = GetEntity();
	CRY_ASSERT( pEntity );

	IEntityClass::SEventInfo eventInfo;
	IEntityClass *pEntityClass = pEntity->GetClass();
	if ( pEntityClass->FindEventInfo( szPortName,eventInfo ) )
	{
		SEntityEvent event( ENTITY_EVENT_SCRIPT_EVENT );
		event.nParam[0] = (INT_PTR)szPortName;
		event.nParam[1] = IEntityClass::EVT_BOOL;

		bool bValue = true;
		event.nParam[2] = (INT_PTR)&bValue;

		GetEntity()->SendEvent( event );
	}
	else
	{
		GameWarning( "CVicinityDependentObjectMover::ActivateOutputPortBool: Called with undefined port %s", szPortName );
	}
}
Beispiel #19
0
int CScriptBind_HUD::TacWarning(IFunctionHandler *pH)
{
	CHUD *pHUD = g_pGame->GetHUD();
	if (!pHUD)
		return pH->EndFunction();
	std::vector<CHUDRadar::RadarEntity> buildings = *(pHUD->GetRadar()->GetBuildings());
	for(int i = 0; i < buildings.size(); ++i)
	{
		IEntity *pEntity = gEnv->pEntitySystem->GetEntity(buildings[i].m_id);
		if(!stricmp(pEntity->GetClass()->GetName(), "HQ"))
		{
			Vec3 pos = pEntity->GetWorldPos();
			pos.z += 10;
			ISound *pSound = gEnv->pSoundSystem->CreateSound("sounds/interface:multiplayer_interface:mp_tac_alarm_ambience", FLAG_SOUND_3D);
			if(pSound)
			{
				pSound->SetPosition(pos);
				pSound->Play();
			}
		}
	}
	return pH->EndFunction();
}
bool CMelee::IsMeleeFilteredOnEntity( const IEntity& targetEntity ) const
{
	static IEntityClass* s_pAnimObjectClass = gEnv->pEntitySystem->GetClassRegistry()->FindClass("AnimObject");

	if (targetEntity.GetClass() == s_pAnimObjectClass)
	{
		if (IScriptTable* pEntityScript = targetEntity.GetScriptTable())
		{
			SmartScriptTable properties;
			if (pEntityScript->GetValue("Properties", properties))
			{
				SmartScriptTable physicProperties;
				if (properties->GetValue("Physics", physicProperties))
				{
					bool bulletCollisionEnabled = true;
					return (physicProperties->GetValue("bBulletCollisionEnabled", bulletCollisionEnabled) && !bulletCollisionEnabled);
				}
			}
		}
	}

	return false;
}
void CLaserBeam::FixAttachment(IEntity* pLaserEntity)
{
	m_usingEntityAttachment = false;

	IItemSystem* pItemSystem = g_pGame->GetIGameFramework()->GetIItemSystem();
	CItem* pOwnerItem = static_cast<CItem*>(pItemSystem->GetItem(m_ownerEntityId));

	if (pOwnerItem)
	{
		IEntity* pOwnerEntity = pOwnerItem->GetEntity();
		IEntity* pAttachedEntity = pOwnerEntity;
		const char* attach_helper = "laser_term";

		Vec3 offset = pOwnerItem->GetSlotHelperPos(m_geometrySlot, attach_helper, false);

		if(m_geometrySlot == eIGS_FirstPerson)
		{
			if(pOwnerItem->IsAccessory())
			{
				EntityId parentId = pOwnerItem->GetParentId();

				if(parentId)
				{
					if(CItem* pParentItem = static_cast<CItem*>(pItemSystem->GetItem(parentId)))
					{
						const SAccessoryParams* pParams = pParentItem->GetAccessoryParams(pAttachedEntity->GetClass());

						attach_helper = pParams->attach_helper.c_str();
						pAttachedEntity = pParentItem->GetEntity();
					}
				}
			}

			if(pAttachedEntity)
			{
				ICharacterInstance *pCharacter = pAttachedEntity->GetCharacter(eIGS_FirstPerson);
				if (pCharacter)
				{
					IAttachmentManager *pAttachmentManager = pCharacter->GetIAttachmentManager();

					IAttachment *pLaserAttachment = pAttachmentManager->GetInterfaceByName(LASER_ATTACH_NAME);

					if(!pLaserAttachment)
					{
						IAttachment *pAttachment = pAttachmentManager->GetInterfaceByName(attach_helper);

						if(pAttachment)
						{
							const char* pBone = pCharacter->GetICharacterModel()->GetICharacterModelSkeleton()->GetJointNameByID(pAttachment->GetJointID());

							pLaserAttachment = pAttachmentManager->CreateAttachment(LASER_ATTACH_NAME, CA_BONE, pBone);

							if(pLaserAttachment)
							{
								QuatT relative = pAttachment->GetAttRelativeDefault();

								if(pOwnerItem->GetEntity() != pAttachedEntity)
								 {
									Matrix34 mtx(relative);
									relative.t = relative * offset;
								}

								pLaserAttachment->SetAttRelativeDefault(relative);
							}
						}
					}

					if(pLaserAttachment)
					{
						CEntityAttachment* pEntAttach = new CEntityAttachment;

						pEntAttach->SetEntityId(m_laserEntityId);
						pLaserAttachment->AddBinding(pEntAttach);
						pLaserAttachment->HideAttachment(0);

						m_usingEntityAttachment = true;
					}		
				}
			}
		}	

		if(!m_usingEntityAttachment && pOwnerEntity)
		{
			pOwnerEntity->AttachChild(pLaserEntity);
			pLaserEntity->SetLocalTM(Matrix34::CreateTranslationMat(offset));
		}
	}
}
void CPlayerPlugin_CurrentlyTargetting::Update(float dt)
{
	m_currentTargetTime += dt;	//updated locally for all players (so doesn't have to be synced)

	assert (IsEntered());
	if (m_ownerPlayer->IsClient())
	{
		EntityId newTargetId = !m_ownerPlayer->IsDead() ? m_ownerPlayer->GetGameObject()->GetWorldQuery()->GetLookAtEntityId() : 0;

		if (newTargetId)
		{
			IActor * targettedActor = g_pGame->GetIGameFramework()->GetIActorSystem()->GetActor(newTargetId);
			if (targettedActor == NULL || targettedActor->IsDead())
			{
				newTargetId = 0;
			}
		}

		if (m_currentTarget != newTargetId)
		{
			m_currentTarget = newTargetId;










			CCCPOINT_IF(m_currentTarget, PlayerState_LocalPlayerNowTargettingSomebody);
			CCCPOINT_IF(!m_currentTarget, PlayerState_LocalPlayerNowTargettingNobody);

			m_currentTargetTime = 0.0f;
			CHANGED_NETWORK_STATE(m_ownerPlayer, CPlayer::ASPECT_CURRENTLYTARGETTING_CLIENT);
		}
	}

#if PLAYER_PLUGIN_DEBUGGING
	IEntity* pEntity = gEnv->pEntitySystem->GetEntity(m_currentTarget);
	PlayerPluginWatch ("Target e%05d (%s %s) - %.2f", m_currentTarget, pEntity ? pEntity->GetName() : "NULL", pEntity ? pEntity->GetClass()->GetName() : "entity", m_currentTargetTime);
#endif
}
		Dumper(EntityId entityId, const char *desc)
		{
			IEntitySystem *pEntitySystem = gEnv->pEntitySystem;
			IEntity *pEntity = pEntitySystem->GetEntity(entityId);
			CryLogAlways(">> Id: %d [%s] $3%s $5%s", entityId, pEntity?pEntity->GetName():"<unknown>", pEntity?pEntity->GetClass()->GetName():"<unknown>", desc?desc:"");
		}
Beispiel #24
0
bool CEditorGame::BuildEntitySerializationList(XmlNodeRef output)
{
	if(!output)
		return false;

	typedef std::vector<IFlowGraph*> TFGVector;

	TSerializationData entityData;	// all entities
	TFGVector flowGraphs;						// all flowgraphs

	// build the all-entity list, and keep a record of those entities 
	//	which have a flowgraph attached
	IEntityIt* pIt = gEnv->pEntitySystem->GetEntityIterator();
	while(IEntity* pEntity = pIt->Next())
	{
		IEntityFlowGraphProxy* pFGProxy = static_cast<IEntityFlowGraphProxy*>(pEntity->GetProxy(ENTITY_PROXY_FLOWGRAPH));
		if(pFGProxy)
		{
			flowGraphs.push_back(pFGProxy->GetFlowGraph());
			MarkEntityForSerialize(entityData, pEntity, eST_FlowGraphContainer);
		}

		if (!stricmp(pEntity->GetClass()->GetName(), "Constraint"))
		{
			MarkEntityForSerialize(entityData, pEntity, eST_Class);

			float constraintRadius = -FLT_MAX;

			if (IScriptTable* entityTable = pEntity->GetScriptTable())
			{
				SmartScriptTable props;
				if (entityTable->GetValue("Properties", props))
					props->GetValue("radius", constraintRadius);
			}

			if (constraintRadius > 0.0f)
			{
				const Vec3 boxMin = pEntity->GetWorldPos() - Vec3(constraintRadius + 0.05f);
				const Vec3 boxMax = pEntity->GetWorldPos() + Vec3(constraintRadius + 0.05f);

				IPhysicalEntity** nearbyEntities = 0;

				if (size_t entityCount = gEnv->pPhysicalWorld->GetEntitiesInBox(boxMin, boxMax, nearbyEntities, ent_all))
				{
					for (size_t i = 0; i < entityCount; ++i)
					{
						if (IEntity* nearbyEntity = gEnv->pEntitySystem->GetEntityFromPhysics(nearbyEntities[i]))
							MarkEntityForSerialize(entityData, nearbyEntity, eST_ConstraintNeighbour);
					}
				}
			}
			else
			{
				CryLogAlways("Failed to find a value radius property for constraint '%s'. "
					"Serialization for this constraint might not work.", pEntity->GetName());
			}
		}
		else if(ShouldSaveEntityClass(pEntity)) // some classes should always be saved
			MarkEntityForSerialize(entityData, pEntity, eST_Class);
	}

	// for each FG, mark all entities referenced as needing saving
	for(TFGVector::const_iterator it = flowGraphs.begin(); it != flowGraphs.end(); ++it)
	{
		if(!*it)
			continue;

		IFlowNodeIteratorPtr nodeIt = (*it)->CreateNodeIterator();
		TFlowNodeId nodeId = 0;
		while(IFlowNodeData* pNode = nodeIt->Next(nodeId))
		{
			EntityId nodeEntity = (*it)->GetEntityId(nodeId);
			if(nodeEntity != 0)
			{
				IEntity* pEntity = gEnv->pEntitySystem->GetEntity(nodeEntity);
				MarkEntityForSerialize(entityData, pEntity, eST_FlowGraph);
			}
		}
	}


	// now do the same for entities moved by trackview
	for(int i=0; i<gEnv->pMovieSystem->GetNumSequences(); ++i)
	{
		IAnimSequence* pSeq = gEnv->pMovieSystem->GetSequence(i);
		int nodeCount = pSeq->GetNodeCount();
		for(int j=0; j<nodeCount; ++j)
		{
			IAnimNode* pNode = pSeq->GetNode(j);
			if(pNode)
			{
				IEntity* pEntity = pNode->GetEntity();
				if(pEntity && ShouldSaveTrackViewEntityClass(pEntity)) 
				{
					MarkEntityForSerialize(entityData, pEntity, eST_TrackView);
				}

				if(EntityGUID* guid = pNode->GetEntityGuid())
				{
					EntityId id = gEnv->pEntitySystem->FindEntityByGuid(*guid);
					if(id != 0)
					{
						IEntity* pEntity2 = gEnv->pEntitySystem->GetEntity(id);
						MarkEntityForSerialize(entityData, pEntity2, eST_TrackView);
					}
				}
			}
		}
	}

	// now check entity links: any entity linked to or from a serialized
	//	entity must also be serialized
	for(TSerializationData::iterator it = entityData.begin(), end = entityData.end(); it != end; ++it)
	{
		IEntity* pEntity = gEnv->pEntitySystem->GetEntity(it->first);
		assert(pEntity);

		IEntityLink* pLink = pEntity->GetEntityLinks();
		while(pLink)
		{
			IEntity* pLinkedEntity = gEnv->pEntitySystem->GetEntity(pLink->entityId);
			assert(pLinkedEntity);

			MarkEntityForSerialize(entityData, pLinkedEntity, eST_Linked);

			pLink = pLink->next;
		}
	}

	// output the final file, plus debug info

#if SERIALIZATION_EXPORT_DEBUG
	int saveCount = 0;
	int totalCount = 0;

	int fgCount = 0;
	int fgRefCount = 0;
	int classCount = 0;
	int tvCount = 0;
	int childCount = 0;
	int parentCount = 0;
	int linkCount = 0;

	int fgUnique = 0;
	int fgRefUnique = 0;
	int classUnique = 0;
	int tvUnique = 0;
	int linkUnique = 0;

	typedef std::map<string, int> TClassSaveInfo;
	TClassSaveInfo classesNotSaved;
	TClassSaveInfo classesSaved;
#endif

	output->setTag("EntitySerialization");
	for(TSerializationData::const_iterator it = entityData.begin(); it != entityData.end(); ++it)
	{
		IEntity* pEntity = gEnv->pEntitySystem->GetEntity(it->first);

#if SERIALIZATION_EXPORT_DEBUG
		++totalCount;
		string reasons = "Saving: ";
#endif

		if(it->second != eST_NotSerialized)
		{
			XmlNodeRef child = output->createNode("Entity");
			child->setAttr("id", it->first);
			//child->setAttr("class", pEntity->GetClass()->GetName());	// debug check
			//child->setAttr("name", pEntity->GetName());								// debug check
			output->addChild(child);

#if SERIALIZATION_EXPORT_DEBUG
			classesSaved[pEntity->GetClass()->GetName()]++;

			++saveCount;
			if(it->second & eST_FlowGraphContainer)
			{
				reasons += "FG Container; ";
				++fgCount;
			}
			if(it->second & eST_FlowGraph)
			{
				reasons += "FG reference; ";
				++fgRefCount;
			}
			if(it->second & eST_Class)
			{
				reasons += "Class; ";
				++classCount;
			}
			if(it->second & eST_TrackView)
			{
				reasons += "Trackview; ";
				++tvCount;
			}
			if(it->second & eST_Child)
			{
				reasons += "Child; ";
				++childCount;
			}
			if(it->second & eST_Parent)
			{
				reasons += "Parent; ";
				++parentCount;
			}
			if(it->second & eST_Linked)
			{
				reasons += "Linked; ";
				++linkCount;
			}

			// unique counts (things added as a result of only one condition)
			switch(it->second)
			{
			case eST_FlowGraph:
				++fgRefUnique;
				break;
			case eST_FlowGraphContainer:
				++fgUnique;
				break;
			case eST_Class:
				++classUnique;
				break;
			case eST_TrackView:
				++tvUnique;
				break;
			case eST_Linked:
				++linkUnique;
				break;
			default:
				break;
			}
		}
		else
		{
			reasons = "Not saving";
			classesNotSaved[pEntity->GetClass()->GetName()]++;
		}

		CryLogAlways("Entity %s (%d, class %s) : %s", pEntity->GetName(), it->first, pEntity->GetClass()->GetName(), reasons.c_str());		
#endif
		}
	}
void CPlayerVisTable::Update(float dt)
{
	const int numEntries = m_numUsedVisTableEntries;

	CryPrefetch(m_visTableEntries);

	//Flip the buffers
	m_currentBufferProcessing = 1 - m_currentBufferProcessing;
	m_currentBufferTarget			= 1 - m_currentBufferTarget;

	Vec3 localPlayerPosn;

	GetLocalPlayerPosn(localPlayerPosn);

	//Iterate over all of the vis table entries and calculate the priorities

	int numAdded = AddVisTableEntriesToPriorityList();

	//Iterate over all of the vis table entries
	for(int i = 0; i < numAdded; ++i)
	{
		const SVisTablePriority& visTableEntry = m_visTablePriorities[i];
		DoVisibilityCheck(localPlayerPosn, *visTableEntry.visInfo, visTableEntry.visIndex);
	}

	const int kNumVistableEntries = m_numUsedVisTableEntries;
	for(int i = 0; i < kNumVistableEntries; i++)
	{
		m_visTableEntries[i].framesSinceLastCheck++;			
	}

#if ALLOW_VISTABLE_DEBUGGING
	if(g_pGameCVars->pl_debug_vistableIgnoreEntities)
	{
		UpdateIgnoreEntityDebug(); 
	}

	if(g_pGameCVars->pl_debug_vistable)
	{
		const float white[] = {1.0f,1.0f,1.0f,1.0f};

		const int kNumUsedVistableEntries = m_numUsedVisTableEntries;
		VisEntryIndex worstIndex = -1;

		int worstLatency = 0;
		for(int i = 0; i < kNumUsedVistableEntries; i++)
		{
			if((m_visTableEntries[i].flags & eVF_Requested) && !(m_visTableEntries[i].flags & eVF_Remove) && (m_visTableEntries[i].framesSinceLastCheck > worstLatency))
			{
				worstLatency	= m_visTableEntries[i].framesSinceLastCheck;
				worstIndex		= i;
			}
		}

		int assertAfterThisManyFrames = g_pGameCVars->g_assertWhenVisTableNotUpdatedForNumFrames;
		if (worstLatency >= assertAfterThisManyFrames && worstIndex > 0 && worstIndex < kNumUsedVistableEntries)
		{
			IEntity * entity = gEnv->pEntitySystem->GetEntity(m_visTableEntries[worstIndex].entityId);
			CRY_ASSERT_MESSAGE(false, string().Format("%u frames have passed since last check of vis-table element %d (entity %d = %s \"%s\") flags=%u", m_visTableEntries[worstIndex].framesSinceLastCheck, worstIndex, m_visTableEntries[worstIndex].entityId, entity ? entity->GetClass()->GetName() : "NULL", entity ? entity->GetName() : "NULL", m_visTableEntries[worstIndex].flags));
		}


		gEnv->pRenderer->Draw2dLabel(20.f, 500.f, 1.5f, white, false, "VistableInfo:\n  Num Linetests this frame: %d\n  Num queries this frame: %d\n  Worst latency: %d", m_numLinetestsThisFrame, m_numQueriesThisFrame, worstLatency);
	
		if (g_pGameCVars->pl_debug_vistable == 2)
		{
			m_debugDraw.Update();
		}
	}

	m_numQueriesThisFrame = 0;
#endif

	m_numLinetestsThisFrame = 0;

	ClearRemovedEntities();
}
Beispiel #26
0
// returns true if firing is allowed
bool CPlant::GetPlantingParameters(Vec3& pos, Vec3& dir, Vec3& vel) const
{
	CActor *pActor = m_pWeapon->GetOwnerActor();
	IMovementController *pMC = pActor?pActor->GetMovementController():0;
	SMovementState info;
	if (pMC)
		pMC->GetMovementState(info);

	if (m_pWeapon->GetStats().fp)
		pos = m_pWeapon->GetSlotHelperPos( eIGS_FirstPerson, m_plantparams.helper.c_str(), true);
	else if (pMC)
		pos = info.eyePosition+info.eyeDirection*0.25f;
	else
		pos = pActor->GetEntity()->GetWorldPos();

	if (pMC)
		dir = info.eyeDirection;
	else
		dir = pActor->GetEntity()->GetWorldRotation().GetColumn1();

	if (IPhysicalEntity *pPE=pActor->GetEntity()->GetPhysics())
	{
		pe_status_dynamics sv;
		if (pPE->GetStatus(&sv))
		{
			if (sv.v.len2()>0.01f)
			{
				float dot=sv.v.GetNormalized().Dot(dir);
				if (dot<0.0f)
					dot=0.0f;
				vel=sv.v*dot;
			}
		}
	}

	// if the ammo should be placed (claymore/mine) rather than thrown forward (c4), check if we can do so...
	if(m_plantparams.place_on_ground)
	{
		ray_hit hit;
		static const int objTypes = ent_static | ent_terrain;
		static const unsigned int flags = rwi_stop_at_pierceable|rwi_colltype_any;
		static IPhysicalEntity* pSkipEnts[10];
		int nskip = CSingle::GetSkipEntities(m_pWeapon, pSkipEnts, 10);
		int res = gEnv->pPhysicalWorld->RayWorldIntersection(pos, 2.0f * dir, objTypes, flags, &hit, 1, pSkipEnts, nskip);
		if(!res)
			return false;
		else
		{
			// check surface normal - must be close to up
			if(hit.n.z < 0.8f)
				return false;

 			// special case to stop stacking of claymores/mines (they are static so are hit by the ray)
 			if(hit.pCollider && hit.pCollider->GetiForeignData() == PHYS_FOREIGN_ID_ENTITY)
			{
				IEntity * pEntity = (IEntity*)hit.pCollider->GetForeignData(PHYS_FOREIGN_ID_ENTITY);
				if(pEntity)
				{
					if(!m_pClaymoreClass)
						m_pClaymoreClass = gEnv->pEntitySystem->GetClassRegistry()->FindClass("claymoreexplosive");
					if(!m_pAVMineClass)
						m_pAVMineClass = gEnv->pEntitySystem->GetClassRegistry()->FindClass("avexplosive");

					if(pEntity->GetClass() == m_pClaymoreClass || pEntity->GetClass() == m_pAVMineClass)
						return false;
				}
 			}

			// second check to see if there is another object in the way
			float hitDist = hit.dist;
			int res = gEnv->pPhysicalWorld->RayWorldIntersection(pos, 2.0f * dir, ent_all, flags, &hit, 1, pSkipEnts, nskip);
			if(res && hit.dist < hitDist-0.1f)
			{
				return false;
			}

			pos = hit.pt;
		}
	}

	return true;
}
//------------------------------------------------------------------------
// returns true if entity is killed, false if it is not
bool CGameRulesMPDamageHandling::SvOnHit( const HitInfo &hitInfo )
{
	const HitTypeInfo * pHitTypeInfo = m_pGameRules->GetHitTypeInfo(hitInfo.type);

#if !defined(_RELEASE)
	if(!pHitTypeInfo)
		CryFatalError("By ::SvOnHit() all hit info should have a hit type that is valid and registered in the GameRules. This isn't true of type %d!", hitInfo.type);
#endif

	SDamageHandling damageHandling(&hitInfo, 1.0f);

	float damage = hitInfo.damage;

	IActorSystem* pActorSystem = g_pGame->GetIGameFramework()->GetIActorSystem();
	CActor *pTargetActor = static_cast<CActor*>(pActorSystem->GetActor(hitInfo.targetId));
	CActor *pShooterActor = static_cast<CActor*>(pActorSystem->GetActor(hitInfo.shooterId));
	CPlayer* pShooterPlayer = (pShooterActor && pShooterActor->IsPlayer()) ? static_cast<CPlayer*>(pShooterActor) : NULL ;

	bool isPlayer = pTargetActor != NULL && pTargetActor->IsPlayer();

#ifndef _RELEASE
	//--- Fix to allow the damage handling to work for these entity classes in the same way as for Players
	static IEntityClass* sDamEntClass = gEnv->pEntitySystem->GetClassRegistry()->FindClass("DamageTestEnt");
	isPlayer |= pTargetActor != NULL && pTargetActor->GetEntity()->GetClass() == sDamEntClass;
#endif

	CPlayer* pPlayer = isPlayer ? static_cast<CPlayer*>(pTargetActor) : NULL;
	const bool isMelee = ((pHitTypeInfo->m_flags & CGameRules::EHitTypeFlag::IsMeleeAttack) != 0);
	const bool checkHeadshots = ((pHitTypeInfo->m_flags & CGameRules::EHitTypeFlag::IgnoreHeadshots) == 0);

	bool bIsHeadShot = false;
	if(pPlayer && hitInfo.partId >= 0 && checkHeadshots)
	{
		bIsHeadShot = pPlayer->IsHeadShot(hitInfo);

		if (!bIsHeadShot && g_pGameCVars->g_mpHeadshotsOnly)
		{
			damage = 0.f;
		}
	}

	//If the player has died more than kTimeToAllowKillsAfterDeath seconds ago, we disallow any damage they apply, unless the hit type is flagged as allowing it.
	static const float kTimeToAllowKillsAfterDeath = 0.05f;
	if(pTargetActor && pShooterPlayer && !hitInfo.hitViaProxy
		&& ((pHitTypeInfo->m_flags & CGameRules::EHitTypeFlag::AllowPostDeathDamage) == 0) && pShooterActor->IsDead()
		&& (gEnv->pTimer->GetFrameStartTime().GetSeconds() - pShooterPlayer->GetDeathTime()) > kTimeToAllowKillsAfterDeath)
	{
		damage = 0.0f;
	}

	IGameRulesStateModule *stateModule = m_pGameRules->GetStateModule();
	IGameRulesRoundsModule* pRoundsModule = m_pGameRules->GetRoundsModule();

	if ( (stateModule != NULL && (stateModule->GetGameState() == IGameRulesStateModule::EGRS_PostGame)) || 
		   (pRoundsModule!= NULL && !pRoundsModule->IsInProgress() ))
	{
		// No damage allowed once the game has ended, except in cases where it would cause graphical glitches
		if (hitInfo.type != CGameRules::EHitType::PunishFall)
		{
			damage = 0.0f;
		}
	}

	IEntity *pTarget = gEnv->pEntitySystem->GetEntity(hitInfo.targetId);

#if defined(SERVER_CHECKS)

	if(damage != 0.0f)
	{
		int nNewCheckCounter = m_checkCounter + 1;
		
		if (CItem *pItem = static_cast<CItem *>(g_pGame->GetIGameFramework()->GetIItemSystem()->GetItem(hitInfo.weaponId)))
		{
			if(CWeapon * pWeapon = static_cast<CWeapon*>(pItem->GetIWeapon()))
			{
				int nFireModeFromShotId = GetFireModeFromShotId(hitInfo.shotId);

				static const int kCheckFreq = 7;

				if(pShooterActor &&	nNewCheckCounter == kCheckFreq)
				{
					float fDamageAtXMeters = 0.0f;

					float fDistance2D, fDistanceMax, fNetLagSeconds;
					CServerCheatMonitor::GetHitValidationInfo(*pShooterActor, hitInfo, fDistance2D, fDistanceMax, fNetLagSeconds);

					bool bDoDamageValidation = false;

					if(isMelee)
					{
						if(CMelee * pMelee = pWeapon->GetMelee())
						{
							//This check can't be used for everything because the default firemode returns '0.f' for range and only CMelee extends it
							//	the horizontal player speed is x 2.0f as the players could have potentially immediately turned and run away from each other
							float fMeleeRangeError = fDistance2D - (pMelee->GetRange() + (CServerCheatMonitor::kMaxHorizontalPlayerSpeed * fNetLagSeconds * 2.0f));
							if(fMeleeRangeError > 0.1f)
							{
								g_pGame->GetAntiCheatManager()->FlagActivity(eCT_MeleeRange, pShooterActor->GetChannelId(), fMeleeRangeError);
							}

							fDamageAtXMeters = pMelee->GetDamageAmountAtXMeters(fDistance2D);

							bDoDamageValidation = true;
						}
					}
					else
					{
						//////////////////////////////////////////////////////////////////////
						// Verify that the hit is from a valid shot

						DoShotValidation(hitInfo, pHitTypeInfo, pShooterActor);

						//////////////////////////////////////////////////////////////////////


						CFireMode * pFireMode = static_cast<CFireMode*>(pWeapon->GetFireMode(nFireModeFromShotId));

						if(pFireMode)
						{
							const SFireModeParams * pParams = pFireMode->GetShared();

							char projectileClassName[128];
							g_pGame->GetIGameFramework()->GetNetworkSafeClassName(projectileClassName, sizeof(projectileClassName), hitInfo.projectileClassId);
							IEntityClass * pProjectileClass = gEnv->pEntitySystem->GetClassRegistry()->FindClass(projectileClassName);

							if((pProjectileClass && (pProjectileClass == pParams->fireparams.ammo_type_class ||	pProjectileClass == pParams->plantparams.ammo_type_class)))
							{
								float fBulletSpeed = 100.f;
								const SAmmoParams * pAmmoParams = g_pGame->GetWeaponSystem()->GetAmmoParams(pFireMode->GetAmmoType());
								if(pAmmoParams)
								{
									fBulletSpeed = pAmmoParams->speed;
								}

								//Might have been closer when the shot was fired
								const float fMaxTimeSinceShot	= ((fDistanceMax / fBulletSpeed) * 2.0f) + fNetLagSeconds; //Should be less than this. Laaaaarge fudge factor
								float fDistance_Conservative	= fDistance2D - (fMaxTimeSinceShot * CServerCheatMonitor::kMaxHorizontalPlayerSpeed);

								fDamageAtXMeters = pFireMode->GetDamageAmountAtXMeters(fDistance_Conservative); 
							}
						}
						else if(pHitTypeInfo->m_flags & CGameRules::EHitTypeFlag::ValidationRequired)
						{
							CryStackStringT<char, 256> invalidFireModeMessage;
							invalidFireModeMessage.Format("Invalid fire mode, weapon: '%s', firemode: %d", pWeapon->GetEntity()->GetName(), nFireModeFromShotId);
							g_pGame->GetAntiCheatManager()->FlagActivity(eCT_ValidHitInfo, pShooterActor->GetChannelId(), invalidFireModeMessage.c_str());
						}
					}

					float fDamageFromWeapon = hitInfo.damage;			

					if(fDamageFromWeapon > fDamageAtXMeters && fDamageAtXMeters > 0.0f)
					{
						//Log the ratio of actual damage to expected damage, e.g. 1.2 x expected
						CryStackStringT<char, 256> excessiveDamageMessage;
						excessiveDamageMessage.Format("Weapon '%s', firemode %d", pWeapon->GetEntity()->GetName(), nFireModeFromShotId);
						g_pGame->GetAntiCheatManager()->FlagActivity(eCT_WeaponDamage, pShooterActor->GetChannelId(), fDamageFromWeapon / fDamageAtXMeters, excessiveDamageMessage.c_str());
					}


					if(pTargetActor)
					{
						CServerCheatMonitor::ValidateTargetActorPositionAgainstHit(*pTargetActor, hitInfo, fNetLagSeconds);
					}
					
					nNewCheckCounter = 0;
				}
				else
				{
					nNewCheckCounter = kCheckFreq - 1;
				}
			}
		}
		m_checkCounter = nNewCheckCounter;
	}

	// Update the shotcounter for tracking headshots and traversal times
	if(pShooterPlayer && (pHitTypeInfo->m_flags & CGameRules::EHitTypeFlag::ValidationRequired))
	{
		char netName[128];
		g_pGame->GetIGameFramework()->GetNetworkSafeClassName(netName, sizeof(netName), hitInfo.projectileClassId);
		IEntityClass * pProjectileClass = gEnv->pEntitySystem->GetClassRegistry()->FindClass(netName);
		if (pProjectileClass)
		{
			CShotCounter* pShotCounter = pShooterPlayer->GetShotCounter();
			pShotCounter->RecordHit(hitInfo, bIsHeadShot);
		}
	}
	
#endif // SERVER_CHECKS

	IEntityClass* pTargetClass = pTarget ? pTarget->GetClass() : NULL;

	// Check for friendly fire
	if( bool bCheckFriendlyFire = ((hitInfo.targetId!=hitInfo.shooterId) && (hitInfo.type!=CGameRules::EHitType::EventDamage)) )
	{
		if(IVehicle* pTargetVehicle = g_pGame->GetIGameFramework()->GetIVehicleSystem()->GetVehicle(hitInfo.targetId))
		{
			if(IActor* pDriverTargetVehicle = pTargetVehicle->GetDriver())
			{
				// Vehicle driver shot own vehicle (same as shooting yourself), don't do friendly fire.
				bCheckFriendlyFire = pDriverTargetVehicle->GetEntityId()!=hitInfo.shooterId;
			}
		}
		if(bCheckFriendlyFire)
		{
			if (m_pGameRules->GetTeamCount() > 1)
			{
				int shooterTeamId = m_pGameRules->GetTeam(hitInfo.shooterId);
				int targetTeamId = m_pGameRules->GetTeam(hitInfo.targetId);

				if (shooterTeamId && (shooterTeamId == targetTeamId))
				{
					damage = GetFriendlyFireDamage(damage, hitInfo, pTargetActor);
				}
			}
		}
	}

	if (damage <= 0.f)
	{
		// If the hit isn't doing anything bail, this means any hit that gets past here has damage associated with it and thus wants to
		// display a hit indicator
		return false;
	}

	if (pPlayer)
	{
		if(hitInfo.partId >= 0 && !isMelee)
		{
			damageHandling.damageMultiplier *= pPlayer->GetBodyDamageMultiplier(hitInfo);
		}

		if (isMelee)
		{
			damageHandling.damageMultiplier *= g_pGameCVars->pl_melee.damage_multiplier_mp;
		}
	}

	damage *= damageHandling.damageMultiplier;

	HitInfo hitInfoWithDamage = hitInfo;
	hitInfoWithDamage.damage = damage;

	if(pPlayer)
	{
		SActorStats* pStats = pPlayer->GetActorStats();
		float actorHealth = pPlayer->GetHealth();

		if(pStats)
		{
#ifndef _RELEASE
			if (g_pGameCVars->g_LogDamage)
			{
				char weaponClassName[64], projectileClassName[64];

				CryLog ("[DAMAGE] %s '%s' took %.3f '%s' damage (%.3f x %.3f) weapon=%s projectile=%s",
						pPlayer->GetEntity()->GetClass()->GetName(), pPlayer->GetEntity()->GetName(),
						damage, m_pGameRules->GetHitType(hitInfo.type),
						hitInfo.damage, damageHandling.damageMultiplier,
						g_pGame->GetIGameFramework()->GetNetworkSafeClassName(weaponClassName, sizeof(weaponClassName), hitInfo.weaponClassId) ? weaponClassName : "none",
						g_pGame->GetIGameFramework()->GetNetworkSafeClassName(projectileClassName, sizeof(projectileClassName), hitInfo.projectileClassId) ? projectileClassName : "none");
			}
#endif

			if(pStats->bStealthKilling && actorHealth <= damage)
			{
				if(pPlayer->GetStealthKill().GetTargetId() != hitInfoWithDamage.shooterId)
				{
					pPlayer->StoreDelayedKillingHitInfo(hitInfoWithDamage);
				}
				
				hitInfoWithDamage.damage = 0;
			}
			else if (pStats->bStealthKilled && hitInfoWithDamage.type != CGameRules::EHitType::StealthKill)
			{
				hitInfoWithDamage.damage = 0;
			}
		}
	}
		
	bool bKilled = SvOnHitScaled(hitInfoWithDamage);

	return bKilled;
}
//------------------------------------------------------------------------
void CMelee::Impulse(const Vec3 &pt, const Vec3 &dir, const Vec3 &normal, IPhysicalEntity *pCollider, int partId, int ipart, int surfaceIdx, float impulseScale)
{
	if(m_noImpulse)
	{
		m_noImpulse = false;
		return;
	}

	if (pCollider && m_pShared->meleeparams.impulse > 0.001f)
	{
		bool strengthMode = false;
		CPlayer *pPlayer = (CPlayer *)m_pWeapon->GetOwnerActor();
		pe_status_dynamics dyn;

		if (!pCollider->GetStatus(&dyn))
		{
			if(strengthMode)
			{
				impulseScale *= 3.0f;
			}
		}
		else
		{
			impulseScale *= clamp((dyn.mass * 0.01f), 1.0f, 15.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 = (IEntity *) pCollider->GetForeignData(PHYS_FOREIGN_ID_ENTITY);

		if(gEnv->bMultiplayer && pEntity)
		{
			if(g_pGame->GetIGameFramework()->GetIActorSystem()->GetActor(pEntity->GetId()) == NULL)
			{
				impulseScale *= 0.33f;
			}
		}

		if(pEntity)
		{
			bool crapDollFilter = false;
#ifdef CRAPDOLLS
			static IEntityClass *pDeadBodyClass = gEnv->pEntitySystem->GetClassRegistry()->FindClass("DeadBody");

			if (pEntity->GetClass() == pDeadBodyClass)
			{
				crapDollFilter = true;
			}

#endif //CRAPDOLLS

			if (!crapDollFilter)
			{
				IEntityPhysicalProxy *pPhysicsProxy = (IEntityPhysicalProxy *)pEntity->GetProxy(ENTITY_PROXY_PHYSICS);
				CActor *pActor = (CActor *)g_pGame->GetIGameFramework()->GetIActorSystem()->GetActor(pEntity->GetId());

				if (pActor)
				{
					SActorStats *pAS = pActor->GetActorStats();

					if (pAS && pAS->isRagDoll)
					{
						//marcok: talk to me before touching this
						impulseScale = 1.0f; //jan: melee impulses were scaled down, I made sure it still "barely moves"
#ifdef CRAPDOLLS
						crapDollFilter = true;
#endif //CRAPDOLLS
					}
				}

				// scale impulse up a bit for player
				if (!crapDollFilter)
				{
					pPhysicsProxy->AddImpulse(partId, pt, dir * m_pShared->meleeparams.impulse * impulseScale * m_meleeScale, true, 1.f);
				}
			}
		}
		else
		{
			pe_action_impulse ai;
			ai.partid = partId;
			ai.ipart = ipart;
			ai.point = pt;
			ai.iApplyTime = 0;
			ai.impulse = dir * (m_pShared->meleeparams.impulse * impulseScale * m_meleeScale);
			pCollider->Action(&ai);
		}

		ISurfaceTypeManager *pSurfaceTypeManager = gEnv->p3DEngine->GetMaterialManager()->GetSurfaceTypeManager();
		int invId = pSurfaceTypeManager->GetSurfaceTypeByName("mat_invulnerable")->GetId();
		// create a physical collision to break trees
		pe_action_register_coll_event collision;
		collision.collMass = 0.005f; // this is actually ignored
		collision.partid[1] = partId;
		// collisions involving partId<-1 are to be ignored by game's damage calculations
		// usually created articially to make stuff break.
		collision.partid[0] = -2;
		collision.idmat[1] = surfaceIdx;
		collision.idmat[0] = invId;
		collision.n = normal;
		collision.pt = pt;
		// 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
		Vec3	v = dir;
		float speed = cry_sqrtf(4000.0f / (80.0f * 0.5f)); // 80.0f is the mass of the player
		// [marco] Check if an object. Should take lots of time to break stuff if not in nanosuit strength mode;
		// and still creates a very low impulse for stuff that might depend on receiving an impulse.
		IRenderNode *pBrush = (IRenderNode *)pCollider->GetForeignData(PHYS_FOREIGN_ID_STATIC);
		collision.vSelf = (v.normalized() * speed * m_meleeScale);
		collision.v = Vec3(0, 0, 0);
		collision.pCollider = pCollider;
		IEntity *pOwner = m_pWeapon->GetOwner();

		if (pOwner && pOwner->GetCharacter(0) && pOwner->GetCharacter(0)->GetISkeletonPose()->GetCharacterPhysics())
		{
			if (ISkeletonPose *pSkeletonPose = pOwner->GetCharacter(0)->GetISkeletonPose())
			{
				if (pSkeletonPose && pSkeletonPose->GetCharacterPhysics())
				{
					pSkeletonPose->GetCharacterPhysics()->Action(&collision);
				}
			}
		}
	}
}
//------------------------------------------------------------------------
void CGameRules::CullEntitiesInExplosion(const ExplosionInfo &explosionInfo)
{
	if (!g_pGameCVars->g_ec_enable || explosionInfo.damage <= 0.1f)
		return;

	IPhysicalEntity **pents;
	float radiusScale = g_pGameCVars->g_ec_radiusScale;
	float minVolume = g_pGameCVars->g_ec_volume;
	float minExtent = g_pGameCVars->g_ec_extent;
	int   removeThreshold = max(1, g_pGameCVars->g_ec_removeThreshold);

	IActor *pClientActor = g_pGame->GetIGameFramework()->GetClientActor();
	Vec3 radiusVec(radiusScale * explosionInfo.physRadius);
	int i = gEnv->pPhysicalWorld->GetEntitiesInBox(explosionInfo.pos-radiusVec,explosionInfo.pos+radiusVec,pents, ent_rigid|ent_sleeping_rigid);
	int removedCount = 0;

	static IEntityClass* s_pInteractiveEntityClass = gEnv->pEntitySystem->GetClassRegistry()->FindClass("InteractiveEntity");
	static IEntityClass* s_pDeadBodyClass = gEnv->pEntitySystem->GetClassRegistry()->FindClass("DeadBody");

	if (i > removeThreshold)
	{
		int entitiesToRemove = i - removeThreshold;
		for(--i;i>=0;i--)
		{
			if(removedCount>=entitiesToRemove)
				break;

			IEntity * pEntity = (IEntity*) pents[i]->GetForeignData(PHYS_FOREIGN_ID_ENTITY);
			if (pEntity)
			{
				// don't remove if entity is held by the player
				if (pClientActor && pEntity->GetId()==pClientActor->GetGrabbedEntityId())
					continue;

				// don't remove items/pickups
				if (IItem* pItem = g_pGame->GetIGameFramework()->GetIItemSystem()->GetItem(pEntity->GetId()))
				{
					continue;
				}
				// don't remove enemies/ragdolls
				if (IActor* pActor = g_pGame->GetIGameFramework()->GetIActorSystem()->GetActor(pEntity->GetId()))
				{
					continue;
				}

				// if there is a flowgraph attached, never remove!
				if (pEntity->GetProxy(ENTITY_PROXY_FLOWGRAPH) != 0)
					continue;

				IEntityClass* pClass = pEntity->GetClass();
				if (pClass == s_pInteractiveEntityClass || pClass == s_pDeadBodyClass)
					continue;

				// get bounding box
				if (IEntityPhysicalProxy* pPhysProxy = (IEntityPhysicalProxy*)pEntity->GetProxy(ENTITY_PROXY_PHYSICS))
				{
					AABB aabb;
					pPhysProxy->GetWorldBounds(aabb);

					// don't remove objects which are larger than a predefined minimum volume
					if (aabb.GetVolume() > minVolume)
						continue;

					// don't remove objects which are larger than a predefined minimum volume
					Vec3 size(aabb.GetSize().abs());
					if (size.x > minExtent || size.y > minExtent || size.z > minExtent)
						continue;
				}

				// marcok: somehow editor doesn't handle deleting non-dynamic entities very well
				// but craig says, hiding is not synchronized for DX11 breakable MP, so we remove entities only when playing pure game
				// alexl: in SinglePlayer, we also currently only hide the object because it could be part of flowgraph logic
				//        which would break if Entity was removed and could not propagate events anymore
				if (gEnv->bMultiplayer == false || gEnv->IsEditor())
				{
					pEntity->Hide(true);
				}
				else
				{
					gEnv->pEntitySystem->RemoveEntity(pEntity->GetId());
				}
				removedCount++;
			}
		}
	}
}
Beispiel #30
0
void CGameStats::ProcessPlayerStat(IEntity* pEntity, const GameplayEvent &event)
{
	if(CCryActionCVars::Get().g_statisticsMode != 1)
		return;

	SGetTime time(m_roundStart);

	const int e_id = pEntity->GetId(); 
	PlayerStatsMap::iterator it = m_playerMap.find(e_id);
	if(it == m_playerMap.end())
		return;
	SPlayerStats& plr = *(it->second.stats.back());
	if(gEnv->bServer)
	{
		switch(event.event)
		{
		case eGE_Kill:
			plr.m_kills++;
			{
				EntityId* params = (EntityId*)event.extra;
				IEntity *weapon = gEnv->pEntitySystem->GetEntity(params[0]);
				string wname = event.description?event.description:"";
				if(weapon)
					wname = weapon->GetClass()->GetName();
				plr.PlayerEvent(time, "kill", wname, params[1], pEntity->GetWorldPos());
			}
			break;
		case eGE_Death:
			plr.m_deaths++;
			plr.m_inVehicle = false;
			plr.PlayerEvent(time, "death", "", 0, pEntity->GetWorldPos());
			break;
		case eGE_Revive:
			plr.m_revives++;
			plr.PlayerEvent(time, "spawn", "", int(event.value), pEntity->GetWorldPos());
			CreateNewLifeStats(e_id);
			break;
		case eGE_WeaponMelee:
			{
				plr.m_melee++;
				plr.PlayerEvent(time, "weapon_melee" );
			}
			break;
		case eGE_EnteredVehicle:
			plr.m_inVehicle = true;
			break;
		case eGE_LeftVehicle:
			plr.m_inVehicle = false;
			break;
		}
	}

	static string vehicle_name;

	switch(event.event)
	{
	case eGE_WeaponShot:
		if(!plr.m_inVehicle)
		{
			if(event.description == NULL)
				break;

			if(strstr(event.description, "bullet")!=0 || strcmp(event.description,"shotgunshell")==0 || strcmp(event.description,"alienmount_acmo")==0)//only counting these
				plr.m_shots += int(event.value);
		}
		plr.WeaponShot(int(event.value), time, pEntity->GetWorldPos());
		break;
	/*case eGE_Damage:
		{
			float dmgVal = event.value;
			const char* weaponName = event.description;
			plr.WeaponDamage(weaponName, dmgVal);

		}break;*/
	case eGE_WeaponHit:
		if(!plr.m_inVehicle)
		{
			float dmgVal = event.value;
			const char* weaponName = event.description;
			uint32 targetId = (uint32)reinterpret_cast<TRUNCATE_PTR>(event.extra);
			const Vec3 fakePos(0,0,0);
			const char* bodyPart = event.strData;
			
			plr.WeaponHit(weaponName);
			plr.WeaponDamage(weaponName, dmgVal);
			plr.PlayerEvent(time, "hit", weaponName, targetId, fakePos, dmgVal, bodyPart );
			
		}	
		break;
	case eGE_Kill:
		{
			plr.ClientKill(event.description, time);			
			
			EntityId* params = (EntityId*)event.extra;
			IEntity* pWeapon = 0;
			if (params)
				gEnv->pEntitySystem->GetEntity(params[0]);
			plr.WeaponKill(pWeapon?pWeapon->GetClass()->GetName():0);
		}
		break;
	case eGE_Death:
		plr.ClientDeath(time);
		break;
	case eGE_Revive:
		plr.ClientRevive(time);
		break;
	case eGE_SuitModeChanged:
		plr.SelectSuitMode(int(event.value), time);
		break;
	case eGE_EnteredVehicle:
		{
			if( IVehicle* pV = CCryAction::GetCryAction()->GetIVehicleSystem()->GetVehicle((EntityId)(TRUNCATE_PTR)event.extra))
			{
				vehicle_name.Format("%s_%s", pV->GetEntity()->GetClass()->GetName(), pV->GetModification());
				plr.EnterVehicle(vehicle_name, time);
			}
		}
		break;
	case eGE_LeftVehicle:
		{
			if( IVehicle* pV = CCryAction::GetCryAction()->GetIVehicleSystem()->GetVehicle((EntityId)(TRUNCATE_PTR)event.extra))
			{
				vehicle_name.Format("%s_%s", pV->GetEntity()->GetClass()->GetName(), pV->GetModification());
				plr.LeaveVehicle(vehicle_name, time);
			}
		}
		break;
	case eGE_ItemSelected:
		{
			if( IEntity* pI = gEnv->pEntitySystem->GetEntity(EntityId((TRUNCATE_PTR)event.extra)) )
				plr.SelectWeapon(pI->GetClass()->GetName(), time);
		}			
		break;
	case eGE_WeaponReload:
		{
			plr.Reload(time, pEntity->GetWorldPos());
			break;
		}	
	case eGE_Spectator:
		plr.Spectator(event.value != 0, time);
		break;
	case eGE_WeaponFireModeChanged:
		{
			plr.FiremodeChanged(time, pEntity->GetWorldPos(), event.description);
			break;
		}
	case eGE_ZoomedIn:
		{
			plr.ZoomIn(time, pEntity->GetWorldPos());
			break;
		}
	case eGE_ZoomedOut:
		{
			plr.ZoomOut(time, pEntity->GetWorldPos());
			break;
		}
	}
}