//------------------------------------------------------------------------ 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); }
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; }
//------------------------------------------------------------------------ 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; }
//------------------------------------------------------------------------ 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 ""; }
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()); }
//----------------------------------------------------------------------- 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; }
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; }
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; }
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 ); } }
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:""); }
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(); }
// 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++; } } } }
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; } } }