예제 #1
0
        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);
                }
            }
        }