int LuaArchive::GetArchiveInfo(lua_State* L) { const std::string archiveName = luaL_checksstring(L, 1); CArchiveScanner::ArchiveData archiveData = archiveScanner->GetArchiveData(archiveName); if (archiveData.IsEmpty()) { return 0; } lua_createtable(L, 0, archiveData.GetInfo().size()); for (const auto& pair: archiveData.GetInfo()) { const std::string& itemName = pair.first; const InfoItem& itemData = pair.second; lua_pushsstring(L, itemName); switch (itemData.valueType) { case INFO_VALUE_TYPE_STRING: { lua_pushsstring(L, itemData.valueTypeString); } break; case INFO_VALUE_TYPE_INTEGER: { lua_pushinteger(L, itemData.value.typeInteger); } break; case INFO_VALUE_TYPE_FLOAT: { lua_pushnumber(L, itemData.value.typeFloat); } break; case INFO_VALUE_TYPE_BOOL: { lua_pushboolean(L, itemData.value.typeBool); } break; default: assert(false); } lua_rawset(L, -3); } return 1; }
int LuaArchive::HasArchive(lua_State* L) { const std::string archiveName = luaL_checksstring(L, 1); CArchiveScanner::ArchiveData archiveData = archiveScanner->GetArchiveData(archiveName); lua_pushboolean(L, !archiveData.IsEmpty()); return 1; }
int LuaArchive::GetArchiveReplaces(lua_State* L) { const std::string archiveName = luaL_checksstring(L, 1); CArchiveScanner::ArchiveData archiveData = archiveScanner->GetArchiveData(archiveName); if (archiveData.IsEmpty()) { return 0; } const std::vector<std::string>& replaces = archiveData.GetReplaces(); unsigned int count = 0; lua_createtable(L, replaces.size(), 0); for (const std::string& replace: replaces) { lua_pushsstring(L, replace); lua_rawseti(L, -2, ++count); } return 1; }
static bool archNameCompare(const CArchiveScanner::ArchiveData& a, const CArchiveScanner::ArchiveData& b) { return (a.GetName() < b.GetName()); }
void CModInfo::Init(const char* modArchive) { filename = modArchive; humanNameVersioned = archiveScanner->NameFromArchive(modArchive); const CArchiveScanner::ArchiveData md = archiveScanner->GetArchiveData(humanNameVersioned); humanName = md.GetName(); shortName = md.GetShortName(); version = md.GetVersion(); mutator = md.GetMutator(); description = md.GetDescription(); // initialize the parser LuaParser parser("gamedata/modrules.lua", SPRING_VFS_MOD_BASE, SPRING_VFS_ZIP); // customize the defs environment parser.GetTable("Spring"); parser.AddFunc("GetModOptions", LuaSyncedRead::GetModOptions); parser.EndTable(); parser.Execute(); if (!parser.IsValid()) { LOG_L(L_ERROR, "Failed loading mod-rules, using defaults; error: %s", parser.GetErrorLog().c_str()); } const LuaTable& root = parser.GetRoot(); { // system const LuaTable& system = root.SubTable("system"); const size_t numThreads = std::max(0, configHandler->GetInt("MultiThreadCount")); bool disableGML = (numThreads == 1); pathFinderSystem = system.GetInt("pathFinderSystem", PFS_TYPE_DEFAULT) % PFS_NUM_TYPES; luaThreadingModel = system.GetInt("luaThreadingModel", MT_LUA_SINGLE_BATCH); //FIXME: remove unsave modes if (luaThreadingModel > 2) { LOG_L(L_WARNING, "Experimental luaThreadingModel %d selected! This is currently unmaintained and may be deprecated and/or removed in the future!", luaThreadingModel); LOG_L(L_WARNING, "Automaticly disabled to prevent desyncs / crashes / hangs / graphical errors!"); if (!configHandler->GetBool("EnableUnsafeAndBrokenMT")) { luaThreadingModel = 2; } else { LOG_L(L_WARNING, "MT enforced: expect desyncs / crashes / hangs / graphical errors!"); } } if (numThreads == 0) { disableGML |= (Threading::GetAvailableCores() <= 1 ); disableGML |= (luaThreadingModel == MT_LUA_NONE ); disableGML |= (luaThreadingModel == MT_LUA_SINGLE ); disableGML |= (luaThreadingModel == MT_LUA_SINGLE_BATCH); } if (disableGML) { // single core, or this game did not make any effort to // specifically support MT ==> disable it by default GML::Enable(false); } GML::SetCheckCallChain(globalConfig->GetMultiThreadLua() == MT_LUA_SINGLE_BATCH); } { // movement const LuaTable& movementTbl = root.SubTable("movement"); allowAircraftToLeaveMap = movementTbl.GetBool("allowAirPlanesToLeaveMap", true); allowAircraftToHitGround = movementTbl.GetBool("allowAircraftToHitGround", true); allowPushingEnemyUnits = movementTbl.GetBool("allowPushingEnemyUnits", false); allowCrushingAlliedUnits = movementTbl.GetBool("allowCrushingAlliedUnits", false); allowUnitCollisionDamage = movementTbl.GetBool("allowUnitCollisionDamage", false); allowUnitCollisionOverlap = movementTbl.GetBool("allowUnitCollisionOverlap", true); allowGroundUnitGravity = movementTbl.GetBool("allowGroundUnitGravity", true); allowHoverUnitStrafing = movementTbl.GetBool("allowHoverUnitStrafing", (pathFinderSystem == PFS_TYPE_QTPFS)); useClassicGroundMoveType = movementTbl.GetBool("useClassicGroundMoveType", false); } { // construction const LuaTable& constructionTbl = root.SubTable("construction"); constructionDecay = constructionTbl.GetBool("constructionDecay", true); constructionDecayTime = (int)(constructionTbl.GetFloat("constructionDecayTime", 6.66) * GAME_SPEED); constructionDecaySpeed = std::max(constructionTbl.GetFloat("constructionDecaySpeed", 0.03), 0.01f); } { // reclaim const LuaTable& reclaimTbl = root.SubTable("reclaim"); multiReclaim = reclaimTbl.GetInt("multiReclaim", 0); reclaimMethod = reclaimTbl.GetInt("reclaimMethod", 1); reclaimUnitMethod = reclaimTbl.GetInt("unitMethod", 1); reclaimUnitEnergyCostFactor = reclaimTbl.GetFloat("unitEnergyCostFactor", 0.0); reclaimUnitEfficiency = reclaimTbl.GetFloat("unitEfficiency", 1.0); reclaimFeatureEnergyCostFactor = reclaimTbl.GetFloat("featureEnergyCostFactor", 0.0); reclaimAllowEnemies = reclaimTbl.GetBool("allowEnemies", true); reclaimAllowAllies = reclaimTbl.GetBool("allowAllies", true); } { // repair const LuaTable& repairTbl = root.SubTable("repair"); repairEnergyCostFactor = repairTbl.GetFloat("energyCostFactor", 0.0); } { // resurrect const LuaTable& resurrectTbl = root.SubTable("resurrect"); resurrectEnergyCostFactor = resurrectTbl.GetFloat("energyCostFactor", 0.5); } { // capture const LuaTable& captureTbl = root.SubTable("capture"); captureEnergyCostFactor = captureTbl.GetFloat("energyCostFactor", 0.0); } { // paralyze const LuaTable& paralyzeTbl = root.SubTable("paralyze"); paralyzeOnMaxHealth = paralyzeTbl.GetBool("paralyzeOnMaxHealth", true); } { // fire-at-dead-units const LuaTable& fireAtDeadTbl = root.SubTable("fireAtDead"); fireAtKilled = fireAtDeadTbl.GetBool("fireAtKilled", false); fireAtCrashing = fireAtDeadTbl.GetBool("fireAtCrashing", false); } { // transportability const LuaTable& transportTbl = root.SubTable("transportability"); transportAir = transportTbl.GetBool("transportAir", false); transportShip = transportTbl.GetBool("transportShip", false); transportHover = transportTbl.GetBool("transportHover", false); transportGround = transportTbl.GetBool("transportGround", true); targetableTransportedUnits = transportTbl.GetBool("targetableTransportedUnits", false); } { // experience const LuaTable& experienceTbl = root.SubTable("experience"); CUnit::SetExpMultiplier (experienceTbl.GetFloat("experienceMult", 1.0f)); CUnit::SetExpPowerScale (experienceTbl.GetFloat("powerScale", 1.0f)); CUnit::SetExpHealthScale(experienceTbl.GetFloat("healthScale", 0.7f)); CUnit::SetExpReloadScale(experienceTbl.GetFloat("reloadScale", 0.4f)); } { // flanking bonus const LuaTable& flankingBonusTbl = root.SubTable("flankingBonus"); flankingBonusModeDefault = flankingBonusTbl.GetInt("defaultMode", 1); } { // feature visibility const LuaTable& featureLOS = root.SubTable("featureLOS"); featureVisibility = featureLOS.GetInt("featureVisibility", FEATURELOS_ALL); featureVisibility = Clamp(featureVisibility, int(FEATURELOS_NONE), int(FEATURELOS_ALL)); } { // sensors, line-of-sight const LuaTable& sensors = root.SubTable("sensors"); const LuaTable& los = sensors.SubTable("los"); requireSonarUnderWater = sensors.GetBool("requireSonarUnderWater", true); // losMipLevel is used as index to readMap->mipHeightmaps, // so the max value is CReadMap::numHeightMipMaps - 1 losMipLevel = los.GetInt("losMipLevel", 1); losMul = los.GetFloat("losMul", 1.0f); // airLosMipLevel doesn't have such restrictions, it's just used in various // bitshifts with signed integers airMipLevel = los.GetInt("airMipLevel", 2); airLosMul = los.GetFloat("airLosMul", 1.0f); if ((losMipLevel < 0) || (losMipLevel > 6)) { throw content_error("Sensors\\Los\\LosMipLevel out of bounds. " "The minimum value is 0. The maximum value is 6."); } if ((airMipLevel < 0) || (airMipLevel > 30)) { throw content_error("Sensors\\Los\\AirLosMipLevel out of bounds. " "The minimum value is 0. The maximum value is 30."); } } }
void CModInfo::Init(const char* modArchive) { filename = modArchive; humanNameVersioned = archiveScanner->NameFromArchive(modArchive); const CArchiveScanner::ArchiveData md = archiveScanner->GetArchiveData(humanNameVersioned); humanName = md.GetName(); shortName = md.GetShortName(); version = md.GetVersion(); mutator = md.GetMutator(); description = md.GetDescription(); // initialize the parser LuaParser parser("gamedata/modrules.lua", SPRING_VFS_MOD_BASE, SPRING_VFS_ZIP); // customize the defs environment parser.GetTable("Spring"); parser.AddFunc("GetModOptions", LuaSyncedRead::GetModOptions); parser.EndTable(); parser.Execute(); if (!parser.IsValid()) { LOG_L(L_ERROR, "Failed loading mod-rules, using defaults; error: %s", parser.GetErrorLog().c_str()); } const LuaTable& root = parser.GetRoot(); { // system const LuaTable& system = root.SubTable("system"); pathFinderSystem = system.GetInt("pathFinderSystem", PFS_TYPE_DEFAULT) % PFS_NUM_TYPES; } { // movement const LuaTable& movementTbl = root.SubTable("movement"); allowAircraftToLeaveMap = movementTbl.GetBool("allowAirPlanesToLeaveMap", true); allowAircraftToHitGround = movementTbl.GetBool("allowAircraftToHitGround", true); allowPushingEnemyUnits = movementTbl.GetBool("allowPushingEnemyUnits", false); allowCrushingAlliedUnits = movementTbl.GetBool("allowCrushingAlliedUnits", false); allowUnitCollisionDamage = movementTbl.GetBool("allowUnitCollisionDamage", false); allowUnitCollisionOverlap = movementTbl.GetBool("allowUnitCollisionOverlap", true); allowGroundUnitGravity = movementTbl.GetBool("allowGroundUnitGravity", true); allowHoverUnitStrafing = movementTbl.GetBool("allowHoverUnitStrafing", (pathFinderSystem == PFS_TYPE_QTPFS)); useClassicGroundMoveType = movementTbl.GetBool("useClassicGroundMoveType", false); } { // construction const LuaTable& constructionTbl = root.SubTable("construction"); constructionDecay = constructionTbl.GetBool("constructionDecay", true); constructionDecayTime = (int)(constructionTbl.GetFloat("constructionDecayTime", 6.66) * GAME_SPEED); constructionDecaySpeed = std::max(constructionTbl.GetFloat("constructionDecaySpeed", 0.03), 0.01f); } { // reclaim const LuaTable& reclaimTbl = root.SubTable("reclaim"); multiReclaim = reclaimTbl.GetInt("multiReclaim", 0); reclaimMethod = reclaimTbl.GetInt("reclaimMethod", 1); reclaimUnitMethod = reclaimTbl.GetInt("unitMethod", 1); reclaimUnitEnergyCostFactor = reclaimTbl.GetFloat("unitEnergyCostFactor", 0.0); reclaimUnitEfficiency = reclaimTbl.GetFloat("unitEfficiency", 1.0); reclaimFeatureEnergyCostFactor = reclaimTbl.GetFloat("featureEnergyCostFactor", 0.0); reclaimAllowEnemies = reclaimTbl.GetBool("allowEnemies", true); reclaimAllowAllies = reclaimTbl.GetBool("allowAllies", true); } { // repair const LuaTable& repairTbl = root.SubTable("repair"); repairEnergyCostFactor = repairTbl.GetFloat("energyCostFactor", 0.0); } { // resurrect const LuaTable& resurrectTbl = root.SubTable("resurrect"); resurrectEnergyCostFactor = resurrectTbl.GetFloat("energyCostFactor", 0.5); } { // capture const LuaTable& captureTbl = root.SubTable("capture"); captureEnergyCostFactor = captureTbl.GetFloat("energyCostFactor", 0.0); } { // paralyze const LuaTable& paralyzeTbl = root.SubTable("paralyze"); paralyzeOnMaxHealth = paralyzeTbl.GetBool("paralyzeOnMaxHealth", true); } { // fire-at-dead-units const LuaTable& fireAtDeadTbl = root.SubTable("fireAtDead"); fireAtKilled = fireAtDeadTbl.GetBool("fireAtKilled", false); fireAtCrashing = fireAtDeadTbl.GetBool("fireAtCrashing", false); } { // transportability const LuaTable& transportTbl = root.SubTable("transportability"); transportAir = transportTbl.GetBool("transportAir", false); transportShip = transportTbl.GetBool("transportShip", false); transportHover = transportTbl.GetBool("transportHover", false); transportGround = transportTbl.GetBool("transportGround", true); targetableTransportedUnits = transportTbl.GetBool("targetableTransportedUnits", false); } { // experience const LuaTable& experienceTbl = root.SubTable("experience"); CUnit::SetExpMultiplier (experienceTbl.GetFloat("experienceMult", 1.0f)); CUnit::SetExpPowerScale (experienceTbl.GetFloat("powerScale", 1.0f)); CUnit::SetExpHealthScale(experienceTbl.GetFloat("healthScale", 0.7f)); CUnit::SetExpReloadScale(experienceTbl.GetFloat("reloadScale", 0.4f)); } { // flanking bonus const LuaTable& flankingBonusTbl = root.SubTable("flankingBonus"); flankingBonusModeDefault = flankingBonusTbl.GetInt("defaultMode", 1); } { // feature visibility const LuaTable& featureLOS = root.SubTable("featureLOS"); featureVisibility = featureLOS.GetInt("featureVisibility", FEATURELOS_ALL); featureVisibility = Clamp(featureVisibility, int(FEATURELOS_NONE), int(FEATURELOS_ALL)); } { // sensors, line-of-sight const LuaTable& sensors = root.SubTable("sensors"); const LuaTable& los = sensors.SubTable("los"); requireSonarUnderWater = sensors.GetBool("requireSonarUnderWater", true); // losMipLevel is used as index to readMap->mipHeightmaps, // so the max value is CReadMap::numHeightMipMaps - 1 losMipLevel = los.GetInt("losMipLevel", 1); losMul = los.GetFloat("losMul", 1.0f); // airLosMipLevel doesn't have such restrictions, it's just used in various // bitshifts with signed integers airMipLevel = los.GetInt("airMipLevel", 2); airLosMul = los.GetFloat("airLosMul", 1.0f); if ((losMipLevel < 0) || (losMipLevel > 6)) { throw content_error("Sensors\\Los\\LosMipLevel out of bounds. " "The minimum value is 0. The maximum value is 6."); } if ((airMipLevel < 0) || (airMipLevel > 30)) { throw content_error("Sensors\\Los\\AirLosMipLevel out of bounds. " "The minimum value is 0. The maximum value is 30."); } } }
void CModInfo::Init(const char* modArchive) { filename = modArchive; humanName = archiveScanner->NameFromArchive(modArchive); const CArchiveScanner::ArchiveData md = archiveScanner->GetArchiveData(humanName); shortName = md.GetShortName(); version = md.GetVersion(); mutator = md.GetMutator(); description = md.GetDescription(); // initialize the parser LuaParser parser("gamedata/modrules.lua", SPRING_VFS_MOD_BASE, SPRING_VFS_ZIP); // customize the defs environment parser.GetTable("Spring"); parser.AddFunc("GetModOptions", LuaSyncedRead::GetModOptions); parser.EndTable(); parser.Execute(); if (!parser.IsValid()) { LOG_L(L_ERROR, "Failed loading mod-rules, using defaults; error: %s", parser.GetErrorLog().c_str()); } const LuaTable root = parser.GetRoot(); // determine if bombers are allowed to leave map boundaries const LuaTable movementTbl = root.SubTable("movement"); allowAirPlanesToLeaveMap = movementTbl.GetBool("allowAirPlanesToLeaveMap", true); allowPushingEnemyUnits = movementTbl.GetBool("allowPushingEnemyUnits", false); // determine whether the modder allows the user to use team coloured nanospray const LuaTable nanosprayTbl = root.SubTable("nanospray"); allowTeamColors = nanosprayTbl.GetBool("allow_team_colors", true); if (allowTeamColors) { // Load the users preference for team coloured nanospray globalRendering->teamNanospray = configHandler->GetBool("TeamNanoSpray"); } // constructions const LuaTable constructionTbl = root.SubTable("construction"); constructionDecay = constructionTbl.GetBool("constructionDecay", true); constructionDecayTime = (int)(constructionTbl.GetFloat("constructionDecayTime", 6.66) * 30); constructionDecaySpeed = constructionTbl.GetFloat("constructionDecaySpeed", 0.03); // reclaim const LuaTable reclaimTbl = root.SubTable("reclaim"); multiReclaim = reclaimTbl.GetInt("multiReclaim", 0); reclaimMethod = reclaimTbl.GetInt("reclaimMethod", 1); reclaimUnitMethod = reclaimTbl.GetInt("unitMethod", 1); reclaimUnitEnergyCostFactor = reclaimTbl.GetFloat("unitEnergyCostFactor", 0.0); reclaimUnitEfficiency = reclaimTbl.GetFloat("unitEfficiency", 1.0); reclaimFeatureEnergyCostFactor = reclaimTbl.GetFloat("featureEnergyCostFactor", 0.0); reclaimAllowEnemies = reclaimTbl.GetBool("allowEnemies", true); reclaimAllowAllies = reclaimTbl.GetBool("allowAllies", true); // repair const LuaTable repairTbl = root.SubTable("repair"); repairEnergyCostFactor = repairTbl.GetFloat("energyCostFactor", 0.0); // resurrect const LuaTable resurrectTbl = root.SubTable("resurrect"); resurrectEnergyCostFactor = resurrectTbl.GetFloat("energyCostFactor", 0.5); // capture const LuaTable captureTbl = root.SubTable("capture"); captureEnergyCostFactor = captureTbl.GetFloat("energyCostFactor", 0.0); // paralyze const LuaTable paralyzeTbl = root.SubTable("paralyze"); paralyzeOnMaxHealth = paralyzeTbl.GetBool("paralyzeOnMaxHealth", true); // fire-at-dead-units const LuaTable fireAtDeadTbl = root.SubTable("fireAtDead"); fireAtKilled = fireAtDeadTbl.GetBool("fireAtKilled", false); fireAtCrashing = fireAtDeadTbl.GetBool("fireAtCrashing", false); // transportability const LuaTable transportTbl = root.SubTable("transportability"); transportAir = transportTbl.GetInt("transportAir", false); transportShip = transportTbl.GetInt("transportShip", false); transportHover = transportTbl.GetInt("transportHover", false); transportGround = transportTbl.GetInt("transportGround", true); // experience const LuaTable experienceTbl = root.SubTable("experience"); CUnit::SetExpMultiplier (experienceTbl.GetFloat("experienceMult", 1.0f)); CUnit::SetExpPowerScale (experienceTbl.GetFloat("powerScale", 1.0f)); CUnit::SetExpHealthScale(experienceTbl.GetFloat("healthScale", 0.7f)); CUnit::SetExpReloadScale(experienceTbl.GetFloat("reloadScale", 0.4f)); // flanking bonus const LuaTable flankingBonusTbl = root.SubTable("flankingBonus"); flankingBonusModeDefault = flankingBonusTbl.GetInt("defaultMode", 1); // feature visibility const LuaTable featureLOS = root.SubTable("featureLOS"); featureVisibility = featureLOS.GetInt("featureVisibility", 3); if (featureVisibility < 0 || featureVisibility > 3) throw content_error("invalid modinfo: featureVisibility, valid range is 0..3"); // sensors const LuaTable sensors = root.SubTable("sensors"); requireSonarUnderWater = sensors.GetBool("requireSonarUnderWater", true); /// LoS const LuaTable los = sensors.SubTable("los"); // losMipLevel is used as index to readmap->mipHeightmaps, // so the max value is CReadMap::numHeightMipMaps - 1 losMipLevel = los.GetInt("losMipLevel", 1); losMul = los.GetFloat("losMul", 1.0f); if ((losMipLevel < 0) || (losMipLevel > 6)) { throw content_error("Sensors\\Los\\LosMipLevel out of bounds. " "The minimum value is 0. The maximum value is 6."); } // airLosMipLevel doesn't have such restrictions, it's just used in various // bitshifts with signed integers airMipLevel = los.GetInt("airMipLevel", 2); if ((airMipLevel < 0) || (airMipLevel > 30)) { throw content_error("Sensors\\Los\\AirLosMipLevel out of bounds. " "The minimum value is 0. The maximum value is 30."); } airLosMul = los.GetFloat("airLosMul", 1.0f); const LuaTable system = root.SubTable("system"); luaThreadingModel = system.GetInt("luaThreadingModel", MT_LUA_SINGLE_BATCH); }