void CLightningArc::TriggerSpark() { const char* targetName = "Target"; IEntity* pEntity = GetEntity(); if (pEntity->GetMaterial() == 0) { GameWarning("Lightning arc '%s' has no Material, no sparks will trigger", pEntity->GetName()); return; } IEntityLink* pLinks = pEntity->GetEntityLinks(); int numLinks = 0; for (IEntityLink* link = pLinks; link; link = link->next) { if (strcmp(link->name, targetName) == 0) ++numLinks; } if (numLinks == 0) { GameWarning("Lightning arc '%s' has no Targets, no sparks will trigger", pEntity->GetName()); return; } int nextSpark = Random(numLinks); IEntityLink* pNextSparkLink = pLinks; for (; nextSpark && pNextSparkLink; pNextSparkLink = pNextSparkLink->next) { if (strcmp(pNextSparkLink->name, targetName) == 0) --nextSpark; } CLightningGameEffect::TIndex id = g_pGame->GetLightningGameEffect()->TriggerSpark( m_lightningPreset, pEntity->GetMaterial(), CLightningGameEffect::STarget(GetEntityId()), CLightningGameEffect::STarget(pNextSparkLink->entityId)); float strikeTime = g_pGame->GetLightningGameEffect()->GetSparkRemainingTime(id); IScriptTable* pTargetScriptTable = 0; IEntity* pTarget = gEnv->pEntitySystem->GetEntity(pNextSparkLink->entityId); if (pTarget) pTargetScriptTable = pTarget->GetScriptTable(); EntityScripts::CallScriptFunction(pEntity, pEntity->GetScriptTable(), "OnStrike", strikeTime, pTargetScriptTable); }
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 } }