void CMapInfo::ReadGlobal() { const LuaTable topTable = *mapRoot; map.humanName = topTable.GetString("description", map.name); map.wantedScript = topTable.GetString("script", map.wantedScript); map.hardness = topTable.GetFloat("maphardness", 100.0f); map.notDeformable = topTable.GetBool("notDeformable", false); map.gravity = topTable.GetFloat("gravity", 130.0f); map.gravity = max(0.001f, map.gravity); map.gravity = -map.gravity / (GAME_SPEED * GAME_SPEED); map.tidalStrength = topTable.GetFloat("tidalStrength", 0.0f); map.maxMetal = topTable.GetFloat("maxMetal", 0.02f); map.extractorRadius = topTable.GetFloat("extractorRadius", 500.0f); map.voidWater = topTable.GetBool("voidWater", false); // clamps map.hardness = max(0.0f, map.hardness); map.tidalStrength = max(0.0f, map.tidalStrength); map.maxMetal = max(0.0f, map.maxMetal); map.extractorRadius = max(0.0f, map.extractorRadius); }
void CUnitDefHandler::LoadSounds(const LuaTable& soundsTable, GuiSoundSet& gsound, const string& soundName) { string fileName = soundsTable.GetString(soundName, ""); if (!fileName.empty()) { LoadSound(gsound, fileName, 1.0f); return; } LuaTable sndTable = soundsTable.SubTable(soundName); for (int i = 1; true; i++) { LuaTable sndFileTable = sndTable.SubTable(i); if (sndFileTable.IsValid()) { fileName = sndFileTable.GetString("file", ""); if (!fileName.empty()) { const float volume = sndFileTable.GetFloat("volume", 1.0f); if (volume > 0.0f) { LoadSound(gsound, fileName, volume); } } } else { fileName = sndTable.GetString(i, ""); if (fileName.empty()) { break; } LoadSound(gsound, fileName, 1.0f); } } }
void CWeaponDefHandler::LoadSound(const LuaTable& wdTable, GuiSoundSet& gsound, const string& soundCat) { string name = ""; float volume = -1.0f; if (soundCat == "start") { name = wdTable.GetString("soundStart", ""); volume = wdTable.GetFloat("soundStartVolume", -1.0f); } else if (soundCat == "hit") { name = wdTable.GetString("soundHit", ""); volume = wdTable.GetFloat("soundHitVolume", -1.0f); } if (name != "") { const int id = LoadSoundFile(name); if (id > 0) { GuiSoundSet::Data soundData(name, 0, volume); gsound.sounds.push_back(soundData); gsound.setID(0, id); } } }
void WeaponDef::LoadSound( const LuaTable& wdTable, const std::string& soundKey, const unsigned int soundIdx, std::vector<GuiSoundSet::Data>& soundData) { string name = ""; int id = -1; float volume = -1.0f; soundData.push_back(GuiSoundSet::Data(name, id, volume)); assert(soundIdx < soundData.size()); assert(soundData[soundIdx].id == -1); if (soundKey == "soundStart") { name = wdTable.GetString(soundKey, ""); volume = wdTable.GetFloat(soundKey + "Volume", -1.0f); } else if (soundKey == "soundHitDry") { name = wdTable.GetString(soundKey, wdTable.GetString("soundHit", "")); volume = wdTable.GetFloat(soundKey + "Volume", wdTable.GetFloat("soundHitVolume", -1.0f)); } else if (soundKey == "soundHitWet") { name = wdTable.GetString(soundKey, wdTable.GetString("soundHit", "")); volume = wdTable.GetFloat(soundKey + "Volume", wdTable.GetFloat("soundHitVolume", -1.0f)); } if (name.empty()) return; if ((id = CommonDefHandler::LoadSoundFile(name)) <= 0) return; soundData[soundIdx] = GuiSoundSet::Data(name, id, volume); }
void CMapInfo::ReadGlobal() { const LuaTable topTable = parser->GetRoot(); map.description = topTable.GetString("description", map.name); map.author = topTable.GetString("author", ""); map.hardness = topTable.GetFloat("maphardness", 100.0f); map.notDeformable = topTable.GetBool("notDeformable", false); map.gravity = topTable.GetFloat("gravity", 130.0f); map.gravity = max(0.001f, map.gravity); map.gravity = -map.gravity / (GAME_SPEED * GAME_SPEED); map.tidalStrength = topTable.GetFloat("tidalStrength", 0.0f); map.maxMetal = topTable.GetFloat("maxMetal", 0.02f); map.extractorRadius = topTable.GetFloat("extractorRadius", 500.0f); map.voidWater = topTable.GetBool("voidWater", false); // clamps if (-0.001f < map.hardness && map.hardness <= 0.0f) map.hardness = -0.001f; else if (0.0f <= map.hardness && map.hardness < 0.001f) map.hardness = 0.001f; map.tidalStrength = max(0.000f, map.tidalStrength); map.maxMetal = max(0.000f, map.maxMetal); map.extractorRadius = max(0.000f, map.extractorRadius); }
void CMapInfo::ReadSmf() { // SMF specific settings const LuaTable mapResTable = parser->GetRoot().SubTable("resources"); smf.detailTexName = mapResTable.GetString("detailTex", ""); smf.specularTexName = mapResTable.GetString("specularTex", ""); smf.splatDetailTexName = mapResTable.GetString("splatDetailTex", ""); smf.splatDistrTexName = mapResTable.GetString("splatDistrTex", ""); smf.grassBladeTexName = mapResTable.GetString("grassBladeTex", ""); smf.grassShadingTexName = mapResTable.GetString("grassShadingTex", ""); smf.skyReflectModTexName = mapResTable.GetString("skyReflectModTex", ""); smf.detailNormalTexName = mapResTable.GetString("detailNormalTex", ""); smf.lightEmissionTexName = mapResTable.GetString("lightEmissionTex", ""); if (!smf.detailTexName.empty()) { smf.detailTexName = "maps/" + smf.detailTexName; } else { const LuaTable& resGfxMaps = resRoot->SubTable("graphics").SubTable("maps"); smf.detailTexName = resGfxMaps.GetString("detailtex", "detailtex2.bmp"); smf.detailTexName = "bitmaps/" + smf.detailTexName; } if (!smf.specularTexName.empty()) { smf.specularTexName = "maps/" + smf.specularTexName; } if (!smf.splatDetailTexName.empty()) { smf.splatDetailTexName = "maps/" + smf.splatDetailTexName; } if (!smf.splatDistrTexName.empty()) { smf.splatDistrTexName = "maps/" + smf.splatDistrTexName; } if (!smf.grassBladeTexName.empty()) { smf.grassBladeTexName = "maps/" + smf.grassBladeTexName; } if (!smf.grassShadingTexName.empty()) { smf.grassShadingTexName = "maps/" + smf.grassShadingTexName; } if (!smf.skyReflectModTexName.empty()) { smf.skyReflectModTexName = "maps/" + smf.skyReflectModTexName; } if (!smf.detailNormalTexName.empty()) { smf.detailNormalTexName = "maps/" + smf.detailNormalTexName; } if (!smf.lightEmissionTexName.empty()) { smf.lightEmissionTexName = "maps/" + smf.lightEmissionTexName; } // height overrides const LuaTable smfTable = parser->GetRoot().SubTable("smf"); smf.minHeightOverride = smfTable.KeyExists("minHeight"); smf.maxHeightOverride = smfTable.KeyExists("maxHeight"); smf.minHeight = smfTable.GetFloat("minHeight", 0.0f); smf.maxHeight = smfTable.GetFloat("maxHeight", 0.0f); std::stringstream ss; for (int i = 0; /* no test */; i++) { ss.str(""); ss << "smtFileName" << i; if (smfTable.KeyExists(ss.str())) { smf.smtFileNames.push_back(smfTable.GetString(ss.str(), ".smt")); } else { break; } } }
void CSyncer::LoadUnits(bool checksum) { unitsLeft = 0; LuaParser luaParser("gamedata/defs.lua", SPRING_VFS_MOD_BASE, SPRING_VFS_ZIP); if (!luaParser.Execute()) { logOutput.Print("luaParser.Execute() failed"); return; } LuaTable rootTable = luaParser.GetRoot().SubTable("UnitDefs"); if (!rootTable.IsValid()) { logOutput.Print("root unitdef table invalid"); return; } vector<string> unitDefNames; rootTable.GetKeys(unitDefNames); const int count = (int)unitDefNames.size(); for (int i = 0; i < count; ++i) { const string& udName = unitDefNames[i]; LuaTable udTable = rootTable.SubTable(udName); Unit u; u.fullName = udTable.GetString("name", udName); if (checksum) { const string fileName = udTable.GetString("filename", ""); const string deadName = udTable.GetString("corpse", udName + "_dead"); const string modelName = udTable.GetString("objectname", udName); u.fbi = CalculateCRC(fileName); u.cob = CalculateCRC("scripts/" + udName + ".cob"); u.model = CalculateCRC("objects3d/" + modelName); // s3o ? u.model += CalculateCRC("objects3d/" + modelName + ".3do"); u.model += CalculateCRC("objects3d/" + deadName + ".3do"); } units[udName] = u; } // map the unitIds map<string, Unit>::iterator mit; for (mit = units.begin(); mit != units.end(); ++mit) { unitIds.push_back(mit->first); } unitsLeft = count; return; }
bool SideParser::Load() { dataVec.clear(); errorLog.clear(); LuaParser parser("gamedata/sidedata.lua", SPRING_VFS_MOD_BASE, SPRING_VFS_MOD_BASE); #if !defined UNITSYNC && !defined DEDICATED // this should not be included with unitsync: // 1. avoids linkage with LuaSyncedRead // 2. ModOptions are not valid during unitsync mod parsing parser.GetTable("Spring"); parser.AddFunc("GetModOptions", LuaSyncedRead::GetModOptions); parser.EndTable(); #endif if (!parser.Execute()) { errorLog = parser.GetErrorLog(); return false; } set<string> sideSet; const LuaTable root = parser.GetRoot(); for (int i = 1; /* no-op */; i++) { const LuaTable sideTable = root.SubTable(i); if (!sideTable.IsValid()) { break; } Data data; data.caseName = sideTable.GetString("name", ""); data.sideName = StringToLower(data.caseName); data.startUnit = sideTable.GetString("startUnit", ""); data.startUnit = StringToLower(data.startUnit); if (data.sideName.empty()) { logOutput.Print("Missing side name: %i", i); } else if (data.startUnit.empty()) { logOutput.Print("Missing side start unit: " + data.sideName); } else { if (sideSet.find(data.sideName) != sideSet.end()) { logOutput.Print("Duplicate side name: " + data.sideName); } else { sideSet.insert(data.sideName); dataVec.push_back(data); } } } return true; }
CGroundDecalHandler::CGroundDecalHandler(void) { drawDecals = false; decalLevel = std::max(0, configHandler->Get("GroundDecals", 1)); groundScarAlphaFade = configHandler->Get("GroundScarAlphaFade", 0); if (decalLevel == 0) { return; } drawDecals = true; unsigned char* buf=new unsigned char[512*512*4]; memset(buf,0,512*512*4); LuaParser resourcesParser("gamedata/resources.lua", SPRING_VFS_MOD_BASE, SPRING_VFS_ZIP); if (!resourcesParser.Execute()) { logOutput.Print(resourcesParser.GetErrorLog()); } const LuaTable scarsTable = resourcesParser.GetRoot().SubTable("graphics").SubTable("scars"); LoadScar("bitmaps/" + scarsTable.GetString(2, "scars/scar2.bmp"), buf, 0, 0); LoadScar("bitmaps/" + scarsTable.GetString(3, "scars/scar3.bmp"), buf, 256, 0); LoadScar("bitmaps/" + scarsTable.GetString(1, "scars/scar1.bmp"), buf, 0, 256); LoadScar("bitmaps/" + scarsTable.GetString(4, "scars/scar4.bmp"), buf, 256, 256); glGenTextures(1, &scarTex); glBindTexture(GL_TEXTURE_2D, scarTex); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_NEAREST); // glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); // glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glBuildMipmaps(GL_TEXTURE_2D,GL_RGBA8 ,512, 512, GL_RGBA, GL_UNSIGNED_BYTE, buf); scarFieldX=gs->mapx/32; scarFieldY=gs->mapy/32; scarField=new std::set<Scar*>[scarFieldX*scarFieldY]; lastTest=0; maxOverlap=decalLevel+1; delete[] buf; if (shadowHandler->canUseShadows) { decalVP = LoadVertexProgram("ARB/GroundDecals.vp"); decalFPsmf = LoadFragmentProgram("ARB/GroundDecalsSMF.fp"); decalFPsm3 = LoadFragmentProgram("ARB/GroundDecalsSM3.fp"); } }
void CMapInfo::ReadSmf() { // SMF specific settings const LuaTable mapResTable = mapRoot->SubTable("resources"); smf.detailTexName = mapResTable.GetString("detailTex", ""); if (!smf.detailTexName.empty()) { smf.detailTexName = "maps/" + smf.detailTexName; } else { const LuaTable resGfxMaps = resRoot->SubTable("graphics").SubTable("maps"); smf.detailTexName = resGfxMaps.GetString("detailtex", "detailtex2.bmp"); smf.detailTexName = "bitmaps/" + smf.detailTexName; } }
void CMapInfo::ReadTerrainTypes() { const LuaTable terrTypeTable = mapRoot->SubTable("terrainTypes"); for (int tt = 0; tt < 256; tt++) { TerrainType& terrType = terrainTypes[tt]; const LuaTable terrain = terrTypeTable.SubTable(tt); terrType.name = terrain.GetString("name", "Default"); terrType.hardness = terrain.GetFloat("hardness", 1.0f); terrType.receiveTracks = terrain.GetBool("receiveTracks", true); const LuaTable moveTable = terrain.SubTable("moveSpeeds"); terrType.tankSpeed = moveTable.GetFloat("tank", 1.0f); terrType.kbotSpeed = moveTable.GetFloat("kbot", 1.0f); terrType.hoverSpeed = moveTable.GetFloat("hover", 1.0f); terrType.shipSpeed = moveTable.GetFloat("ship", 1.0f); // clamps terrType.hardness = max(0.0f, terrType.hardness); terrType.tankSpeed = max(0.0f, terrType.tankSpeed); terrType.kbotSpeed = max(0.0f, terrType.kbotSpeed); terrType.hoverSpeed = max(0.0f, terrType.hoverSpeed); terrType.shipSpeed = max(0.0f, terrType.shipSpeed); } }
void CAssParser::SetPieceParentName( SAssPiece* piece, const S3DModel* model, const aiNode* pieceNode, const LuaTable& pieceTable, ParentNameMap& parentMap ) { // Get parent name from metadata or model if (pieceTable.KeyExists("parent")) { parentMap[piece] = pieceTable.GetString("parent", ""); return; } if (pieceNode->mParent == nullptr) return; if (pieceNode->mParent->mParent != nullptr) { // parent is not the root parentMap[piece] = std::string(pieceNode->mParent->mName.data); } else { // parent is the root (which must already exist) assert(model->GetRootPiece() != nullptr); parentMap[piece] = (model->GetRootPiece())->name; } }
CDamageArrayHandler::CDamageArrayHandler(LuaParser* defsParser) { #define DEFAULT_ARMORDEF_NAME "default" try { const LuaTable rootTable = defsParser->GetRoot().SubTable("ArmorDefs"); if (!rootTable.IsValid()) throw content_error("Error loading ArmorDefs"); // GetKeys() sorts the keys, so can not simply push_back before call rootTable.GetKeys(armorDefKeys); armorDefKeys.insert(armorDefKeys.begin(), DEFAULT_ARMORDEF_NAME); armorDefNameIdxMap[DEFAULT_ARMORDEF_NAME] = 0; LOG("[%s] number of ArmorDefs: " _STPF_, __FUNCTION__, armorDefKeys.size()); // expects the following structure, subtables must be in array-format: // // {"tanks" = {[1] = "supertank", [2] = "megatank"}, "infantry" = {[1] = "dude"}, ...} // // the old (pre-95.0) <key, value> subtable definitions are no longer supported! // for (unsigned int armorDefIdx = 1; armorDefIdx < armorDefKeys.size(); armorDefIdx++) { const std::string armorDefName = StringToLower(armorDefKeys[armorDefIdx]); if (armorDefName == DEFAULT_ARMORDEF_NAME) { // ignore, no need to clear entire table LOG_L(L_WARNING, "[%s] ArmorDefs: tried to define the \"%s\" armor type!", __FUNCTION__, DEFAULT_ARMORDEF_NAME); continue; } armorDefNameIdxMap[armorDefName] = armorDefIdx; const LuaTable armorDefTable = rootTable.SubTable(armorDefKeys[armorDefIdx]); const unsigned int numArmorDefEntries = armorDefTable.GetLength(); for (unsigned int armorDefEntryIdx = 0; armorDefEntryIdx < numArmorDefEntries; armorDefEntryIdx++) { const std::string& unitDefName = StringToLower(armorDefTable.GetString(armorDefEntryIdx + 1, "")); const auto armorDefTableIt = armorDefNameIdxMap.find(unitDefName); if (armorDefTableIt == armorDefNameIdxMap.end()) { armorDefNameIdxMap[unitDefName] = armorDefIdx; continue; } LOG_L(L_WARNING, "[%s] UnitDef \"%s\" in ArmorDef \"%s\" already belongs to ArmorDef category %d!", __FUNCTION__, unitDefName.c_str(), armorDefName.c_str(), armorDefTableIt->second); } } } catch (const content_error&) { armorDefNameIdxMap.clear(); armorDefNameIdxMap[DEFAULT_ARMORDEF_NAME] = 0; armorDefKeys.clear(); armorDefKeys.push_back(DEFAULT_ARMORDEF_NAME); } }
void SolidObjectDecalDef::Parse(const LuaTable& table) { groundDecalTypeName = table.GetString("groundDecalType", table.GetString("buildingGroundDecalType", "")); trackDecalTypeName = table.GetString("trackType", "StdTank"); useGroundDecal = table.GetBool("useGroundDecal", table.GetBool("useBuildingGroundDecal", false)); groundDecalType = -1; groundDecalSizeX = table.GetInt("groundDecalSizeX", table.GetInt("buildingGroundDecalSizeX", 4)); groundDecalSizeY = table.GetInt("groundDecalSizeY", table.GetInt("buildingGroundDecalSizeY", 4)); groundDecalDecaySpeed = table.GetFloat("groundDecalDecaySpeed", table.GetFloat("buildingGroundDecalDecaySpeed", 0.1f)); leaveTrackDecals = table.GetBool("leaveTracks", false); trackDecalType = -1; trackDecalWidth = table.GetFloat("trackWidth", 32.0f); trackDecalOffset = table.GetFloat("trackOffset", 0.0f); trackDecalStrength = table.GetFloat("trackStrength", 0.0f); trackDecalStretch = table.GetFloat("trackStretch", 1.0f); }
void CPreGame::StartServer(const std::string& setupscript) { assert(!gameServer); GameData* startupData = new GameData(); CGameSetup* setup = new CGameSetup(); setup->Init(setupscript); startupData->SetRandomSeed(static_cast<unsigned>(gu->usRandInt())); if (! setup->mapName.empty()) { // would be better to use MapInfo here, but this doesn't work LoadMap(setup->mapName); // map into VFS std::string mapDefFile; const std::string extension = setup->mapName.substr(setup->mapName.length()-3); if (extension == "smf") mapDefFile = std::string("maps/")+setup->mapName.substr(0,setup->mapName.find_last_of('.'))+".smd"; else if(extension == "sm3") mapDefFile = string("maps/")+setup->mapName; else throw std::runtime_error("CPreGame::StartServer(): Unknown extension: " + extension); MapParser mp(setup->mapName); LuaTable mapRoot = mp.GetRoot(); const std::string mapWantedScript = mapRoot.GetString("script", ""); const std::string scriptFile = mapRoot.GetString("scriptFile", ""); if (!mapWantedScript.empty()) { setup->scriptName = mapWantedScript; } } // here we now the name of the script to use CScriptHandler::SelectScript(setup->scriptName); std::string scriptWantedMod; scriptWantedMod = CScriptHandler::Instance().chosenScript->GetModName(); if (!scriptWantedMod.empty()) { setup->modName = archiveScanner->ModArchiveToModName(scriptWantedMod); } LoadMod(setup->modName); std::string modArchive = archiveScanner->ModNameToModArchive(setup->modName); startupData->SetModChecksum(archiveScanner->GetModChecksum(modArchive)); std::string mapFromScript = CScriptHandler::Instance().chosenScript->GetMapName(); if (!mapFromScript.empty() && setup->mapName != mapFromScript) { //TODO unload old map LoadMap(mapFromScript, true); } startupData->SetMapChecksum(archiveScanner->GetMapChecksum(setup->mapName)); setup->LoadStartPositions(); good_fpu_control_registers("before CGameServer creation"); startupData->SetSetup(setup->gameSetupText); gameServer = new CGameServer(settings.get(), false, startupData, setup); gameServer->AddLocalClient(settings->myPlayerName, SpringVersion::GetFull()); good_fpu_control_registers("after CGameServer creation"); }
void CArchiveScanner::ReadCacheData(const std::string& filename) { if (!FileSystem::FileExists(filename)) { LOG_L(L_INFO, "Archive cache doesn't exist: %s", filename.c_str()); return; } LuaParser p(filename, SPRING_VFS_RAW, SPRING_VFS_BASE); if (!p.Execute()) { LOG_L(L_ERROR, "Failed to parse archive cache: %s", p.GetErrorLog().c_str()); return; } const LuaTable archiveCache = p.GetRoot(); // Do not load old version caches const int ver = archiveCache.GetInt("internalVer", (INTERNAL_VER + 1)); if (ver != INTERNAL_VER) { return; } const LuaTable archives = archiveCache.SubTable("archives"); for (int i = 1; archives.KeyExists(i); ++i) { const LuaTable curArchive = archives.SubTable(i); const LuaTable archived = curArchive.SubTable("archivedata"); std::string name = curArchive.GetString("name", ""); ArchiveInfo& ai = archiveInfos[StringToLower(name)]; ai.origName = name; ai.path = curArchive.GetString("path", ""); // do not use LuaTable.GetInt() for 32-bit integers, the Spring lua // library uses 32-bit floats to represent numbers, which can only // represent 2^24 consecutive integers ai.modified = strtoul(curArchive.GetString("modified", "0").c_str(), 0, 10); ai.checksum = strtoul(curArchive.GetString("checksum", "0").c_str(), 0, 10); ai.updated = false; ai.archiveData = CArchiveScanner::ArchiveData(archived, true); if (ai.archiveData.GetModType() == modtype::map) { AddDependency(ai.archiveData.GetDependencies(), "Map Helper v1"); } else if (ai.archiveData.GetModType() == modtype::primary) { AddDependency(ai.archiveData.GetDependencies(), "Spring content v1"); } } const LuaTable brokenArchives = archiveCache.SubTable("brokenArchives"); for (int i = 1; brokenArchives.KeyExists(i); ++i) { const LuaTable curArchive = brokenArchives.SubTable(i); std::string name = curArchive.GetString("name", ""); StringToLowerInPlace(name); BrokenArchive& ba = this->brokenArchives[name]; ba.path = curArchive.GetString("path", ""); ba.modified = strtoul(curArchive.GetString("modified", "0").c_str(), 0, 10); ba.updated = false; ba.problem = curArchive.GetString("problem", "unknown"); } isDirty = false; }
void CAssParser::FindTextures( S3DModel* model, const aiScene* scene, const LuaTable& modelTable, const std::string& modelPath, const std::string& modelName ) { // Assign textures // The S3O texture handler uses two textures. // The first contains diffuse color (RGB) and teamcolor (A) // The second contains glow (R), reflectivity (G) and 1-bit Alpha (A). // 1. try to find by name (lowest prioriy) if (model->tex1.empty()) model->tex1 = FindTextureByRegex("unittextures/", modelName); // high priority if (model->tex1.empty()) model->tex1 = FindTextureByRegex("unittextures/", modelName + "1"); if (model->tex2.empty()) model->tex2 = FindTextureByRegex("unittextures/", modelName + "2"); if (model->tex1.empty()) model->tex1 = FindTextureByRegex(modelPath, "tex1"); if (model->tex2.empty()) model->tex2 = FindTextureByRegex(modelPath, "tex2"); if (model->tex1.empty()) model->tex1 = FindTextureByRegex(modelPath, "diffuse"); if (model->tex2.empty()) model->tex2 = FindTextureByRegex(modelPath, "glow"); // low priority // 2. gather model-defined textures of first material (medium priority) if (scene->mNumMaterials > 0) { const unsigned int texTypes[] = { aiTextureType_SPECULAR, aiTextureType_UNKNOWN, aiTextureType_DIFFUSE, /* // TODO: support these too (we need to allow constructing tex1 & tex2 from several sources) aiTextureType_EMISSIVE, aiTextureType_HEIGHT, aiTextureType_NORMALS, aiTextureType_SHININESS, aiTextureType_OPACITY, */ }; for (unsigned int n = 0; n < (sizeof(texTypes) / sizeof(texTypes[0])); n++) { aiString textureFile; if (scene->mMaterials[0]->Get(AI_MATKEY_TEXTURE(texTypes[n], 0), textureFile) != aiReturn_SUCCESS) continue; assert(textureFile.length > 0); model->tex1 = FindTexture(textureFile.data, modelPath, model->tex1); } } // 3. try to load from metafile (highest priority) model->tex1 = FindTexture(modelTable.GetString("tex1", ""), modelPath, model->tex1); model->tex2 = FindTexture(modelTable.GetString("tex2", ""), modelPath, model->tex2); model->invertTexYAxis = modelTable.GetBool("fliptextures", true); // Flip texture upside down model->invertTexAlpha = modelTable.GetBool("invertteamcolor", true); // Reverse teamcolor levels }
void CArchiveScanner::ReadCacheData(const string& filename) { LuaParser p(filename, SPRING_VFS_RAW, SPRING_VFS_BASE); if (!p.Execute()) { logOutput.Print("ERROR in " + filename + ": " + p.GetErrorLog()); } const LuaTable archiveCache = p.GetRoot(); const LuaTable archives = archiveCache.SubTable("archives"); // Do not load old version caches const int ver = archiveCache.GetInt("internalVer", (INTERNAL_VER + 1)); if (ver != INTERNAL_VER) { return; } for (int i = 1; archives.KeyExists(i); ++i) { const LuaTable curArchive = archives.SubTable(i); const LuaTable archived = curArchive.SubTable("archivedata"); ArchiveInfo ai; ai.origName = curArchive.GetString("name", ""); ai.path = curArchive.GetString("path", ""); // do not use LuaTable.GetInt() for 32-bit integers, the Spring lua // library uses 32-bit floats to represent numbers, which can only // represent 2^24 consecutive integers ai.modified = strtoul(curArchive.GetString("modified", "0").c_str(), 0, 10); ai.checksum = strtoul(curArchive.GetString("checksum", "0").c_str(), 0, 10); ai.updated = false; ai.archiveData = GetArchiveData(archived); if (ai.archiveData.modType == modtype::map) AddDependency(ai.archiveData.dependencies, "maphelper.sdz"); else if (ai.archiveData.modType == modtype::primary) AddDependency(ai.archiveData.dependencies, "Spring content v1"); string lcname = StringToLower(ai.origName); archiveInfo[lcname] = ai; } isDirty = false; }
void CWeaponDefHandler::LoadSound(const LuaTable& wdTable, GuiSoundSet& gsound, const string& soundCat) { string name = ""; float volume = -1.0f; if (soundCat == "start") { name = wdTable.GetString("soundStart", ""); volume = wdTable.GetFloat("soundStartVolume", -1.0f); } else if (soundCat == "hit") { name = wdTable.GetString("soundHit", ""); volume = wdTable.GetFloat("soundHitVolume", -1.0f); } if (name != "") { if (!sound->HasSoundItem(name)) { if (name.find(".wav") == string::npos) { // .wav extension missing, add it name += ".wav"; } const string soundPath = "sounds/" + name; CFileHandler sfile(soundPath); if (sfile.FileExists()) { // only push data if we extracted a valid name GuiSoundSet::Data soundData(name, 0, volume); gsound.sounds.push_back(soundData); int id = sound->GetSoundId(soundPath); gsound.setID(0, id); } } else { GuiSoundSet::Data soundData(name, 0, volume); gsound.sounds.push_back(soundData); int id = sound->GetSoundId(name); gsound.setID(0, id); } } }
void CMapInfo::ReadSmf() { // SMF specific settings const LuaTable mapResTable = mapRoot->SubTable("resources"); smf.detailTexName = mapResTable.GetString("detailTex", ""); if (!smf.detailTexName.empty()) { smf.detailTexName = "maps/" + smf.detailTexName; } else { const LuaTable resGfxMaps = resRoot->SubTable("graphics").SubTable("maps"); smf.detailTexName = resGfxMaps.GetString("detailtex", "detailtex2.bmp"); smf.detailTexName = "bitmaps/" + smf.detailTexName; } // height overrides const LuaTable smfTable = mapRoot->SubTable("smf"); smf.minHeightOverride = smfTable.KeyExists("minHeight"); smf.maxHeightOverride = smfTable.KeyExists("maxHeight"); smf.minHeight = smfTable.GetFloat("minHeight", 0.0f); smf.maxHeight = smfTable.GetFloat("maxHeight", 0.0f); }
void SolidObjectDef::ParseCollisionVolume(const LuaTable& table) { collisionVolume = new CollisionVolume( table.GetString("collisionVolumeType", ""), table.GetFloat3("collisionVolumeScales", ZeroVector), table.GetFloat3("collisionVolumeOffsets", ZeroVector) ); // if this unit wants per-piece volumes, make // its main collision volume deferent and let // it ignore hits collisionVolume->SetDefaultToPieceTree(table.GetBool("usePieceCollisionVolumes", false)); collisionVolume->SetDefaultToFootPrint(table.GetBool("useFootPrintCollisionVolume", false)); collisionVolume->SetIgnoreHits(collisionVolume->DefaultToPieceTree()); }
void CAssParser::FindTextures( S3DModel* model, const aiScene* scene, const LuaTable& modelTable, const std::string& modelPath, const std::string& modelName ) { // 1. try to find by name (lowest priority) model->texs[0] = FindTextureByRegex("unittextures/", modelName); if (model->texs[0].empty()) model->texs[0] = FindTextureByRegex("unittextures/", modelName + "1"); if (model->texs[1].empty()) model->texs[1] = FindTextureByRegex("unittextures/", modelName + "2"); if (model->texs[0].empty()) model->texs[0] = FindTextureByRegex(modelPath, "tex1"); if (model->texs[1].empty()) model->texs[1] = FindTextureByRegex(modelPath, "tex2"); if (model->texs[0].empty()) model->texs[0] = FindTextureByRegex(modelPath, "diffuse"); if (model->texs[1].empty()) model->texs[1] = FindTextureByRegex(modelPath, "glow"); // lowest-priority name // 2. gather model-defined textures of first material (medium priority) if (scene->mNumMaterials > 0) { constexpr unsigned int texTypes[] = { aiTextureType_SPECULAR, aiTextureType_UNKNOWN, aiTextureType_DIFFUSE, /* // TODO: support these too (we need to allow constructing tex1 & tex2 from several sources) aiTextureType_EMISSIVE, aiTextureType_HEIGHT, aiTextureType_NORMALS, aiTextureType_SHININESS, aiTextureType_OPACITY, */ }; for (unsigned int texType: texTypes) { aiString textureFile; if (scene->mMaterials[0]->Get(AI_MATKEY_TEXTURE(texType, 0), textureFile) != aiReturn_SUCCESS) continue; assert(textureFile.length > 0); model->texs[0] = FindTexture(textureFile.data, modelPath, model->texs[0]); } } // 3. try to load from metafile (highest priority) model->texs[0] = FindTexture(modelTable.GetString("tex1", ""), modelPath, model->texs[0]); model->texs[1] = FindTexture(modelTable.GetString("tex2", ""), modelPath, model->texs[1]); }
void CAssParser::SetPieceParentName( SAssPiece* piece, const S3DModel* model, const aiNode* pieceNode, const LuaTable& pieceTable ) { // Get parent name from metadata or model if (pieceTable.KeyExists("parent")) { piece->parentName = pieceTable.GetString("parent", ""); } else if (pieceNode->mParent != NULL) { if (pieceNode->mParent->mParent != NULL) { piece->parentName = std::string(pieceNode->mParent->mName.data); } else { // my parent is the root (which must already exist) assert(model->GetRootPiece() != NULL); piece->parentName = model->GetRootPiece()->name; } } }
CArchiveScanner::ArchiveData CArchiveScanner::GetArchiveData(const LuaTable& archiveTable) { ArchiveData md; if (!archiveTable.IsValid()) { return md; } md.name = archiveTable.GetString("name", ""); md.shortName = archiveTable.GetString("shortName", ""); md.version = archiveTable.GetString("version", ""); md.mutator = archiveTable.GetString("mutator", ""); md.game = archiveTable.GetString("game", ""); md.shortGame = archiveTable.GetString("shortGame", ""); md.description = archiveTable.GetString("description", ""); md.modType = archiveTable.GetInt("modType", 0); md.mapfile = archiveTable.GetString("mapfile", ""); const LuaTable dependencies = archiveTable.SubTable("depend"); for (int dep = 1; dependencies.KeyExists(dep); ++dep) { const std::string depend = dependencies.GetString(dep, ""); md.dependencies.push_back(depend); } const LuaTable replaces = archiveTable.SubTable("replace"); for (int rep = 1; replaces.KeyExists(rep); ++rep) { md.replaces.push_back(replaces.GetString(rep, "")); } // HACK needed until lobbies, lobbyserver and unitsync are sorted out // so they can uniquely identify different versions of the same mod. // (at time of this writing they use name only) // NOTE when changing this, this function is used both by the code that // reads ArchiveCache.lua and the code that reads modinfo.lua from the mod. // so make sure it doesn't keep adding stuff to the name everytime // Spring/unitsync is loaded. if (md.name.find(md.version) == std::string::npos && !md.version.empty()) { md.name += " " + md.version; } return md; }
void CMapInfo::ReadAtmosphere() { // MAP\ATMOSPHERE const LuaTable atmoTable = mapRoot->SubTable("atmosphere"); atmosphere_t& atmo = atmosphere; atmo.cloudDensity = atmoTable.GetFloat("cloudDensity", 0.5f); atmo.minWind = atmoTable.GetFloat("minWind", 5.0f); atmo.maxWind = atmoTable.GetFloat("maxWind", 25.0f); atmo.fogStart = atmoTable.GetFloat("fogStart", 0.1f); atmo.fogColor = atmoTable.GetFloat3("fogColor", float3(0.7f, 0.7f, 0.8f)); atmo.skyColor = atmoTable.GetFloat3("skyColor", float3(0.1f, 0.15f, 0.7f)); atmo.sunColor = atmoTable.GetFloat3("sunColor", float3(1.0f, 1.0f, 1.0f)); atmo.cloudColor = atmoTable.GetFloat3("cloudColor", float3(1.0f, 1.0f, 1.0f)); atmo.skyBox = atmoTable.GetString("skyBox", ""); // clamps atmo.cloudDensity = max(0.0f, atmo.cloudDensity); atmo.maxWind = max(0.0f, atmo.maxWind); atmo.minWind = max(0.0f, atmo.minWind); atmo.minWind = min(atmo.maxWind, atmo.minWind); }
static inline void GetGroundScars(std::unordered_map<std::string, STex>& textures) { LuaParser resourcesParser("gamedata/resources.lua", SPRING_VFS_MOD_BASE, SPRING_VFS_ZIP); if (!resourcesParser.Execute()) { LOG_L(L_ERROR, "Failed to load resources: %s", resourcesParser.GetErrorLog().c_str()); } const LuaTable scarsTable = resourcesParser.GetRoot().SubTable("graphics").SubTable("scars"); for (int i = 1; i <= scarsTable.GetLength(); ++i) { std::string texName = scarsTable.GetString(i, IntToString(i, "scars/scar%i.bmp")); std::string texName2 = texName + ".dds"; //FIXME auto name = IntToString(i); try { textures[ name ] = LoadTexture(texName); textures[GetExtraTextureName(name)] = LoadTexture(texName2); } catch(const content_error& err) { LOG_L(L_ERROR, "%s", err.what()); } } }
/** Load the messages from gamedata/messages.lua into memory. */ void CMessages::Load() { LuaParser luaParser("gamedata/messages.lua", SPRING_VFS_MOD_BASE, SPRING_VFS_MOD_BASE); if (!luaParser.Execute()) { // Show parse errors in the infolog. logOutput.Print(string("ERROR: messages.lua: ") + luaParser.GetErrorLog()); return; } const LuaTable root = luaParser.GetRoot(); vector<string> labels; root.GetKeys(labels); for (size_t l = 0; l < labels.size(); l++) { const string label = StringToLower(labels[l]); const LuaTable msgTable = root.SubTable(label); if (!msgTable.IsValid()) { continue; } vector<string> msgs; for (int s = 1; true; s++) { const string msg = msgTable.GetString(s, ""); if (msg.empty()) { break; } msgs.push_back(msg); } if (!msgs.empty()) { tr[label] = msgs; } } loaded = true; }
void CCustomExplosionGenerator::Load(CExplosionGeneratorHandler* h, const string& tag) { static std::map<string, CEGData> cachedCEGs; std::map<string, CEGData>::iterator it = cachedCEGs.find(tag); if (it == cachedCEGs.end()) { CEGData cegData; const LuaTable& root = h->GetTable(); const LuaTable expTable = root.SubTable(tag); if (!expTable.IsValid()) { throw content_error("Explosion info for " + tag + " not found."); } vector<string> spawns; expTable.GetKeys(spawns); for (vector<string>::iterator si = spawns.begin(); si != spawns.end(); ++si) { ProjectileSpawnInfo psi; const string& spawnName = *si; const LuaTable spawnTable = expTable.SubTable(spawnName); if (!spawnTable.IsValid() || spawnName == "groundflash") { continue; } const string className = spawnTable.GetString("class", spawnName); unsigned int flags = 0; if (spawnTable.GetBool("ground", false)) { flags |= SPW_GROUND; } if (spawnTable.GetBool("water", false)) { flags |= SPW_WATER; } if (spawnTable.GetBool("air", false)) { flags |= SPW_AIR; } if (spawnTable.GetBool("underwater", false)) { flags |= SPW_UNDERWATER; } if (spawnTable.GetBool("unit", false)) { flags |= SPW_UNIT; } if (spawnTable.GetBool("nounit", false)) { flags |= SPW_NO_UNIT; } psi.projectileClass = h->projectileClasses.GetClass(className); psi.flags = flags; psi.count = spawnTable.GetInt("count", 1); string code; map<string, string> props; map<string, string>::const_iterator propIt; spawnTable.SubTable("properties").GetMap(props); for (propIt = props.begin(); propIt != props.end(); ++propIt) { creg::Class::Member* m = psi.projectileClass->FindMember(propIt->first.c_str()); if (m && (m->flags & creg::CM_Config)) { ParseExplosionCode(&psi, m->offset, m->type, propIt->second, code); } } code += (char)OP_END; psi.code.resize(code.size()); copy(code.begin(), code.end(), psi.code.begin()); cegData.projectileSpawn.push_back(psi); } const LuaTable gndTable = expTable.SubTable("groundflash"); const int ttl = gndTable.GetInt("ttl", 0); if (ttl > 0) { cegData.groundFlash.circleAlpha = gndTable.GetFloat("circleAlpha", 0.0f); cegData.groundFlash.flashSize = gndTable.GetFloat("flashSize", 0.0f); cegData.groundFlash.flashAlpha = gndTable.GetFloat("flashAlpha", 0.0f); cegData.groundFlash.circleGrowth = gndTable.GetFloat("circleGrowth", 0.0f); cegData.groundFlash.color = gndTable.GetFloat3("color", float3(1.0f, 1.0f, 0.8f)); unsigned int flags = SPW_GROUND; if (gndTable.GetBool("ground", false)) { flags |= SPW_GROUND; } if (gndTable.GetBool("water", false)) { flags |= SPW_WATER; } if (gndTable.GetBool("air", false)) { flags |= SPW_AIR; } if (gndTable.GetBool("underwater", false)) { flags |= SPW_UNDERWATER; } if (gndTable.GetBool("unit", false)) { flags |= SPW_UNIT; } if (gndTable.GetBool("nounit", false)) { flags |= SPW_NO_UNIT; } cegData.groundFlash.flags = flags; cegData.groundFlash.ttl = ttl; } cegData.useDefaultExplosions = expTable.GetBool("useDefaultExplosions", false); cachedCEGs[tag] = cegData; currentCEG = &cachedCEGs[tag]; } else { currentCEG = &(it->second); } }
unsigned int CCustomExplosionGenerator::Load(CExplosionGeneratorHandler* h, const string& tag) { unsigned int explosionID = -1U; if (tag.empty()) { return explosionID; } const std::map<std::string, unsigned int>::const_iterator it = explosionIDs.find(tag); if (it == explosionIDs.end()) { CEGData cegData; const LuaTable* root = h->GetExplosionTableRoot(); const LuaTable& expTable = (root != NULL)? root->SubTable(tag): LuaTable(); if (!expTable.IsValid()) { // not a fatal error: any calls to ::Explosion will just return early logOutput.Print("[CCEG::Load] WARNING: table for CEG \"" + tag + "\" invalid (parse errors?)"); return explosionID; } vector<string> spawns; expTable.GetKeys(spawns); for (vector<string>::iterator si = spawns.begin(); si != spawns.end(); ++si) { ProjectileSpawnInfo psi; const string& spawnName = *si; const LuaTable spawnTable = expTable.SubTable(spawnName); if (!spawnTable.IsValid() || spawnName == "groundflash") { continue; } const string className = spawnTable.GetString("class", spawnName); psi.projectileClass = h->projectileClasses.GetClass(className); psi.flags = GetFlagsFromTable(spawnTable); psi.count = spawnTable.GetInt("count", 1); if (psi.projectileClass->binder->flags & creg::CF_Synced) { psi.flags |= SPW_SYNCED; } string code; map<string, string> props; map<string, string>::const_iterator propIt; spawnTable.SubTable("properties").GetMap(props); for (propIt = props.begin(); propIt != props.end(); ++propIt) { creg::Class::Member* m = psi.projectileClass->FindMember(propIt->first.c_str()); if (m && (m->flags & creg::CM_Config)) { ParseExplosionCode(&psi, m->offset, m->type, propIt->second, code); } } code += (char)OP_END; psi.code.resize(code.size()); copy(code.begin(), code.end(), psi.code.begin()); cegData.projectileSpawn.push_back(psi); } const LuaTable gndTable = expTable.SubTable("groundflash"); const int ttl = gndTable.GetInt("ttl", 0); if (ttl > 0) { cegData.groundFlash.circleAlpha = gndTable.GetFloat("circleAlpha", 0.0f); cegData.groundFlash.flashSize = gndTable.GetFloat("flashSize", 0.0f); cegData.groundFlash.flashAlpha = gndTable.GetFloat("flashAlpha", 0.0f); cegData.groundFlash.circleGrowth = gndTable.GetFloat("circleGrowth", 0.0f); cegData.groundFlash.color = gndTable.GetFloat3("color", float3(1.0f, 1.0f, 0.8f)); cegData.groundFlash.flags = SPW_GROUND | GetFlagsFromTable(gndTable); cegData.groundFlash.ttl = ttl; } cegData.useDefaultExplosions = expTable.GetBool("useDefaultExplosions", false); explosionID = explosionData.size(); explosionData.push_back(cegData); explosionIDs[tag] = explosionID; } else { explosionID = it->second; } return explosionID; }
void CCustomExplosionGenerator::Load(CExplosionGeneratorHandler* h, const string& tag) { typedef std::map<string, CEGData> CEGMap; typedef std::map<string, CEGData>::iterator CEGMapIt; CEGMapIt it = cachedCEGs.find(tag); if (it == cachedCEGs.end()) { CEGData cegData; const LuaTable& root = h->GetTable(); const LuaTable expTable = root.SubTable(tag); if (!expTable.IsValid()) { throw content_error("Explosion info for " + tag + " not found."); } vector<string> spawns; expTable.GetKeys(spawns); for (vector<string>::iterator si = spawns.begin(); si != spawns.end(); ++si) { ProjectileSpawnInfo psi; const string& spawnName = *si; const LuaTable spawnTable = expTable.SubTable(spawnName); if (!spawnTable.IsValid() || spawnName == "groundflash") { continue; } const string className = spawnTable.GetString("class", spawnName); psi.projectileClass = h->projectileClasses.GetClass(className); psi.flags = GetFlagsFromTable(spawnTable); psi.count = spawnTable.GetInt("count", 1); if (psi.projectileClass->binder->flags & creg::CF_Synced) { psi.flags |= SPW_SYNCED; } string code; map<string, string> props; map<string, string>::const_iterator propIt; spawnTable.SubTable("properties").GetMap(props); for (propIt = props.begin(); propIt != props.end(); ++propIt) { creg::Class::Member* m = psi.projectileClass->FindMember(propIt->first.c_str()); if (m && (m->flags & creg::CM_Config)) { ParseExplosionCode(&psi, m->offset, m->type, propIt->second, code); } } code += (char)OP_END; psi.code.resize(code.size()); copy(code.begin(), code.end(), psi.code.begin()); cegData.projectileSpawn.push_back(psi); } const LuaTable gndTable = expTable.SubTable("groundflash"); const int ttl = gndTable.GetInt("ttl", 0); if (ttl > 0) { cegData.groundFlash.circleAlpha = gndTable.GetFloat("circleAlpha", 0.0f); cegData.groundFlash.flashSize = gndTable.GetFloat("flashSize", 0.0f); cegData.groundFlash.flashAlpha = gndTable.GetFloat("flashAlpha", 0.0f); cegData.groundFlash.circleGrowth = gndTable.GetFloat("circleGrowth", 0.0f); cegData.groundFlash.color = gndTable.GetFloat3("color", float3(1.0f, 1.0f, 0.8f)); cegData.groundFlash.flags = SPW_GROUND | GetFlagsFromTable(gndTable); cegData.groundFlash.ttl = ttl; } cegData.useDefaultExplosions = expTable.GetBool("useDefaultExplosions", false); it = cachedCEGs.insert(std::make_pair(tag, cegData)).first; } currentCEG = it; }