void CUIHUD3D::SpawnHudEntities() { RemoveHudEntities(); if (gEnv->IsEditor() && gEnv->IsEditing()) return; const char* hudprefab = NULL; IGameRules* pGameRules = gEnv->pGame->GetIGameFramework()->GetIGameRulesSystem()->GetCurrentGameRules(); if (pGameRules) { IScriptTable* pTable = pGameRules->GetEntity()->GetScriptTable(); if (pTable) { if (!pTable->GetValue("hud_prefab", hudprefab)) hudprefab = NULL; } } hudprefab = hudprefab ? hudprefab : HUD3D_PREFAB_LIB; XmlNodeRef node = gEnv->pSystem->LoadXmlFromFile(hudprefab); if (node) { // get the prefab with the name defined in HUD3D_PREFAB_NAME XmlNodeRef prefab = NULL; for (int i = 0; i < node->getChildCount(); ++i) { const char* name = node->getChild(i)->getAttr("Name"); if (name && strcmp(name, HUD3D_PREFAB_NAME) == 0) { prefab = node->getChild(i); prefab = prefab ? prefab->findChild("Objects") : XmlNodeRef(); break; } } if (prefab) { // get the PIVOT entity and collect childs XmlNodeRef pivotNode = NULL; std::vector<XmlNodeRef> childs; const int count = prefab->getChildCount(); childs.reserve(count-1); for (int i = 0; i < count; ++i) { const char* name = prefab->getChild(i)->getAttr("Name"); if (strcmp("PIVOT", name) == 0) { assert(pivotNode == NULL); pivotNode = prefab->getChild(i); } else { childs.push_back(prefab->getChild(i)); } } if (pivotNode) { // spawn pivot entity IEntityClass* pEntClass = gEnv->pEntitySystem->GetClassRegistry()->FindClass( pivotNode->getAttr("EntityClass") ); if (pEntClass) { SEntitySpawnParams params; params.nFlags = ENTITY_FLAG_CLIENT_ONLY; params.pClass = pEntClass; m_pHUDRootEntity = gEnv->pEntitySystem->SpawnEntity(params); } if (!m_pHUDRootEntity) return; m_HUDRootEntityId = m_pHUDRootEntity->GetId(); // spawn the childs and link to the pivot enity for (std::vector<XmlNodeRef>::iterator it = childs.begin(); it != childs.end(); ++it) { XmlNodeRef child = *it; pEntClass = gEnv->pEntitySystem->GetClassRegistry()->FindClass( child->getAttr("EntityClass") ); if (pEntClass) { const char* material = child->getAttr("Material"); Vec3 pos; Vec3 scale; Quat rot; child->getAttr("Pos", pos); child->getAttr("Rotate", rot); child->getAttr("Scale", scale); SEntitySpawnParams params; params.nFlags = ENTITY_FLAG_CLIENT_ONLY; params.pClass = pEntClass; params.vPosition = pos; params.qRotation = rot; params.vScale = scale; IEntity* pEntity = gEnv->pEntitySystem->SpawnEntity(params); if (pEntity) { IScriptTable* pScriptTable = pEntity->GetScriptTable(); if (pScriptTable) { SmartScriptTable probs; pScriptTable->GetValue("Properties", probs); XmlNodeRef properties = child->findChild("Properties"); if (probs && properties) { for (int k = 0; k < properties->getNumAttributes(); ++k) { const char* sKey; const char* sVal; properties->getAttributeByIndex(k, &sKey, &sVal); probs->SetValue(sKey, sVal); } } Script::CallMethod(pScriptTable,"OnPropertyChange"); } if (material) { IMaterial* pMat = gEnv->p3DEngine->GetMaterialManager()->LoadMaterial(material); if (pMat) pEntity->SetMaterial(pMat); } m_pHUDRootEntity->AttachChild(pEntity); m_HUDEnties.push_back( pEntity->GetId() ); } } } } } } OnVisCVarChange( NULL ); }
// one-time validation of entity tables bool CScriptRMI::ValidateDispatchTable( const char * clazz, SmartScriptTable dispatch, SmartScriptTable methods, bool bServerTable ) { CryAutoCriticalSection lkDispatch(m_dispatchMutex); std::map<string,size_t>::iterator iterN = m_entityClassToEntityTypeID.lower_bound(clazz); if (iterN == m_entityClassToEntityTypeID.end() || iterN->first != clazz) { iterN = m_entityClassToEntityTypeID.insert( iterN, std::make_pair(clazz, m_entityClassToEntityTypeID.size()) ); CRY_ASSERT(iterN->second == m_dispatch.size()); m_dispatch.push_back(SDispatch()); } SDispatch& dispatchTblCont = m_dispatch[iterN->second]; SFunctionDispatchTable& dispatchTbl = bServerTable ? dispatchTblCont.server : dispatchTblCont.client; IScriptTable::Iterator iter = dispatch->BeginIteration(); while (dispatch->MoveNext(iter)) { if (iter.sKey) { if (iter.sKey[0] == '_' && iter.sKey[1] == '_') continue; ScriptVarType type = methods->GetValueType( iter.sKey ); if (type != svtFunction) { GameWarning( "In class %s: function %s is exposed but not defined", clazz, iter.sKey ); dispatch->EndIteration(iter); return false; } } else { int id = iter.nKey; CRY_ASSERT(id>0); id--; if (id >= dispatchTbl.size()) dispatchTbl.resize(id+1); SFunctionDispatch& dt = dispatchTbl[id]; if (iter.value.GetVarType() != svtString) { GameWarning("Expected a string in dispatch table, got type %d", iter.value.GetVarType()); dispatch->EndIteration(iter); return false; } const char * funcData = iter.value.str; const char * colon = strchr(funcData, ':'); if (colon == NULL) { dispatch->EndIteration(iter); return false; } if (colon - funcData > MaxSynchedPropertyNameLength) { dispatch->EndIteration(iter); return false; } memcpy( dt.name, funcData, colon-funcData ); dt.name[colon-funcData] = 0; strcpy(dt.format, colon + 1); } } dispatch->EndIteration(iter); dispatch->SetValue( VALIDATED_FIELD, true ); if (bServerTable) { dispatchTblCont.m_serverDispatchScriptTable = dispatch; } else { dispatchTblCont.m_clientDispatchScriptTable = dispatch; } return true; }
// setup the meta-table for synched variables bool CScriptRMI::BuildSynchTable( SmartScriptTable vars, SmartScriptTable cls, const char * name ) { IScriptSystem * pSS = vars->GetScriptSystem(); SmartScriptTable synched( pSS ); SmartScriptTable defaultValues( pSS ); // TODO: Improve IScriptTable::SUserFunctionDesc fd; fd.pFunctor = functor_ret( SynchedNewIndexFunction ); fd.sFunctionName = "__newindex"; fd.sGlobalName = "<net-dispatch>"; fd.sFunctionParams = "(...)"; synched->AddFunction( fd ); std::vector<SSynchedPropertyInfo> properties; IScriptTable::Iterator iter = vars->BeginIteration(); while (vars->MoveNext(iter)) { if (iter.sKey) { int type; if (!vars->GetValue(iter.sKey, type)) { vars->EndIteration(iter); pSS->RaiseError( "No type for %s", iter.sKey ); return false; } size_t len = strlen(iter.sKey); if (len > MaxSynchedPropertyNameLength) { vars->EndIteration(iter); pSS->RaiseError( "Synched var name '%s' too long (max is %d)", iter.sKey, (int)MaxSynchedPropertyNameLength ); return false; } SSynchedPropertyInfo info; strcpy( info.name, iter.sKey ); info.type = (EScriptSerializeType) type; properties.push_back( info ); if (info.type == eSST_String) defaultValues->SetValue( iter.sKey, "" ); else defaultValues->SetValue( iter.sKey, 0 ); } } vars->EndIteration( iter ); if (properties.empty()) return true; fd.pFunctor = NULL; fd.pUserDataFunc = SerializeFunction; fd.nDataSize = sizeof(SSynchedPropertyInfo) * properties.size(); fd.pDataBuffer = &properties[0]; fd.sFunctionName = SERIALIZE_FUNCTION; fd.sFunctionParams = "(...)"; fd.sGlobalName = "<net-dispatch>"; synched->AddFunction( fd ); cls->SetValue( SERVER_SYNCHED_FIELD, synched ); cls->SetValue( "synched", defaultValues ); return true; }
// build a script dispatch table - this table is the metatable for all // dispatch proxy tables used (onClient, allClients, otherClients) bool CScriptRMI::BuildDispatchTable( SmartScriptTable methods, SmartScriptTable classMethodTable, SmartScriptTable cls, const char * name ) { IScriptSystem * pSS = methods->GetScriptSystem(); SmartScriptTable dispatch( pSS ); uint8 funcID = 0; IScriptTable::SUserFunctionDesc fd; SFunctionInfo info; IScriptTable::Iterator iter = methods->BeginIteration(); while (methods->MoveNext(iter)) { if (iter.sKey) { const char * function = iter.sKey; if (strlen(function)>=2 && function[0] == '_' && function[1] == '_') { methods->EndIteration(iter); pSS->RaiseError( "In Net.Expose: can't expose functions beginning with '__' (function was %s)", function ); return false; } SmartScriptTable specTable; if (!methods->GetValue(function, specTable)) { methods->EndIteration(iter); pSS->RaiseError( "In Net.Expose: function %s entry is not a table (in %s)", function, name ); return false; } // fetch format int count = specTable->Count(); if (count < 1) { methods->EndIteration(iter); pSS->RaiseError( "In Net.Expose: function %s entry is an empty table (in %s)", function, name ); return false; } else if (count-1 > MaxRMIParameters) { methods->EndIteration(iter); pSS->RaiseError( "In Net.Expose: function %s has too many parameters (%d) (in %s)", function, count-1, name ); return false; } int tempReliability; if (!specTable->GetAt(1, tempReliability) || tempReliability < 0 || tempReliability >= eNRT_NumReliabilityTypes) { methods->EndIteration(iter); pSS->RaiseError( "In Net.Expose: function %s has invalid reliability type %d (in %s)", function, tempReliability, name ); return false; } ENetReliabilityType reliability = (ENetReliabilityType) tempReliability; if (!specTable->GetAt(2, tempReliability) || tempReliability < 0 || tempReliability >= eRAT_NumAttachmentTypes) { methods->EndIteration(iter); pSS->RaiseError( "In Net.Expose: function %s has invalid attachment type %d (in %s)", function, tempReliability, name ); } ERMIAttachmentType attachment = (ERMIAttachmentType) tempReliability; string format; format.reserve(count-1); for (int i=3; i<=count; i++) { int type = 666; if (!specTable->GetAt( i, type ) || type<-128 || type>127) { methods->EndIteration(iter); pSS->RaiseError( "In Net.Expose: function %s has invalid serialization policy %d at %d (in %s)", function, type, i, name ); return false; } format.push_back( (char) type ); } CRY_ASSERT( format.length() <= MaxRMIParameters ); strcpy( info.format, format.c_str() ); info.funcID = funcID; info.reliability = reliability; info.attachment = attachment; fd.pUserDataFunc = ProxyFunction; fd.sFunctionName = function; fd.nDataSize = sizeof(SFunctionInfo); fd.pDataBuffer = &info; fd.sGlobalName = "<net-dispatch>"; fd.sFunctionParams = "(...)"; dispatch->AddFunction( fd ); string lookupData = function; lookupData += ":"; lookupData += format; dispatch->SetAt( funcID+1, lookupData.c_str() ); funcID ++; if (funcID == 0) { funcID--; methods->EndIteration(iter); pSS->RaiseError( "Too many functions... max is %d", funcID ); return false; } } else { GameWarning( "In Net.Expose: non-string key ignored" ); } } methods->EndIteration(iter); dispatch->SetValue( VALIDATED_FIELD, false ); cls->SetValue( name, dispatch ); return true; }
void CFlashLight::EnableFogVolume(CWeapon* pWeapon, int slot, bool enable) { if (!g_pGameCVars->i_flashlight_has_fog_volume) { return; } if (!m_sharedparams->pFlashLightParams) { return; } IEntity* pFogVolume = 0; if (m_fogVolume == 0) { const Vec3 size = Vec3( m_sharedparams->pFlashLightParams->fogVolumeRadius, m_sharedparams->pFlashLightParams->fogVolumeSize, m_sharedparams->pFlashLightParams->fogVolumeRadius); SEntitySpawnParams fogVolumeParams; fogVolumeParams.pClass = gEnv->pEntitySystem->GetClassRegistry()->FindClass("FogVolume"); fogVolumeParams.nFlags = ENTITY_FLAG_NO_SAVE; fogVolumeParams.vPosition = Vec3(ZERO); pFogVolume = gEnv->pEntitySystem->SpawnEntity(fogVolumeParams); if (!pFogVolume) { return; } m_fogVolume = pFogVolume->GetId(); SmartScriptTable pProperties; pFogVolume->GetScriptTable()->GetValue("Properties", pProperties); if (pProperties) { pProperties->SetValue("color_Color", m_sharedparams->pFlashLightParams->fogVolumeColor); pProperties->SetValue("GlobalDensity", m_sharedparams->pFlashLightParams->fogVolumeDensity); pProperties->SetValue("Size", size); pProperties->SetValue("FallOffScale", 0.0f); } EntityScripts::CallScriptFunction(pFogVolume, pFogVolume->GetScriptTable(), "OnPropertyChange"); pFogVolume->Activate(true); } else { pFogVolume = gEnv->pEntitySystem->GetEntity(m_fogVolume); } if (!pFogVolume) { return; } const char* attachHelper = "lightFog_term"; const float distance = m_sharedparams->pFlashLightParams->fogVolumeSize * 0.5f; ICharacterInstance* pCharacter = pWeapon->GetEntity()->GetCharacter(slot); if (enable && pCharacter) { IAttachmentManager* pAttachmentManager = pCharacter->GetIAttachmentManager(); IAttachment* pAttachment = pAttachmentManager->GetInterfaceByName(attachHelper); if (pAttachment) { CEntityAttachment* pEntityAttachment = new CEntityAttachment(); pEntityAttachment->SetEntityId(m_fogVolume); pAttachment->AddBinding(pEntityAttachment); QuatT relative(IDENTITY); relative.t.y = distance; pAttachment->SetAttRelativeDefault(relative); } } pFogVolume->Hide(!enable); }
////////////////////////////////////////////////////////////////////////// // Set event targets from the XmlNode exported by Editor. void CScriptProxy::SetEventTargets( XmlNodeRef &eventTargetsNode ) { std::set<string> sourceEvents; std::vector<SEntityEventTarget> eventTargets; IScriptSystem* pSS = GetIScriptSystem(); for (int i = 0; i < eventTargetsNode->getChildCount(); i++) { XmlNodeRef eventNode = eventTargetsNode->getChild(i); SEntityEventTarget et; et.event = eventNode->getAttr("Event"); if (!eventNode->getAttr("Target", et.target)) et.target = 0; // failed reading... et.sourceEvent = eventNode->getAttr("SourceEvent"); if (et.event.empty() || !et.target || et.sourceEvent.empty()) continue; eventTargets.push_back(et); sourceEvents.insert(et.sourceEvent); } if (eventTargets.empty()) return; SmartScriptTable pEventsTable; if (!m_pThis->GetValue( "Events",pEventsTable )) { pEventsTable = pSS->CreateTable(); // assign events table to the entity self script table. m_pThis->SetValue( "Events",pEventsTable ); } for (std::set<string>::iterator it = sourceEvents.begin(); it != sourceEvents.end(); ++it) { SmartScriptTable pTrgEvents(pSS); string sourceEvent = *it; pEventsTable->SetValue( sourceEvent.c_str(),pTrgEvents ); // Put target events to table. int trgEventIndex = 1; for (size_t i = 0; i < eventTargets.size(); i++) { SEntityEventTarget &et = eventTargets[i]; if (et.sourceEvent == sourceEvent) { SmartScriptTable pTrgEvent(pSS); pTrgEvents->SetAt( trgEventIndex,pTrgEvent ); trgEventIndex++; ScriptHandle hdl; hdl.n = et.target; pTrgEvent->SetAt( 1, hdl); pTrgEvent->SetAt( 2,et.event.c_str()); } } } }