public override IEnumerable <IModObject> Load(Mod mod) { foreach (var rec in DataFile.Records) { var m = new Mount(); m.TemplateParameters = rec.Parameters; mod.Mounts.Add(m); m.ModID = rec.Get <string>("ID", m); m.Name = rec.Get <string>("Long Name", m); m.ShortName = rec.Get <string>("Short Name", m) ?? m.Name; // default to long name m.Description = rec.Get <string>("Description", m); m.Code = rec.Get <string>("Code", m); m.PictureName = rec.Get <string>("Pic", m); m.CostPercent = rec.Get <int>("Cost Percent", m) ?? 100; m.SizePercent = rec.Get <int>("Tonnage Percent", m) ?? 100; m.DurabilityPercent = rec.Get <int>("Tonnage Structure Percent", m) ?? 100; m.WeaponDamagePercent = rec.Get <int>("Damage Percent", m) ?? 100; m.SupplyUsagePercent = rec.Get <int>("Supply Percent", m) ?? 100; m.WeaponRangeModifier = rec.Get <int>("Range Modifier", m) ?? 0; m.WeaponAccuracyModifier = rec.Get <int>("Weapon To Hit Modifier", m) ?? 0; m.MinimumVehicleSize = rec.Get <int>("Vehicle Size Minimum", m); m.MaximumVehicleSize = rec.Get <int>("Vehicle Size Maximum", m); m.RequiredComponentFamily = rec.Get <string>(new string[] { "Comp Family Requirement", "Component Family Requirement", "Comp Family", "Component Family" }, m); var wtstring = rec.Get <string>(new string[] { "Weapon Type Requirement", "Weapon Type" }, m); if (wtstring == null) { m.WeaponTypes = WeaponTypes.AnyComponent; } else { m.WeaponTypes = wtstring.Value.Capitalize().ParseEnum <WeaponTypes>(); } var vtstring = rec.Get <string>(new string[] { "Vehicle Type", "Vehicle Type Requirement" }, m); if (vtstring == null) { m.VehicleTypes = VehicleTypes.All; } else { m.VehicleTypes = vtstring.Value.Capitalize().ParseEnum <VehicleTypes>(); } m.AbilityPercentages = AbilityLoader.LoadPercentagesOrModifiers(rec, "Percent", m); m.AbilityModifiers = AbilityLoader.LoadPercentagesOrModifiers(rec, "Modifier", m); m.UnlockRequirements = RequirementLoader.LoadEmpireRequirements(rec, m, RequirementType.Unlock).ToList(); // TODO - build and use requirements yield return(m); } }
public override IEnumerable <IModObject> Load(Mod mod) { foreach (var rec in DataFile.Records) { var f = new FacilityTemplate(); f.TemplateParameters = rec.Parameters; mod.FacilityTemplates.Add(f); int index = -1; f.ModID = rec.Get <string>("ID", f); f.Name = rec.Get <string>("Name", f); f.Description = rec.Get <string>("Description", f); f.Group = rec.Get <string>("Facility Group", f); f.Family = rec.Get <string>("Facility Family", f); f.RomanNumeral = rec.Get <int>("Roman Numeral", f); var picfield = rec.FindField("Pic", ref index, false, 0, true); if (picfield != null) { f.PictureName = picfield.Value; } else { f.PictureName = "Facil_" + rec.Get <int>("Pic Num", f).Value.ToString("000"); // for compatibility with SE4 } foreach (var costfield in rec.Fields.Where(cf => cf.Name.StartsWith("Cost "))) { f.Cost[Resource.Find(costfield.Name.Substring("Cost ".Length))] = costfield.CreateFormula <int>(f); } foreach (var tr in RequirementLoader.LoadEmpireRequirements(rec, f, RequirementType.Unlock)) { f.UnlockRequirements.Add(tr); } // TODO - build and use requirements foreach (var abil in AbilityLoader.Load(Filename, rec, f).ToArray()) { f.Abilities.Add(abil); } yield return(f); } }
public override IEnumerable <IModObject> Load(Mod mod) { foreach (var rec in DataFile.Records) { var sst = new StarSystemTemplate(null); sst.TemplateParameters = rec.Parameters; string temp; int index = -1; sst.ModID = rec.Get <string>("ID", sst); rec.TryFindFieldValue("Name", out temp, ref index, Mod.Errors, 0, true); sst.Name = temp; mod.StarSystemTemplates.Add(sst); rec.TryFindFieldValue("Description", out temp, ref index, Mod.Errors, 0, true); sst.Description = temp; sst.Radius = rec.Get <int>("Radius") ?? 6; rec.TryFindFieldValue("Background Bitmap", out temp, ref index, Mod.Errors, 0, true); sst.BackgroundImagePath = Path.GetFileNameWithoutExtension(temp); // so we can use PNG when SE4 specifies BMP files rec.TryFindFieldValue("Empires Can Start In", out temp, ref index, Mod.Errors, 0, true); sst.EmpiresCanStartIn = bool.Parse(temp); rec.TryFindFieldValue("Non-Tiled Center Pic", out temp, ref index, Mod.Errors, 0, true); sst.NonTiledCenterCombatImage = bool.Parse(temp); foreach (var abil in AbilityLoader.Load(Filename, rec, sst)) { sst.Abilities.Add(abil); } sst.WarpPointAbilities = Mod.Current.StellarAbilityTemplates.FindByName(rec.Get <string>("WP Stellar Abil Type", sst)); int count = 0; int start = 0; while (true) { count++; string sobjtype; string pos; if (!rec.TryFindFieldValue(new string[] { "Obj " + count + " Physical Type", "Obj Physical Type" }, out temp, ref start, null, start, true)) { break; // couldn't load next stellar object template } else { sobjtype = temp; } start++; if (!rec.TryFindFieldValue(new string[] { "Obj " + count + " Position", "Obj Position" }, out temp, ref start, null, start)) { Mod.Errors.Add(new DataParsingException("Could not find \"Obj Position\" field.", Mod.CurrentFileName, rec)); continue; // skip this stellar object } else { pos = temp; } start++; ITemplate <StellarObject> sobjTemplate; if (sobjtype == "Star" || sobjtype == "Destroyed Star") { var template = new StarTemplate(); if (sobjtype == "DestroyedStar") { template.IsDestroyed = true; } if (!rec.TryFindFieldValue(new string[] { "Obj " + count + " Stellar Abil Type", "Obj Stellar Abil Type" }, out temp, ref start, null, start, true)) { Mod.Errors.Add(new DataParsingException("Could not find \"Obj Stellar Abil Type\" field for star.", Mod.CurrentFileName, rec)); continue; // skip this stellar object } else { template.Abilities = mod.StellarAbilityTemplates.FindByName(temp); if (template.Abilities == null) { template.Abilities = new RandomAbilityTemplate(); yield return(template.Abilities); Mod.Errors.Add(new DataParsingException("Could not find stellar ability type \"" + temp + "\" in StellarAbilityTypes.txt.", Mod.CurrentFileName, rec)); } } if (!rec.TryFindFieldValue(new string[] { "Obj " + count + " Size", "Obj Size" }, out temp, ref start, null, start, true)) { Mod.Errors.Add(new DataParsingException("Could not find \"Obj Size\" field for star.", Mod.CurrentFileName, rec)); continue; // skip this stellar object } else { if (temp == "Any") { template.StellarSize = null; } else { try { template.StellarSize = temp.ParseEnum <StellarSize>(); } catch (ArgumentException ex) { Mod.Errors.Add(new DataParsingException("Invalid stellar object size \"" + temp + "\". Must be Tiny, Small, Medium, Large, Huge, or Any.", ex, Mod.CurrentFileName, rec)); continue; // skip this stellar object } } } start++; if (!rec.TryFindFieldValue(new string[] { "Obj " + count + " Age", "Obj Age" }, out temp, ref start, null, start)) { Mod.Errors.Add(new DataParsingException("Could not find \"Obj Age\" field for star.", Mod.CurrentFileName, rec)); continue; // skip this stellar object } else { template.Age = temp == "Any" ? null : temp; } start++; if (!rec.TryFindFieldValue(new string[] { "Obj " + count + " Color", "Obj Color" }, out temp, ref start, null, start)) { Mod.Errors.Add(new DataParsingException("Could not find \"Obj Color\" field for star.", Mod.CurrentFileName, rec)); continue; // skip this stellar object } else { template.Color = temp == "Any" ? null : temp; } start++; if (!rec.TryFindFieldValue(new string[] { "Obj " + count + " Luminosity", "Obj Luminosity" }, out temp, ref start, null, start)) { Mod.Errors.Add(new DataParsingException("Could not find \"Obj Luminosity\" field for star.", Mod.CurrentFileName, rec)); continue; // skip this stellar object } else { template.Brightness = temp == "Any" ? null : temp; } start++; sobjTemplate = template; } else if (sobjtype == "Planet") { var template = new PlanetTemplate(); if (!rec.TryFindFieldValue(new string[] { "Obj " + count + " Stellar Abil Type", "Obj Stellar Abil Type" }, out temp, ref start, null, start, true)) { Mod.Errors.Add(new DataParsingException("Could not find \"Obj Stellar Abil Type\" field for planet.", Mod.CurrentFileName, rec)); continue; // skip this stellar object } else { template.Abilities = mod.StellarAbilityTemplates.FindByName(temp); if (template.Abilities == null) { template.Abilities = new RandomAbilityTemplate(); yield return(template.Abilities); Mod.Errors.Add(new DataParsingException("Could not find stellar ability type \"" + temp + "\" in StellarAbilityTypes.txt.", Mod.CurrentFileName, rec)); } } if (!rec.TryFindFieldValue(new string[] { "Obj " + count + " Size", "Obj Size" }, out temp, ref start, null, start, true)) { Mod.Errors.Add(new DataParsingException("Could not find \"Obj Size\" field for planet.", Mod.CurrentFileName, rec)); continue; // skip this stellar object } else { if (temp == "Any") { template.StellarSize = null; } else { try { template.StellarSize = temp.ParseEnum <Size>(); } catch (ArgumentException ex) { Mod.Errors.Add(new DataParsingException("Invalid stellar object size \"" + temp + "\". Must be Tiny, Small, Medium, Large, Huge, or Any.", ex, Mod.CurrentFileName, rec)); continue; // skip this stellar object } } } start++; if (!rec.TryFindFieldValue(new string[] { "Obj " + count + " Atmosphere", "Obj Atmosphere" }, out temp, ref start, null, start)) { Mod.Errors.Add(new DataParsingException("Could not find \"Obj Atmosphere\" field for planet.", Mod.CurrentFileName, rec)); continue; // skip this stellar object } else { template.Atmosphere = temp == "Any" ? null : temp; } start++; if (!rec.TryFindFieldValue(new string[] { "Obj " + count + " Composition", "Obj Composition" }, out temp, ref start, null, start)) { Mod.Errors.Add(new DataParsingException("Could not find \"Obj Composition\" field for planet.", Mod.CurrentFileName, rec)); continue; // skip this stellar object } else { template.Surface = temp == "Any" ? null : temp; } start++; sobjTemplate = template; } else if (sobjtype == "Asteroids") { var template = new AsteroidFieldTemplate(); if (!rec.TryFindFieldValue(new string[] { "Obj " + count + " Stellar Abil Type", "Obj Stellar Abil Type" }, out temp, ref start, null, start, true)) { Mod.Errors.Add(new DataParsingException("Could not find \"Obj Stellar Abil Type\" field for asteroid field.", Mod.CurrentFileName, rec)); continue; // skip this stellar object } else { template.Abilities = mod.StellarAbilityTemplates.FindByName(temp); if (template.Abilities == null) { template.Abilities = new RandomAbilityTemplate(); yield return(template.Abilities); Mod.Errors.Add(new DataParsingException("Could not find stellar ability type \"" + temp + "\" in StellarAbilityTypes.txt.", Mod.CurrentFileName, rec)); } } if (!rec.TryFindFieldValue(new string[] { "Obj " + count + " Size", "Obj Size" }, out temp, ref start, null, start, true)) { Mod.Errors.Add(new DataParsingException("Could not find \"Obj Size\" field for asteroid field.", Mod.CurrentFileName, rec)); continue; // skip this stellar object } else { if (temp == "Any") { template.StellarSize = null; } else { try { template.StellarSize = (StellarSize)Enum.Parse(typeof(Size), temp); } catch (ArgumentException ex) { Mod.Errors.Add(new DataParsingException("Invalid stellar object size \"" + temp + "\". Must be Tiny, Small, Medium, Large, Huge, or Any.", ex, Mod.CurrentFileName, rec)); continue; // skip this stellar object } } } start++; if (!rec.TryFindFieldValue(new string[] { "Obj " + count + " Atmosphere", "Obj Atmosphere" }, out temp, ref start, null, start)) { Mod.Errors.Add(new DataParsingException("Could not find \"Obj Atmosphere\" field for asteroid field.", Mod.CurrentFileName, rec)); continue; // skip this stellar object } else { template.Atmosphere = temp == "Any" ? null : temp; } start++; if (!rec.TryFindFieldValue(new string[] { "Obj " + count + " Composition", "Obj Composition" }, out temp, ref start, null, start)) { Mod.Errors.Add(new DataParsingException("Could not find \"Obj Composition\" field for asteroid field.", Mod.CurrentFileName, rec)); continue; // skip this stellar object } else { template.Surface = temp == "Any" ? null : temp; } start++; sobjTemplate = template; } else if (sobjtype == "Storm") { var template = new StormTemplate(); if (!rec.TryFindFieldValue(new string[] { "Obj " + count + " Stellar Abil Type", "Obj Stellar Abil Type" }, out temp, ref start, null, start, true)) { Mod.Errors.Add(new DataParsingException("Could not find \"Obj Stellar Abil Type\" field for storm.", Mod.CurrentFileName, rec)); continue; // skip this stellar object } else { template.Abilities = mod.StellarAbilityTemplates.FindByName(temp); if (template.Abilities == null) { template.Abilities = new RandomAbilityTemplate(); yield return(template.Abilities); Mod.Errors.Add(new DataParsingException("Could not find stellar ability type \"" + temp + "\" in StellarAbilityTypes.txt.", Mod.CurrentFileName, rec)); } } if (!rec.TryFindFieldValue(new string[] { "Obj " + count + " Size", "Obj Size" }, out temp, ref start, null, start, true)) { Mod.Errors.Add(new DataParsingException("Could not find \"Obj Size\" field for storm.", Mod.CurrentFileName, rec)); continue; // skip this stellar object } else { if (temp == "Any") { template.Size = null; } else { try { template.Size = temp.ParseEnum <Size>(); } catch (ArgumentException ex) { Mod.Errors.Add(new DataParsingException("Invalid stellar object size \"" + temp + "\". Must be Tiny, Small, Medium, Large, Huge, or Any.", ex, Mod.CurrentFileName, rec)); continue; // skip this stellar object } } } start++; sobjTemplate = template; } else { Mod.Errors.Add(new DataParsingException("Invalid stellar object type \"" + sobjtype + "\". Must be Star, Planet, Asteroids, or Storm.", Mod.CurrentFileName, rec)); continue; } if (pos.StartsWith("Ring ")) { int ring; if (!int.TryParse(pos.Substring("Ring ".Length), out ring)) { Mod.Errors.Add(new DataParsingException("Could not parse stellar object location \"" + pos + "\". Expected integer after Ring.", Mod.CurrentFileName, rec)); continue; } sst.StellarObjectLocations.Add(new RingStellarObjectLocation { Ring = ring, StellarObjectTemplate = sobjTemplate }); } else if (pos.StartsWith("Coord ") || pos.StartsWith("Centered Coord ")) { int x, y; string coordsData; bool isCentered = pos.StartsWith("Centered Coord "); if (isCentered) { coordsData = pos.Substring("Centered Coord ".Length); } else { coordsData = pos.Substring("Coord ".Length); } var splitData = coordsData.Split(','); if (splitData.Length < 2) { Mod.Errors.Add(new DataParsingException("Could not parse stellar object location \"" + pos + "\". Expected two comma separated integers after Coord.", Mod.CurrentFileName, rec)); continue; } if (!int.TryParse(splitData[0].Trim(), out x)) { Mod.Errors.Add(new DataParsingException("Could not parse stellar object location \"" + pos + "\". Expected two comma separated integers after Coord.", Mod.CurrentFileName, rec)); continue; } if (!int.TryParse(splitData[1].Trim(), out y)) { Mod.Errors.Add(new DataParsingException("Could not parse stellar object location \"" + pos + "\". Expected two comma separated integers after Coord.", Mod.CurrentFileName, rec)); continue; } sst.StellarObjectLocations.Add(new CoordStellarObjectLocation { Coordinates = new Point(x, y), UseCenteredCoordinates = isCentered, StellarObjectTemplate = sobjTemplate }); } else if (pos.StartsWith("Same As")) { int idx; if (!int.TryParse(pos.Substring("Same As ".Length), out idx)) { Mod.Errors.Add(new DataParsingException("Could not parse stellar object location \"" + pos + "\". Expected integer after Same As.", Mod.CurrentFileName, rec)); continue; } if (idx > sst.StellarObjectLocations.Count) { Mod.Errors.Add(new DataParsingException("A \"Same As\" stellar object location can reference only previously defined locations.", Mod.CurrentFileName, rec)); continue; } sst.StellarObjectLocations.Add(new SameAsStellarObjectLocation { StarSystemTemplate = sst, TargetIndex = idx, StellarObjectTemplate = sobjTemplate }); } else if (pos.StartsWith("Circle Radius ")) { int radius; if (!int.TryParse(pos.Substring("Circle Radius ".Length), out radius)) { Mod.Errors.Add(new DataParsingException("Could not parse stellar object location \"" + pos + "\". Expected integer after Circle Radius.", Mod.CurrentFileName, rec)); continue; } sst.StellarObjectLocations.Add(new CircleRadiusStellarObjectLocation { Radius = radius, StellarObjectTemplate = sobjTemplate }); } } // replace sight obscuration and other abilities that really should belong to sectors but Aaron reused for star systems // so we don't get them using the same ability and systems inheriting abilities from storms etc. thus affecting the entire system! sst.Abilities.Where(a => a.Rule.Matches("Sector - Sight Obscuration")).SafeForeach(a => a.Rule = AbilityRule.Find("System - Sight Obscuration")); sst.Abilities.Where(a => a.Rule.Matches("Sector - Sensor Interference")).SafeForeach(a => a.Rule = AbilityRule.Find("System - Sensor Interference")); sst.Abilities.Where(a => a.Rule.Matches("Sector - Shield Disruption")).SafeForeach(a => a.Rule = AbilityRule.Find("System - Shield Disruption")); sst.Abilities.Where(a => a.Rule.Matches("Sector - Damage")).SafeForeach(a => a.Rule = AbilityRule.Find("System - Damage")); yield return(sst); } }
public override IEnumerable <IModObject> Load(Mod mod) { foreach (var rec in DataFile.Records) { IHull <IVehicle> hull; var hullname = rec.Get <string>("Name", null); var hulltype = rec.Get <string>("Vehicle Type", null); switch (hulltype) { case "Ship": hull = new Hull <Ship>(); break; case "Base": hull = new Hull <Base>(); break; case "Fighter": hull = new Hull <Fighter>(); break; case "Satellite": hull = new Hull <Satellite>(); break; case "Troop": hull = new Hull <Troop>(); break; case "Drone": hull = new Hull <Drone>(); break; case "Mine": hull = new Hull <Mine>(); break; case "Weapon Platform": hull = new Hull <WeaponPlatform>(); break; default: Mod.Errors.Add(new DataParsingException("Invalid vehicle type \"" + hulltype + "\" specified for " + hullname + " hull.", Mod.CurrentFileName, rec)); continue; } hull.TemplateParameters = rec.Parameters; hull.ModID = rec.Get <string>("ID", hull); hull.Name = hullname; mod.Hulls.Add(hull); hull.ShortName = rec.Get <string>("Short Name", hull); hull.Description = rec.Get <string>("Description", hull); hull.Code = rec.Get <string>("Code", hull); var bitmapfields = rec.Fields.Where(f => f.Name.EndsWith("Bitmap Name")); foreach (var f in bitmapfields) { hull.PictureNames.Add(f.Value); } hull.Size = rec.Get <int>("Tonnage", hull); foreach (var costfield in rec.Fields.Where(cf => cf.Name.StartsWith("Cost "))) { hull.Cost[Resource.Find(costfield.Name.Substring("Cost ".Length))] = costfield.CreateFormula <int>(hull); } hull.ThrustPerMove = rec.Get <int>("Engines Per Move", hull); foreach (var tr in RequirementLoader.LoadEmpireRequirements(rec, hull, RequirementType.Unlock)) { hull.UnlockRequirements.Add(tr); } // TODO - build and use requirements foreach (var abil in AbilityLoader.Load(Filename, rec, hull)) { hull.Abilities.Add(abil); } hull.NeedsBridge = rec.Get <bool>("Requirement Must Have Bridge", hull); hull.CanUseAuxiliaryControl = rec.Get <bool>("Requirement Can Have Aux Con", hull); hull.MinLifeSupport = rec.Get <int>("Requirement Min Life Support", hull); hull.MinCrewQuarters = rec.Get <int>("Requirement Min Crew Quarters", hull); hull.MaxEngines = rec.Get <int>("Requirement Max Engines", hull); hull.MinPercentFighterBays = rec.Get <int>("Requirement Pct Fighter Bays", hull); hull.MinPercentColonyModules = rec.Get <int>("Requirement Pct Colony Mods", hull); hull.MinPercentCargoBays = rec.Get <int>("Requirement Pct Cargo", hull); yield return(hull); } }
public override IEnumerable <IModObject> Load(Mod mod) { foreach (var rec in DataFile.Records) { var c = new ComponentTemplate(); c.TemplateParameters = rec.Parameters; mod.ComponentTemplates.Add(c); int index = -1; c.ModID = rec.Get <string>("ID", c); c.Name = rec.Get <string>("Name", c); c.Description = rec.Get <string>("Description", c); var picfield = rec.FindField("Pic", ref index, false, 0, true); if (picfield != null) { c.PictureName = picfield.CreateFormula <string>(c); } else { c.PictureName = "Comp_" + rec.Get <int>("Pic Num", c).Value.ToString("000"); // for compatibility with SE4 } c.Size = rec.Get <int>("Tonnage Space Taken", c); c.Durability = rec.Get <int>("Tonnage Structure", c); foreach (var costfield in rec.Fields.Where(cf => cf.Name.StartsWith("Cost "))) { c.Cost[Resource.Find(costfield.Name.Substring("Cost ".Length))] = costfield.CreateFormula <int>(c); } var vtoverridefield = rec.FindField(new string[] { "Vehicle List Type Override", "Vechicle List Type Override" }, ref index, false, 0, true); // silly Aaron can't spell "vehicle" if (vtoverridefield != null) { c.VehicleTypes = ParseVehicleTypes(vtoverridefield.Value, ",", rec); } else { c.VehicleTypes = ParseVehicleTypes(rec.Get <string>("Vehicle Type", c), @"\", rec); } c.SupplyUsage = rec.Get <int>("Supply Amount Used", c); var restrictions = rec.Get <string>("Restrictions", c); if (!string.IsNullOrEmpty(restrictions) && restrictions != "None") { var word = restrictions.Value.Split(' ').First(); int num; if (numbers.Contains(word)) { c.MaxPerVehicle = numbers.IndexOf(word); } else if (int.TryParse(word, out num)) { c.MaxPerVehicle = num; } else { Mod.Errors.Add(new DataParsingException("Can't parse \"" + word + "\" as a max-per-vehicle restriction.", Mod.CurrentFileName, rec)); } } c.Group = rec.Get <string>("General Group", c); c.Family = rec.Get <string>("Family", c); c.RomanNumeral = rec.Get <int>("Roman Numeral", c); c.StellarConstructionGroup = rec.Get <string>("Custom Group", c); foreach (var tr in RequirementLoader.LoadEmpireRequirements(rec, c, RequirementType.Unlock)) { c.UnlockRequirements.Add(tr); } // TODO - build and use requirements foreach (var abil in AbilityLoader.Load(Filename, rec, c)) { c.Abilities.Add(abil); } var wfield = rec.FindField("Weapon Type", ref index, false, 0, true); if (wfield != null) { WeaponInfo w = null; if (wfield.Value == "Seeking" || wfield.Value == "Seeking Point-Defense") { var sw = new SeekingWeaponInfo(); sw.SeekerSpeed = rec.Get <int>("Weapon Seeker Speed", c); sw.SeekerDurability = rec.Get <int>("Weapon Seeker Dmg Res", c); w = sw; } else if (wfield.Value == "Direct Fire" || wfield.Value == "Point-Defense") { var dfw = new DirectFireWeaponInfo(); dfw.AccuracyModifier = rec.Get <int>("Weapon Modifier", c); w = dfw; } else if (wfield.Value == "Warhead" || wfield.Value == "Warhead Point-Defense") { var ww = new WarheadWeaponInfo(); w = ww; } else if (string.IsNullOrEmpty(wfield.Value) || wfield.Value == "None") { w = null; } else { Mod.Errors.Add(new DataParsingException("Invalid weapon type \"" + wfield.Value + "\".", Mod.CurrentFileName, rec, wfield)); } if (w != null) { if (wfield.Value.EndsWith("Point-Defense")) { w.IsPointDefense = true; } var wtoverridefield = rec.FindField("Weapon List Target Override", ref index, false, 0, true); if (wtoverridefield != null) { w.Targets = ParseWeaponTargets(wtoverridefield.Value, ",", rec); } else { w.Targets = ParseWeaponTargets(rec.Get <string>("Weapon Target", c), @"\", rec); } w.MinRange = rec.Get <int>(new string[] { "Min Range", "Minimum Range", "Weapon Min Range", "Weapon Minimum Range" }, c) ?? 0; w.MaxRange = rec.Get <int>(new string[] { "Max Range", "Maximum Range", "Weapon Max Range", "Weapon Maximum Range" }, c) ?? 20; var dmgfield = rec.FindField(new string[] { "Damage", "Weapon Damage", "Damage At Rng", "Weapon Damage At Rng", "Damage At Range", "Weapon Damage At Range" }, ref index); if (dmgfield.Value.StartsWith("=")) { w.Damage = dmgfield.CreateFormula <int>(c); } else { string dmgstr = null; try { var dict = new SafeDictionary <int, int>(); var split = dmgfield.Value.Split(' '); for (var i = 0; i < split.Length; i++) { if (split[i].ToInt() == 0) { continue; } dict[i + 1] = split[i].ToInt(); } // HACK - SE4 doesn't explicitly specify damage at range zero so copy the damage at range one value if (dict[1] != 0) { dict[0] = dict[1]; w.MinRange = 0; } w.MinRange = dict.Keys.Min(); w.MaxRange = dict.Keys.Max(); w.Damage = dict.BuildMultiConditionalLessThanOrEqual(c, "range", 0); } catch (Exception ex) { Mod.Errors.Add(new DataParsingException("Can't parse \"" + dmgstr + "\" as a damage string: " + ex.Message, Mod.CurrentFileName, rec)); } } var damTypeName = rec.Get <string>("Weapon Damage Type", c); w.DamageType = Mod.Current.DamageTypes.FindByName(damTypeName); if (w.DamageType == null) { // no valid damage type? then make it normal damage and log a warning w.DamageType = DamageType.Normal; Mod.Errors.Add(new DataParsingException("Unknown damage type \"" + damTypeName + "\"; setting " + c + "'s damage type to Normal.", Mod.CurrentFileName, rec)); } w.ReloadRate = rec.Get <double>("Weapon Reload Rate", c); var wdisptype = rec.Get <string>("Weapon Display Type", c); var wdispname = rec.Get <string>("Weapon Display", c); if (wdisptype == "Beam") { w.DisplayEffect = new BeamWeaponDisplayEffect(wdispname); } else if (wdisptype == "Torp" || wdisptype == "Torpedo" || wdisptype == "Projectile") { w.DisplayEffect = new ProjectileWeaponDisplayEffect(wdispname); } else if (wdisptype == "Seeker") { w.DisplayEffect = new SeekerWeaponDisplayEffect(wdispname); } else { Mod.Errors.Add(new DataParsingException("Invalid weapon display effect type \"" + wdisptype + "\".", Mod.CurrentFileName, rec)); } // sanity check if (wdisptype == "Beam" && w is SeekingWeaponInfo) { Mod.Errors.Add(new DataParsingException("A seeking weapon cannot use a beam display effect.", Mod.CurrentFileName, rec)); } w.Sound = rec.Get <string>("Weapon Sound", c); w.Family = rec.Get <string>("Weapon Family", c); } c.WeaponInfo = w; yield return(c); } } }