public WdTank(string id, JsonDict json, WdCountry country, WdData data) { RawId = id; Country = country; Raw = json; var tags1 = Raw["tags"].WdString().Split("\r\n").Select(s => s.Trim()).ToHashSet(); var tags2 = Raw["tags"].WdString().Split(' ').Select(s => s.Trim()).ToHashSet(); Tags = tags1.Count > tags2.Count ? tags1 : tags2; NotInShop = Raw.ContainsKey("notInShop") && Raw["notInShop"].GetBool(); Price = Raw["price"] is JsonDict ? Raw["price"][""].WdInt() : Raw["price"].WdInt(); Gold = Raw["price"] is JsonDict && Raw["price"].ContainsKey("gold"); if (Tags.Contains("lightTank")) { Class = "lightTank"; } else if (Tags.Contains("mediumTank")) { Class = "mediumTank"; } else if (Tags.Contains("heavyTank")) { Class = "heavyTank"; } else if (Tags.Contains("SPG")) { Class = "SPG"; } else if (Tags.Contains("AT-SPG")) { Class = "AT-SPG"; } else { Class = null; } Tier = Raw["level"].WdInt(); Secret = Tags.Contains("secret"); string scriptsFolder = string.IsNullOrEmpty(data.VersionConfig.PathSourceScripts) ? @"res\scripts" : data.VersionConfig.PathSourceScripts; var path = WotFileExporter.CombinePaths(data.Installation.Path, scriptsFolder, @"item_defs\vehicles\{0}\{1}.xml".Fmt(Country.Name, id)); using (var stream = WotFileExporter.GetFileStream(path)) { RawExtra = BxmlReader.ReadFile(stream); } FullName = data.ResolveString(Raw["userString"].WdString()); ShortName = Raw.ContainsKey("shortUserString") ? data.ResolveString(Raw["shortUserString"].WdString()) : FullName; Description = data.ResolveString(Raw["description"].WdString()); MaxSpeedForward = RawExtra["speedLimits"]["forward"].WdDecimal(); MaxSpeedReverse = RawExtra["speedLimits"]["backward"].WdDecimal(); RepairCost = RawExtra["repairCost"].WdDecimal(); Hull = new WdHull(RawExtra["hull"].GetDict()); Chassis = new List <WdChassis>(); Turrets = new List <WdTurret>(); Engines = new List <WdEngine>(); Radios = new List <WdRadio>(); // these lists are populated once all the tanks are loaded, since some shared modules occur before the non-shared "definition" of the module. foreach (var kvp in RawExtra["chassis"].GetDict()) { if (kvp.Value.GetStringLenientSafe() != "shared" && kvp.Value.Safe[""].GetStringSafe() != "shared" && !kvp.Value.ContainsKey("shared")) { Country.Chassis.Add(kvp.Key, new WdChassis(kvp.Key, kvp.Value.GetDict(), data)); } } foreach (var kvp in RawExtra["turrets0"].GetDict()) { if (kvp.Value.GetStringLenientSafe() != "shared" && kvp.Value.Safe[""].GetStringSafe() != "shared" && !kvp.Value.ContainsKey("shared")) { Country.Turrets.Add(kvp.Key, new WdTurret(kvp.Key, kvp.Value.GetDict(), data)); } } // RawExtra["engines"] and RawExtra["radios"] only contain information about unlocks; the rest is contained in separate files parsed in WdCountry. }
public WdData(GameInstallation installation, GameVersionConfig versionConfig) { Countries = new Dictionary <string, WdCountry>(); Warnings = new List <string>(); Installation = installation; VersionConfig = versionConfig; IList <string> countries = new[] { "ussr", "germany", "usa", "france", "china", "uk", "japan", "czech", "sweden", "poland" }; countries = countries.Where( c => WotFileExporter.Exists(WotFileExporter.CombinePaths(installation.Path, versionConfig.PathVehicleList.Replace(@"""Country""", c)))).ToList(); string scriptsFolder = string.IsNullOrEmpty(versionConfig.PathSourceScripts) ? @"res\scripts" : versionConfig.PathSourceScripts; foreach (var country in countries) { JsonDict tanks, engines, guns, radios, shells; string path; path = WotFileExporter.CombinePaths(installation.Path, versionConfig.PathVehicleList.Replace(@"""Country""", country)); try { using (var stream = WotFileExporter.GetFileStream(path)) { tanks = BxmlReader.ReadFile(stream); } } catch (Exception e) { throw new WotDataException("Couldn't read vehicle list for country \"{0}\" from file \"{1}\"".Fmt(country, path), e); } path = WotFileExporter.CombinePaths(installation.Path, scriptsFolder, @"item_defs\vehicles\{0}\components\engines.xml").Fmt(country); try { using (var stream = WotFileExporter.GetFileStream(path)) { engines = BxmlReader.ReadFile(stream); } } catch (Exception e) { throw new WotDataException("Couldn't read engines data for country \"{0}\" from file \"{1}\"".Fmt(country, path), e); } path = WotFileExporter.CombinePaths(installation.Path, scriptsFolder, @"item_defs\vehicles\{0}\components\guns.xml").Fmt(country); try { using (var stream = WotFileExporter.GetFileStream(path)) { guns = BxmlReader.ReadFile(stream); } } catch (Exception e) { throw new WotDataException("Couldn't read guns data for country \"{0}\" from file \"{1}\"".Fmt(country, path), e); } path = WotFileExporter.CombinePaths(installation.Path, scriptsFolder, @"item_defs\vehicles\{0}\components\radios.xml").Fmt(country); try { using (var stream = WotFileExporter.GetFileStream(path)) { radios = BxmlReader.ReadFile(stream); } } catch (Exception e) { throw new WotDataException("Couldn't read radios data for country \"{0}\" from file \"{1}\"".Fmt(country, path), e); } path = WotFileExporter.CombinePaths(installation.Path, scriptsFolder, @"item_defs\vehicles\{0}\components\shells.xml").Fmt(country); try { using (var stream = WotFileExporter.GetFileStream(path)) { shells = BxmlReader.ReadFile(stream); } } catch (Exception e) { throw new WotDataException("Couldn't read shells data for country \"{0}\" from file \"{1}\"".Fmt(country, path), e); } // Nothing interesting in these: //chassis = BxmlReader.ReadFile(ZipFileExporter.CombinePaths(installation.Path, scriptsFolder, @"item_defs\vehicles\{0}\components\chassis.xml").Fmt(country)); //turrets = BxmlReader.ReadFile(ZipFileExporter.CombinePaths(installation.Path, scriptsFolder, @"item_defs\vehicles\{0}\components\turrets.xml").Fmt(country)); // Observe that these are the exact same pieces of information that are available directly in the vehicle definition (parsed in WdTank) try { Countries.Add(country, new WdCountry(country, this, tanks, engines, guns, radios, shells)); } catch (Exception e) { throw new WotDataException("Could not parse game data for country \"{0}\"".Fmt(country), e); } } foreach (var country in Countries.Values) { // Link all the modules to each tank foreach (var tank in country.Tanks.Values) { foreach (var key in tank.RawExtra["chassis"].GetDict().Keys) { tank.Chassis.Add(country.Chassis[key]); } foreach (var key in tank.RawExtra["turrets0"].GetDict().Keys) { tank.Turrets.Add(country.Turrets[key]); } foreach (var key in tank.RawExtra["engines"].GetDict().Keys) { tank.Engines.Add(country.Engines[key]); } foreach (var key in tank.RawExtra["radios"].GetDict().Keys) { if (key != "") { tank.Radios.Add(country.Radios[key]); } } } // Guns are a bit weird; it appears that there's a base definition + turret-specific overrides. foreach (var turret in country.Turrets.Values) { foreach (var kvp in turret.Raw["guns"].GetDict()) { if (!country.Guns.ContainsKey(kvp.Key)) { Warnings.Add("Could not complete gun loading for turret “{0}”, gun “{1}”.".Fmt(turret.Id, kvp.Key)); continue; } var gun = country.Guns[kvp.Key].Clone(); gun.UpdateFrom(kvp.Value.GetDict(), country); if (turret.Raw.ContainsKey("yawLimits")) // earlier game versions have this data in the turret record { var parts = turret.Raw["yawLimits"].WdString().Split(' ').Select(x => decimal.Parse(x, NumberStyles.Float, CultureInfo.InvariantCulture)).ToArray(); gun.YawLeftLimit = parts[0]; // not too sure about which is which gun.YawRightLimit = parts[1]; } turret.Guns.Add(gun); } } // Validate that the guns loaded fully foreach (var gun in country.Guns.Values) { try { gun.Validate(); } catch (Exception e) { Warnings.Add("Incomplete data for gun “{0}”: {1}".Fmt(gun.Id, e.Message)); } } } // Clear the string data, since it's no longer needed _moFiles.Clear(); _moFiles = null; }