void CAntiCheatManager::DumpCheatRecords() { XmlNodeRef records = GetISystem()->CreateXmlNode("CheatRecords"); std::map<CryUserID, SCheatRecord>::iterator itCheatRecord; for (itCheatRecord = m_cheatRecords.begin(); itCheatRecord != m_cheatRecords.end(); ++itCheatRecord) { XmlNodeRef playerRecord = records->newChild("Player"); const char* szGuid = itCheatRecord->first.get()->GetGUIDAsString(); CAntiCheatManager::Xml_SetGuid(playerRecord, szGuid); for (int i=0; i<eCT_Num; ++i) { SCheatInfraction &infraction = itCheatRecord->second.infractions[i]; if (infraction.numInfractions > 0 || infraction.cumulativeSeverity > 0.f) { XmlNodeRef infractionXml = playerRecord->newChild("Infraction"); CAntiCheatManager::Xml_SetCheatType(infractionXml, i); infractionXml->setAttr("incidences", infraction.numInfractions); infractionXml->setAttr("cumulative_severity", infraction.cumulativeSeverity); } } } CheatLogInternalXml(records); }
bool CFlowGraphModule::SaveModuleXml(XmlNodeRef saveTo) { if (!m_pRootGraph || !saveTo) return false; saveTo->setAttr("isModule", true); saveTo->setAttr("moduleName", m_name); // NB: don't save our graph here, just the module ports (graph is saved // by the calling code) if (m_modulePorts.size() > 0) { XmlNodeRef inputs = saveTo->newChild("ModuleInputsOutputs"); for (size_t i = 0; i < m_modulePorts.size(); ++i) { XmlNodeRef ioChild = inputs->newChild("Port"); ioChild->setAttr("Name", m_modulePorts[i].name); ioChild->setAttr("Type", m_modulePorts[i].type); ioChild->setAttr("Input", m_modulePorts[i].input); } } return true; }
void CClipVolumeProxy::SerializeXML(XmlNodeRef &entityNodeXML, bool loading) { if(loading) { LOADING_TIME_PROFILE_SECTION; if(XmlNodeRef pVolumeNode = entityNodeXML->findChild( "ClipVolume" )) { const char* szFileName = NULL; if(pVolumeNode->getAttr("GeometryFileName",&szFileName)) { // replace %level% by level path char szFilePath[_MAX_PATH]; const int nAliasNameLen = sizeof("%level%")-1; cry_strcpy(szFilePath, gEnv->p3DEngine->GetLevelFilePath(szFileName+nAliasNameLen)); if(m_pEntity && LoadFromFile(szFilePath)) gEnv->p3DEngine->UpdateClipVolume(m_pClipVolume, m_pRenderMesh, m_pBspTree, m_pEntity->GetWorldTM(), !m_pEntity->IsHidden(), m_pEntity->GetName()); } } } else { XmlNodeRef volumeNode = entityNodeXML->newChild( "ClipVolume" ); volumeNode->setAttr( "GeometryFileName", m_GeometryFileName ); } }
void CWorldState::SetString(const char * entityName, char * valueName , string value) { // CryLog("CWorldState::SetString()"); if(worldStateXml) { XmlNodeRef entityNode = worldStateXml->findChild(entityName); if(!entityNode) { CreateChild(entityName); entityNode = worldStateXml->findChild(entityName); } const uint32 Count = entityNode->getChildCount(); for (uint32 Index = 0; Index < Count; ++Index) { XmlNodeRef child = entityNode->getChild(Index); if(strcmp(child->getTag(),valueName)==0) { child->setAttr("value",value); worldStateXml->saveToFile(szSaveFile); return; } } //CryLog("CWorldState::CreateString()"); XmlNodeRef child = entityNode->newChild(valueName); child->setAttr("value",value); worldStateXml->saveToFile(szSaveFile); } else return; }
void CAntiCheatManager::PlayerVotedOff( EntityId playerId, const TVoteDataList& voteData, float fSecondsToBanFor ) { //verify it is from the main thread. This cannot be called from other threads as it bypasses the queue if ( IActor * pTargetActor = g_pGame->GetIGameFramework()->GetIActorSystem()->GetActor(playerId)) { uint16 targetActorChannel = pTargetActor->GetChannelId(); XmlNodeRef playersVoteDataXml; playersVoteDataXml = GetISystem()->CreateXmlNode("VoteData"); for(TVoteDataList::const_iterator iter = voteData.begin(), end = voteData.end(); iter != end; ++iter) { XmlNodeRef playerVoteXml = playersVoteDataXml->newChild("Vote"); if ( IActor * pVotingActor = g_pGame->GetIGameFramework()->GetIActorSystem()->GetActor(iter->voterId) ) { uint16 channelId = pVotingActor->GetChannelId(); if( INetChannel * pNetChannel = g_pGame->GetIGameFramework()->GetNetChannel(channelId) ) { playerVoteXml->setAttr("player_nickname", pNetChannel->GetNickname() ); playerVoteXml->setAttr("vote", iter->bVotedToKick ? "for" : "against"); } } } ProcessFlagActivity( eCT_VoteKicked, targetActorChannel, 0, 0, "Player voted off by their peers", playersVoteDataXml ); } }
void CAntiCheatManager::CheatLogSeverity(XmlNodeRef incidentXml, uint16 channelId, float fTotalSeverity, int numInfractions, float fDeltaSeverity) { XmlNodeRef severityNode = incidentXml->newChild("Severity"); severityNode->setAttr("change", fDeltaSeverity); severityNode->setAttr("total", fTotalSeverity); severityNode->setAttr("num_infractions", numInfractions); }
XmlNodeRef CAntiCheatManager::CheatLogAction(XmlNodeRef incidentNode, ECheatAction eCheatAction, int nConfidence) { XmlNodeRef actionNode = incidentNode->newChild("Action"); CAntiCheatManager::Xml_SetActionType(actionNode, eCheatAction); actionNode->setAttr("confidence", nConfidence); return actionNode; }
//------------------------------------------------------------------------ bool CActionFilter::SerializeXML(const XmlNodeRef& root, bool bLoading) { if (bLoading) { // loading const XmlNodeRef& child = root; if (strcmp(child->getTag(), "actionfilter") != 0) return false; EActionFilterType actionFilterType = eAFT_ActionFail; if (!strcmp(child->getAttr("type"), "actionFail")) actionFilterType = eAFT_ActionFail; if (!strcmp(child->getAttr("type"), "actionPass")) actionFilterType = eAFT_ActionPass; m_type = actionFilterType; int nFilters = child->getChildCount(); for (int f=0; f<nFilters; ++f) { XmlNodeRef filter = child->getChild(f); Filter(CCryName(filter->getAttr("name"))); } } else { // saving XmlNodeRef filterRoot = root->newChild("actionfilter"); filterRoot->setAttr("name", m_name); filterRoot->setAttr("type", m_type == eAFT_ActionPass ? "actionPass" : "actionFail"); filterRoot->setAttr("version", m_pActionMapManager->GetVersion()); TFilterActions::const_iterator iter = m_filterActions.begin(); while (iter != m_filterActions.end()) { XmlNodeRef filterChild = filterRoot->newChild("filter"); filterChild->setAttr("name", iter->c_str()); ++iter; } } return true; }
void CWorldState::CreateChildToEntity(const char * entityName, const char *childName) { if(worldStateXml) { CryLog("CWorldState::CreateChildToEntity()"); XmlNodeRef entityNode = worldStateXml->findChild(entityName); if(!entityNode) return; entityNode->newChild(childName); worldStateXml->saveToFile(szSaveFile); } else return; }
void CAntiCheatManager::DumpPlayerRecords() { XmlNodeRef playerRecords = GetISystem()->CreateXmlNode("PlayerSessionRecords"); CGameRules *pGameRules = g_pGame->GetGameRules(); IGameRulesPlayerStatsModule *pPlayerStatsModule = pGameRules->GetPlayerStatsModule(); for (TPlayerSessionDataMap::iterator itPlayerRecord = m_PlayerSessionData.begin(); itPlayerRecord != m_PlayerSessionData.end(); ++itPlayerRecord) { XmlNodeRef playerSession = playerRecords->newChild("PlayerSession"); playerSession->setAttr("local_session_id", itPlayerRecord->first); SPlayerSessionData& rPlayerSessionData = itPlayerRecord->second; playerSession->setAttr("player_nickname", rPlayerSessionData.playerName); playerSession->setAttr("connect_game_time", rPlayerSessionData.connectTime.GetMilliSecondsAsInt64()); int64 nDisconnectTime = itPlayerRecord->second.disconnectTime.GetMilliSecondsAsInt64(); //nDisconnectTime == 0 means that it has not been set, and so the player did not disconnect and was present at round end if(nDisconnectTime != 0) { playerSession->setAttr("disconnect_game_time", nDisconnectTime); } else { if(IActor * pActor = pGameRules->GetActorByChannelId(itPlayerRecord->first)) { GetPlayerStats(pPlayerStatsModule, pActor->GetEntityId(), rPlayerSessionData); } } playerSession->setAttr("kills", rPlayerSessionData.kills); playerSession->setAttr("deaths", rPlayerSessionData.deaths); playerSession->setAttr("points", rPlayerSessionData.points); } CheatLogInternalXml(playerRecords); m_PlayerSessionData.clear(); }
//------------------------------------------------------------------------ bool CPlayerProfile::SaveAttributes(const XmlNodeRef& root) { if (m_attributesVersion > 0) root->setAttr(VERSION_TAG, m_attributesVersion); const TAttributeMap& defaultMap = GetDefaultAttributeMap(); TAttributeMap::iterator iter = m_attributeMap.begin(); while (iter != m_attributeMap.end()) { string val; iter->second.GetValueWithConversion(val); bool bSaveIt = true; TAttributeMap::const_iterator defaultIter = defaultMap.find(iter->first); if (defaultIter != defaultMap.end()) { string defaultVal; defaultIter->second.GetValueWithConversion(defaultVal); // check if value is different from default bSaveIt = val != defaultVal; } if(m_pManager->IsOnlineOnlyAttribute(iter->first)) { bSaveIt = false; } if (bSaveIt) { // TODO: config. variant saving XmlNodeRef child = root->newChild("Attr"); child->setAttr("name", iter->first); child->setAttr("value", val); } ++iter; } if(m_pManager->HasEnabledOnlineAttributes() && m_pManager->CanProcessOnlineAttributes() && !IsDefault()) { m_pManager->SaveOnlineAttributes(this); } return true; }
XmlNodeRef CAntiCheatManager::CreateIncidentXML(uint16 channelId, TCheatType type, const float *params, int numParams, const char * pDescription) { XmlNodeRef incidentXml = GetISystem()->CreateXmlNode("Incident"); CAntiCheatManager::Xml_SetDisplayName(incidentXml, channelId); CAntiCheatManager::Xml_SetGuid(incidentXml, channelId); CAntiCheatManager::Xml_SetCheatType(incidentXml, type); if(pDescription && pDescription[0]) incidentXml->setAttr("description", pDescription); for(int i = 0; i < numParams; i++) { CryStackStringT<char, 16> paramNodeName; paramNodeName.FormatFast("%s-%d", PARAM_NODE, i+1); XmlNodeRef child = incidentXml->newChild(paramNodeName.c_str()); child->setAttr(PARAM_VALUE, params[i]); } return incidentXml; }
void CAreaProxy::SerializeXML( XmlNodeRef &entityNode,bool bLoading ) { if (m_nFlags & FLAG_NOT_SERIALIZE) return; if (bLoading) { XmlNodeRef areaNode = entityNode->findChild( "Area" ); if (!areaNode) return; int nId=0,nGroup=0,nPriority=0; float fProximity = 0; float fHeight = 0; areaNode->getAttr( "Id",nId ); areaNode->getAttr( "Group",nGroup ); areaNode->getAttr( "Proximity",fProximity ); areaNode->getAttr( "Priority",nPriority ); m_pArea->SetID(nId); m_pArea->SetGroup(nGroup); m_pArea->SetProximity(fProximity); m_pArea->SetPriority(nPriority); const char* token(0); XmlNodeRef pointsNode = areaNode->findChild( "Points" ); if (pointsNode) { for (int i = 0; i < pointsNode->getChildCount(); i++) { XmlNodeRef pntNode = pointsNode->getChild(i); Vec3 pos; if (pntNode->getAttr( "Pos",pos )) m_localPoints.push_back(pos); // Get sound obstruction bool bObstructSound = 0; pntNode->getAttr("ObstructSound", bObstructSound); m_abObstructSound.push_back(bObstructSound); } m_pArea->SetAreaType( ENTITY_AREA_TYPE_SHAPE ); areaNode->getAttr( "Height",fHeight ); m_pArea->SetHeight(fHeight); // Set points. OnMove(); } else if (areaNode->getAttr("SphereRadius",m_fRadius)) { // Sphere. areaNode->getAttr("SphereCenter",m_vCenter); m_pArea->SetSphere( m_pEntity->GetWorldTM().TransformPoint(m_vCenter),m_fRadius ); } else if (areaNode->getAttr("VolumeRadius",m_fRadius)) { areaNode->getAttr("Gravity",m_fGravity); areaNode->getAttr("DontDisableInvisible", m_bDontDisableInvisible); AABB box; box.Reset(); // Bezier Volume. pointsNode = areaNode->findChild( "BezierPoints" ); if (pointsNode) { for (int i = 0; i < pointsNode->getChildCount(); i++) { XmlNodeRef pntNode = pointsNode->getChild(i); Vec3 pt; if (pntNode->getAttr( "Pos",pt)) { m_bezierPoints.push_back(pt); box.Add( pt ); } } } m_pArea->SetAreaType( ENTITY_AREA_TYPE_GRAVITYVOLUME ); if (!m_pEntity->GetRenderProxy()) { IEntityRenderProxyPtr pRenderProxy = crycomponent_cast<IEntityRenderProxyPtr>(m_pEntity->CreateProxy( ENTITY_PROXY_RENDER )); m_pEntity->SetFlags(m_pEntity->GetFlags() | ENTITY_FLAG_SEND_RENDER_EVENT); if (box.min.x > box.max.x) box.min = box.max = Vec3(0,0,0); box.min-=Vec3(m_fRadius, m_fRadius, m_fRadius); box.max+=Vec3(m_fRadius, m_fRadius, m_fRadius); Matrix34 tm = m_pEntity->GetWorldTM_Fast(); box.SetTransformedAABB( m_pEntity->GetWorldTM_Fast().GetInverted(),box ); pRenderProxy->SetLocalBounds(box, true); } OnEnable(m_bIsEnable); } else if (areaNode->getAttr("AreaSolidFileName",&token)) { CCryFile file; int nAliasLen = sizeof("%level%")-1; const char* areaSolidFileName; if (strncmp(token,"%level%",nAliasLen) == 0) areaSolidFileName = GetIEntitySystem()->GetSystem()->GetI3DEngine()->GetLevelFilePath(token+nAliasLen); else areaSolidFileName = token; if( file.Open(areaSolidFileName,"rb") ) { int numberOfClosedPolygon = 0; int numberOfOpenPolygon = 0; m_pArea->BeginSettingSolid(m_pEntity->GetWorldTM()); file.ReadType(&numberOfClosedPolygon); file.ReadType(&numberOfOpenPolygon); ReadPolygonsForAreaSolid( file, numberOfClosedPolygon, true ); ReadPolygonsForAreaSolid( file, numberOfOpenPolygon, false ); m_pArea->EndSettingSolid(); } } else { // Box. Vec3 bmin(0,0,0),bmax(0,0,0); areaNode->getAttr("BoxMin",bmin); areaNode->getAttr("BoxMax",bmax); m_pArea->SetBox( bmin,bmax,m_pEntity->GetWorldTM() ); // Get sound obstruction XmlNodeRef const pNodeSoundData = areaNode->findChild("SoundData"); if (pNodeSoundData) { assert(m_abObstructSound.size() == 0); for (int i = 0; i < pNodeSoundData->getChildCount(); ++i) { XmlNodeRef const pNodeSide = pNodeSoundData->getChild(i); if (pNodeSide) { bool bObstructSound = false; pNodeSide->getAttr("ObstructSound", bObstructSound); m_abObstructSound.push_back(bObstructSound); } } } OnMove(); } m_pArea->ClearEntities(); XmlNodeRef entitiesNode = areaNode->findChild( "Entities" ); // Export Entities. if (entitiesNode) { for (int i = 0; i < entitiesNode->getChildCount(); i++) { XmlNodeRef entNode = entitiesNode->getChild(i); EntityId entityId; EntityGUID entityGuid; if(gEnv->pEntitySystem->EntitiesUseGUIDs()) { if (entNode->getAttr( "Guid",entityGuid )) m_pArea->AddEntity( entityGuid ); } else { if (entNode->getAttr( "Id",entityId )) m_pArea->AddEntity( entityId ); } } } } else { // Save points. XmlNodeRef areaNode = entityNode->newChild( "Area" ); areaNode->setAttr( "Id",m_pArea->GetID() ); areaNode->setAttr( "Group",m_pArea->GetGroup() ); areaNode->setAttr( "Proximity",m_pArea->GetProximity() ); areaNode->setAttr( "Priority", m_pArea->GetPriority() ); EEntityAreaType type = m_pArea->GetAreaType(); if (type == ENTITY_AREA_TYPE_SHAPE) { XmlNodeRef pointsNode = areaNode->newChild( "Points" ); for (unsigned int i = 0; i < m_localPoints.size(); i++) { XmlNodeRef pntNode = pointsNode->newChild("Point"); pntNode->setAttr( "Pos",m_localPoints[i] ); pntNode->setAttr("ObstructSound", m_abObstructSound[i]); } areaNode->setAttr( "Height",m_pArea->GetHeight() ); } else if (type == ENTITY_AREA_TYPE_SPHERE) { // Box. areaNode->setAttr("SphereCenter",m_vCenter); areaNode->setAttr("SphereRadius",m_fRadius); } else if (type == ENTITY_AREA_TYPE_BOX) { // Box. Vec3 bmin,bmax; m_pArea->GetBox(bmin,bmax); areaNode->setAttr("BoxMin",bmin); areaNode->setAttr("BoxMax",bmax); // Set sound obstruction XmlNodeRef const pNodeSoundData = areaNode->newChild("SoundData"); if (pNodeSoundData) { assert(m_abObstructSound.size() == 6); size_t nIndex = 0; tSoundObstructionIterConst const ItEnd = m_abObstructSound.end(); for (tSoundObstructionIterConst It = m_abObstructSound.begin(); It != ItEnd ; ++It) { bool const bObstructed = (bool)(*It); stack_string sTemp; sTemp.Format("Side%d", ++nIndex); XmlNodeRef const pNodeSide = pNodeSoundData->newChild(sTemp.c_str()); pNodeSide->setAttr("ObstructSound", bObstructed); } } } else if (type == ENTITY_AREA_TYPE_GRAVITYVOLUME) { areaNode->setAttr("VolumeRadius",m_fRadius); areaNode->setAttr("Gravity",m_fGravity); areaNode->setAttr("DontDisableInvisible", m_bDontDisableInvisible); XmlNodeRef pointsNode = areaNode->newChild( "BezierPoints" ); for (unsigned int i = 0; i < m_bezierPoints.size(); i++) { XmlNodeRef pntNode = pointsNode->newChild("Point"); pntNode->setAttr( "Pos",m_bezierPoints[i] ); } } #ifdef SW_ENTITY_ID_USE_GUID const std::vector<EntityGUID>& entGUIDs=*m_pArea->GetEntitiesGuid(); // Export Entities. if (!entGUIDs.empty()) { XmlNodeRef nodes = areaNode->newChild( "Entities" ); for (uint32 i = 0; i < entGUIDs.size(); i++) { EntityGUID guid = entGUIDs[i]; XmlNodeRef entNode = nodes->newChild( "Entity" ); entNode->setAttr( "Guid",guid ); entNode->setAttr( "Id",gEnv->pEntitySystem->GenerateEntityIdFromGuid(guid) ); } } #else const std::vector<EntityId>& entIDs=*m_pArea->GetEntities(); // Export Entities. if (!entIDs.empty()) { XmlNodeRef nodes = areaNode->newChild( "Entities" ); for (uint32 i = 0; i < entIDs.size(); i++) { int entityId = entIDs[i]; XmlNodeRef entNode = nodes->newChild( "Entity" ); entNode->setAttr( "Id",entityId ); } } #endif } }
void CAnimationProxyDualCharacterBase::Generate1P3PPairFile() { const int MAX_MODELS = 128; ICharacterModel *pCharacterModels[MAX_MODELS]; int numModels; gEnv->pCharacterManager->GetLoadedModels(NULL, numModels); numModels = min(numModels, MAX_MODELS); gEnv->pCharacterManager->GetLoadedModels(pCharacterModels, numModels); s_animCrCHashMap.clear(); for (uint32 i=0; i<numModels; ++i) { if (pCharacterModels[i]->GetNumInstances() > 0) { IAnimationSet *animSet = pCharacterModels[i]->GetICharInstanceFromModel(0)->GetIAnimationSet(); uint32 numAnims = animSet->GetAnimationCount(); for (uint32 anm = 0; anm < numAnims; anm++) { uint32 animCRC = animSet->GetCRCByAnimID(anm); if (s_animCrCHashMap.find(animCRC) == s_animCrCHashMap.end()) { int animID3P = -1; const char *name = animSet->GetNameByAnimID(anm); if (strlen(name) >= 255) { CRY_ASSERT_MESSAGE(0, string().Format("[CAnimationProxyDualCharacterBase::Generate1P3PPairFiles] Animname %s overruns buffer", name)); CryLogAlways("[CAnimationProxyDualCharacterBase::Generate1P3PPairFiles] Animname %s overruns buffer", name); continue; } const char *pos = CryStringUtils::stristr(name, "_1p"); if (pos) { char name3P[256]; strcpy(name3P, name); name3P[(int)(TRUNCATE_PTR)pos + 1 - (int)(TRUNCATE_PTR)name] = '3'; animID3P = animSet->GetAnimIDByName(name3P); if (animID3P >= 0) { uint32 animCRCTP = animSet->GetCRCByAnimID(animID3P); s_animCrCHashMap[animCRC] = animCRCTP; } } } } } } //--- Save the file CryFixedStringT<256> animCrC; XmlNodeRef nodePairList = gEnv->pSystem->CreateXmlNode( "Pairs" ); for (NameHashMap::iterator iter = s_animCrCHashMap.begin(); iter != s_animCrCHashMap.end(); ++iter) { XmlNodeRef nodePair = nodePairList->newChild( "Pair" ); animCrC.Format("%u", iter->first); nodePair->setAttr( "FP", animCrC.c_str()); animCrC.Format("%u", iter->second); nodePair->setAttr( "TP", animCrC.c_str()); } nodePairList->saveToFile(ANIMPAIR_PATHNAME); s_animCrCHashMap.clear(); Load1P3PPairFile(); }
bool CScriptSurfaceType::Load( int nId ) { m_nId = nId; IScriptSystem *pScriptSystem = gEnv->pScriptSystem; SmartScriptTable mtlTable; if (!pScriptSystem->GetGlobalValue("Materials", mtlTable)) { return false; } ////////////////////////////////////////////////////////////////////////// if (!pScriptSystem->ExecuteFile( m_script,true )) { GetISystem()->Warning( VALIDATOR_MODULE_3DENGINE,VALIDATOR_WARNING, VALIDATOR_FLAG_FILE|VALIDATOR_FLAG_SCRIPT, m_script.c_str(), "'%s' failed to load surface type definition script",m_name.c_str() ); return false; } if (!mtlTable->GetValue( m_name,m_pScriptTable )) return false; XmlNodeRef matNode = m_root->newChild("SurfaceType"); matNode->setAttr( "name",m_name ); // Load physics params. SmartScriptTable pPhysicsTable,props; float fBouncyness = 0.0f; float fFriction = 1.0f; int iPiercingResistence = sf_max_pierceable; // physics traces range 0-15 int imatBreakable = -1, bManuallyBreakable=0; m_iBreakability=0; m_nHitpoints=0; m_breakEnergy=0; if (m_pScriptTable->GetValue("physics",pPhysicsTable)) { pPhysicsTable->GetValue("friction",fFriction); pPhysicsTable->GetValue("bouncyness",fBouncyness); pPhysicsTable->GetValue("breakable_id",imatBreakable); if (pPhysicsTable->GetValue("pierceability",iPiercingResistence)) { if(iPiercingResistence>sf_max_pierceable) iPiercingResistence = sf_max_pierceable; } int nBreakable2d = 0; int bNoCollide = 0; pPhysicsTable->GetValue("no_collide", bNoCollide); if (pPhysicsTable->GetValue("break_energy",m_breakEnergy)) { bManuallyBreakable = sf_manually_breakable; m_iBreakability = 2; pPhysicsTable->GetValue("hit_points",m_nHitpoints); } else if (m_pScriptTable->GetValue("breakable_2d",props)) { nBreakable2d = 1; bManuallyBreakable = sf_manually_breakable; m_iBreakability = 1; props->GetValue("break_energy",m_breakEnergy); props->GetValue("hit_points",m_nHitpoints); } m_nFlags &= ~SURFACE_TYPE_NO_COLLIDE; if (bNoCollide) m_nFlags |= SURFACE_TYPE_NO_COLLIDE; XmlNodeRef physNode = matNode->newChild("Physics"); physNode->setAttr( "friction",fFriction ); physNode->setAttr( "elasticity",fBouncyness ); physNode->setAttr( "breakable_id",imatBreakable ); physNode->setAttr( "pierceability",iPiercingResistence ); physNode->setAttr( "no_collide",bNoCollide ); physNode->setAttr( "break_energy",m_breakEnergy ); physNode->setAttr( "hit_points",m_nHitpoints ); physNode->setAttr( "breakable_2d",nBreakable2d ); } SmartScriptTable pAITable; if (m_pScriptTable->GetValue("AI",pAITable)) { XmlNodeRef aiNode = matNode->newChild("AI"); float fImpactRadius = 1; float fFootStepRadius = 1; float proneMult = 1; float crouchMult = 1; float movingMult = 1; pAITable->GetValue( "fImpactRadius",fImpactRadius ); pAITable->GetValue( "fFootStepRadius",fFootStepRadius ); pAITable->GetValue( "proneMult",proneMult ); pAITable->GetValue( "crouchMult",crouchMult ); pAITable->GetValue( "movingMult",movingMult ); aiNode->setAttr( "fImpactRadius",fImpactRadius ); aiNode->setAttr( "fFootStepRadius",fFootStepRadius ); aiNode->setAttr( "proneMult",proneMult ); aiNode->setAttr( "crouchMult",crouchMult ); aiNode->setAttr( "movingMult",movingMult ); } gEnv->pPhysicalWorld->SetSurfaceParameters(m_nId,fBouncyness,fFriction, (uint32)(sf_pierceability(iPiercingResistence) | sf_matbreakable(imatBreakable) | bManuallyBreakable)); return true; }