bool CBattleDust::CheckForMerging(CBattleEvent* pEvent) { FUNCTION_PROFILER(GetISystem(), PROFILE_GAME); if(!g_pGameCVars->g_battleDust_enable) return false; if(!pEvent) return false; if(!gEnv->bServer) return false; // check if area can merge with nearby areas for(std::list<EntityId>::iterator it = m_eventIdList.begin(); it != m_eventIdList.end(); ++it) { EntityId areaId = (*it); CBattleEvent *pBattleArea = FindEvent(areaId); if(!pBattleArea) continue; if(CheckIntersection(pEvent, pBattleArea->m_worldPos, pBattleArea->m_radius) && pBattleArea->m_radius > 0 && (pBattleArea != pEvent) && pBattleArea->GetEntity()) { MergeAreas(pBattleArea, pEvent->m_worldPos, pEvent->m_radius); return true; } } return false; }
void CBattleDust::RecordEvent(EBattleDustEventType event, Vec3 worldPos, const IEntityClass* pClass) { FUNCTION_PROFILER(GetISystem(), PROFILE_GAME); if(!g_pGameCVars->g_battleDust_enable) return; if(!gEnv->bServer) return; // this typically means the xml file failed to load. Turn off the dust. if(m_maxParticleCount == 0) return; SBattleEventParameter param; if(!GetEventParams(event, pClass, param)) return; if(param.m_power == 0 || worldPos.IsEquivalent(Vec3(0,0,0))) return; if(m_pBattleEventClass == NULL) m_pBattleEventClass = gEnv->pEntitySystem->GetClassRegistry()->FindClass( "BattleEvent" ); // first check if we need a new event bool newEvent = true; for(std::list<EntityId>::iterator it = m_eventIdList.begin(); it != m_eventIdList.end(); ++it) { EntityId areaId = (*it); CBattleEvent *pBattleArea = FindEvent(areaId); if(pBattleArea && CheckIntersection(pBattleArea, worldPos, param.m_power)) { // don't need a new event as this one is within an existing one. Just merge them. MergeAreas(pBattleArea, worldPos, param.m_power); pBattleArea->m_lifeRemaining += param.m_lifetime; pBattleArea->m_lifetime = pBattleArea->m_lifeRemaining; pBattleArea->m_lifetime = CLAMP(pBattleArea->m_lifetime, 0.0f, m_maxLifetime); pBattleArea->m_lifeRemaining = CLAMP(pBattleArea->m_lifeRemaining, 0.0f, m_maxLifetime); newEvent = false; break; } } if(newEvent) { IEntitySystem * pEntitySystem = gEnv->pEntitySystem; SEntitySpawnParams esp; esp.id = 0; esp.nFlags = 0; esp.pClass = m_pBattleEventClass; if (!esp.pClass) return; esp.pUserData = NULL; esp.sName = "BattleDust"; esp.vPosition = worldPos; // when CBattleEvent is created it will add itself to the list IEntity * pEntity = pEntitySystem->SpawnEntity( esp ); if(pEntity) { // find the just-added entity in the list, and set it's properties IGameObject* pGO = g_pGame->GetIGameFramework()->GetGameObject(pEntity->GetId()); if(pGO) { CBattleEvent* pNewEvent = static_cast<CBattleEvent*>(pGO->QueryExtension("BattleEvent")); if(pNewEvent) { pNewEvent->m_radius = param.m_power; pNewEvent->m_peakRadius = param.m_power; pNewEvent->m_lifetime = param.m_lifetime; pNewEvent->m_lifeRemaining = param.m_lifetime; pNewEvent->m_worldPos = worldPos; pNewEvent->m_lifetime = CLAMP(pNewEvent->m_lifetime, 0.0f, m_maxLifetime); pNewEvent->m_lifeRemaining = CLAMP(pNewEvent->m_lifeRemaining, 0.0f, m_maxLifetime); pGO->ChangedNetworkState(CBattleEvent::PROPERTIES_ASPECT); } } } } }
bool MergeAreasGenerator::Import(const TypeConfigRef& typeConfig, const ImportParameter& parameter, Progress& progress) { TypeInfoSet mergeTypes; FileScanner scanner; FileWriter writer; uint32_t areasWritten=0; for (const auto& type : typeConfig->GetTypes()) { if (type->CanBeArea() && type->GetMergeAreas()) { mergeTypes.Set(type); } } std::unordered_set<Id> nodeUseMap; try { scanner.Open(AppendFileToDir(parameter.GetDestinationDirectory(), MergeAreaDataGenerator::AREAS_TMP), FileScanner::Sequential, parameter.GetRawWayDataMemoryMaped()); if (!ScanAreaNodeIds(progress, *typeConfig, scanner, mergeTypes, nodeUseMap)) { return false; } uint32_t nodeCount=nodeUseMap.size(); progress.Info("Found "+NumberToString(nodeCount)+" nodes as possible connection points for areas"); /* ------ */ writer.Open(AppendFileToDir(parameter.GetDestinationDirectory(), AREAS2_TMP)); writer.Write(areasWritten); while (true) { TypeInfoSet loadedTypes; std::vector<AreaMergeData> mergeJob(typeConfig->GetTypeCount()); // // Load type data // progress.SetAction("Collecting area data by type"); if (!GetAreas(parameter, progress, *typeConfig, mergeTypes, loadedTypes, nodeUseMap, scanner, writer, mergeJob, areasWritten)) { return false; } // Merge progress.SetAction("Merging areas"); for (const auto& type : loadedTypes) { if (!mergeJob[type->GetIndex()].areas.empty()) { progress.Info("Merging areas of type "+type->GetName()); MergeAreas(progress, nodeUseMap, mergeJob[type->GetIndex()]); progress.Info("Reduced areas of '"+type->GetName()+"' from "+NumberToString(mergeJob[type->GetIndex()].areaCount)+" to "+NumberToString(mergeJob[type->GetIndex()].areaCount-mergeJob[type->GetIndex()].mergedAway.size())); mergeJob[type->GetIndex()].areas.clear(); } } // Store back merge result if (!loadedTypes.Empty()) { if (!WriteMergeResult(progress, *typeConfig, scanner, writer, loadedTypes, mergeJob, areasWritten)) { return false; } mergeTypes.Remove(loadedTypes); } if (mergeTypes.Empty()) { break; } } scanner.Close(); writer.GotoBegin(); writer.Write(areasWritten); writer.Close(); } catch (IOException& e) { progress.Error(e.GetDescription()); scanner.CloseFailsafe(); writer.CloseFailsafe(); return false; } return true; }