public ResourceQuantity Evaluate(object host) { var q = new ResourceQuantity(); foreach (var kvp in this) { q.Add(kvp.Key, kvp.Value.Evaluate(host)); } return(q); }
// TODO - status messages for the GUI private void PlaceEmpire(Galaxy gal, Empire emp, PRNG dice) { if (AllSystemsExplored) { // set all systems explored foreach (var sys in gal.StarSystemLocations.Select(ssl => ssl.Item)) { sys.ExploredByEmpires.Add(emp); } } // give empire starting techs Galaxy.Current.CleanGameState(); // need to know what the techs in the game are! foreach (var tech in Mod.Current.Technologies.Where(t => !t.IsRacial || emp.Abilities().Any(a => a.Rule.Matches("Tech Area") && a.Value1 == t.RacialTechID))) { switch (StartingTechnologyLevel) { case StartingTechnologyLevel.Low: emp.ResearchedTechnologies[tech] = tech.StartLevel; break; case StartingTechnologyLevel.Medium: emp.ResearchedTechnologies[tech] = Math.Max(tech.StartLevel, tech.RaiseLevel); break; case StartingTechnologyLevel.High: emp.ResearchedTechnologies[tech] = tech.MaximumLevel; break; } } // give empire starting resources and storage capacity foreach (var r in Resource.All.Where(r => r.IsGlobal)) { emp.StoredResources.Add(r, StartingResources); emp.IntrinsicResourceStorage.Add(r, ResourceStorage); } // give empire starting research emp.BonusResearch = StartingResearch + (int)(ResearchPointsPerUnspentEmpirePoint * (EmpirePoints - emp.PrimaryRace.Traits.Sum(q => q.Cost))); // TODO - moddable colony techs? string colonyTechName = null; if ((emp.PrimaryRace.NativeSurface) == "Rock") { colonyTechName = "Rock Planet Colonization"; } else if ((emp.PrimaryRace.NativeSurface) == "Ice") { colonyTechName = "Ice Planet Colonization"; } else if ((emp.PrimaryRace.NativeSurface) == "Gas Giant") { colonyTechName = "Gas Giant Colonization"; } var colonyTech = Mod.Current.Technologies.SingleOrDefault(t => t.Name == colonyTechName); if (colonyTech != null && emp.ResearchedTechnologies[colonyTech] < 1) { emp.ResearchedTechnologies[colonyTech] = 1; } // find facilities to place on homeworlds var facils = emp.UnlockedItems.OfType <FacilityTemplate>(); var sy = facils.WithMax(facil => facil.GetAbilityValue("Space Yard", 2).ToInt()).LastOrDefault(); var sp = facils.LastOrDefault(facil => facil.HasAbility("Spaceport")); var rd = facils.LastOrDefault(facil => facil.HasAbility("Supply Generation")); var min = facils.WithMax(facil => facil.GetAbilityValue("Resource Generation - Minerals").ToInt()).LastOrDefault(); var org = facils.WithMax(facil => facil.GetAbilityValue("Resource Generation - Organics").ToInt()).LastOrDefault(); var rad = facils.WithMax(facil => facil.GetAbilityValue("Resource Generation - Radioactives").ToInt()).LastOrDefault(); var res = facils.WithMax(facil => facil.GetAbilityValue("Point Generation - Research").ToInt()).LastOrDefault(); // TODO - game setup option for intel facilities on homeworlds? HomeworldStartingFacilities.txt ala se5? // SY rate, for colonies var rate = new ResourceQuantity(); if (sy != null) { // TODO - define mappings between SY ability numbers and resource names in a mod file rate.Add(Resource.Minerals, sy.GetAbilityValue("Space Yard", 2, true, true, a => a.Value1 == "1").ToInt()); rate.Add(Resource.Organics, sy.GetAbilityValue("Space Yard", 2, true, true, a => a.Value1 == "2").ToInt()); rate.Add(Resource.Radioactives, sy.GetAbilityValue("Space Yard", 2, true, true, a => a.Value1 == "3").ToInt()); } // build connectivity graph for computing warp distance var graph = new ConnectivityGraph <StarSystem>(); foreach (var s in Galaxy.Current.StarSystemLocations.Select(ssl => ssl.Item)) { graph.Add(s); } foreach (var s in Galaxy.Current.StarSystemLocations.Select(ssl => ssl.Item)) { foreach (var wp in s.FindSpaceObjects <WarpPoint>()) { graph.Connect(s, wp.TargetStarSystemLocation.Item, true); } } for (int i = 0; i < HomeworldsPerEmpire; i++) { // TODO - respect Empire Placement and Max Homeworld Dispersion settings var planets = gal.StarSystemLocations.SelectMany(ssl => ssl.Item.FindSpaceObjects <Planet>(p => p.Owner == null && p.MoonOf == null)); var okSystems = gal.StarSystemLocations.Select(ssl => ssl.Item).Where(sys => sys.EmpiresCanStartIn); if (i > 0) { // make sure subsequent homeworlds are placed within a limited number of warps from the first homeworld okSystems = okSystems.Where(sys => graph.ComputeDistance(sys, emp.OwnedSpaceObjects.OfType <Planet>().First().FindStarSystem()) <= MaxHomeworldDispersion); } switch (EmpirePlacement) { case EmpirePlacement.CanStartInSameSystem: // no further filtering break; case EmpirePlacement.DifferentSystems: // filter to systems containing no other empires' homeworlds okSystems = okSystems.Where(sys => !sys.FindSpaceObjects <Planet>(p => p.Owner != null && p.Owner != emp).Any()); break; case EmpirePlacement.Equidistant: // filter to systems containing no other empires' homeworlds okSystems = okSystems.Where(sys => !sys.FindSpaceObjects <Planet>(p => p.Owner != null && p.Owner != emp).Any()); // filter to systems that are the maximum distance away from any other empire's homeworlds var otherEmpireHomeSystems = gal.StarSystemLocations.SelectMany(ssl => ssl.Item.FindSpaceObjects <Planet>(p => p.Owner != null && p.Owner != emp).Select(p => p.FindStarSystem()).Distinct()).ToArray(); okSystems = okSystems.WithMax(sys => otherEmpireHomeSystems.Min(o => graph.ComputeDistance(sys, o))); break; } okSystems = okSystems.ToArray(); if (!okSystems.Any()) { // replace an inhospitable system with a hospitable one var convertSys = gal.StarSystemLocations.Select(ssl => ssl.Item).Where(sys => !sys.EmpiresCanStartIn).PickRandom(dice); if (convertSys == null) { throw new Exception("No suitable system found to place " + emp + "'s homeworld #" + (i + 1) + ". (Try increasing the number of star systems.)"); } var newSys = Mod.Current.StarSystemTemplates.Where(q => q.EmpiresCanStartIn).PickRandom(dice).Instantiate(); var sid = convertSys.ID; newSys.CopyTo(convertSys); convertSys.ID = sid; convertSys.Name = Mod.Current.StarSystemNames.Except(gal.StarSystemLocations.Select(q => q.Item.Name)).PickRandom(dice); foreach (var l in Galaxy.Current.StarSystemLocations) { foreach (var wp in l.Item.FindSpaceObjects <WarpPoint>().Where(q => q.Target.StarSystem == convertSys).ToArray()) { wp.Dispose(); WarpPointPlacementStrategy.PlaceWarpPoints(Galaxy.Current.StarSystemLocations.Single(q => q.Item == convertSys), l); } } GalaxyTemplate.NameStellarObjects(convertSys); okSystems = new[] { convertSys }; } Planet hw; planets = planets.Where(p => okSystems.Contains(p.FindStarSystem())); if (!planets.Any()) { // make sure we're placing the homeworld in a system with at least one empty sector okSystems = okSystems.Where(sys2 => sys2.Sectors.Any(sec => !sec.SpaceObjects.Any())); if (!okSystems.Any()) { throw new Exception("No suitable system found to place " + emp + "'s homeworld #" + (i + 1) + ". (Try regenerating the map or increasing the number of star systems.)"); } // make brand new planet in an OK system var sys = okSystems.PickRandom(dice); var nextNum = sys.FindSpaceObjects <Planet>(p => p.MoonOf == null).Count() + 1; hw = MakeHomeworld(emp, sys.Name + " " + nextNum.ToRomanNumeral(), dice); var okSectors = sys.Sectors.Where(sector => !sector.SpaceObjects.Any()); okSectors.PickRandom(dice).Place(hw); } else { hw = planets.PickRandom(dice); } if (hw.Surface != emp.PrimaryRace.NativeSurface || hw.Atmosphere != emp.PrimaryRace.NativeAtmosphere || hw.Size != HomeworldSize) { var replacementHomeworld = MakeHomeworld(emp, hw.Name, dice); replacementHomeworld.CopyTo(hw); } hw.ResourceValue[Resource.Minerals] = hw.ResourceValue[Resource.Organics] = hw.ResourceValue[Resource.Radioactives] = HomeworldValue; hw.Colony = new Colony { Owner = emp, ConstructionQueue = new ConstructionQueue(hw), IsHomeworld = true, }; hw.AddPopulation(emp.PrimaryRace, hw.Size.MaxPopulation); if (sy != null && hw.Colony.Facilities.Count < hw.MaxFacilities) { hw.Colony.Facilities.Add(sy.Instantiate()); } if (sp != null && hw.Colony.Facilities.Count < hw.MaxFacilities && (!emp.HasAbility("No Spaceports") || sp.Abilities.Count > 1)) { // natural merchants get spaceports only if spaceports have more than one ability // of course, if the other abilities are *penalties*... oh well, they can scrap them! hw.Colony.Facilities.Add(sp.Instantiate()); } if (rd != null && hw.Colony.Facilities.Count < hw.MaxFacilities) { hw.Colony.Facilities.Add(rd.Instantiate()); } var lastCount = 0; while (hw.Colony.Facilities.Count < hw.MaxFacilities && hw.Colony.Facilities.Count > lastCount) { lastCount = hw.Colony.Facilities.Count; if (min != null && hw.Colony.Facilities.Count < hw.MaxFacilities) { hw.Colony.Facilities.Add(min.Instantiate()); } if (org != null && hw.Colony.Facilities.Count < hw.MaxFacilities) { hw.Colony.Facilities.Add(org.Instantiate()); } if (rad != null && hw.Colony.Facilities.Count < hw.MaxFacilities) { hw.Colony.Facilities.Add(rad.Instantiate()); } // no research facilities needed at max tech! if (StartingTechnologyLevel != StartingTechnologyLevel.High) { if (res != null && hw.Colony.Facilities.Count < hw.MaxFacilities) { hw.Colony.Facilities.Add(res.Instantiate()); } } } foreach (var f in hw.Colony.Facilities) { f.ConstructionProgress = f.Cost; } } // mark home systems explored foreach (var sys in gal.StarSystemLocations.Select(ssl => ssl.Item)) { if (!sys.ExploredByEmpires.Contains(emp) && sys.FindSpaceObjects <Planet>().Any(planet => planet.Owner == emp)) { sys.ExploredByEmpires.Add(emp); } } // in case two empires started in the same system foreach (var x in gal.FindSpaceObjects <ISpaceObject>().Owned().ToArray()) { x.UpdateEmpireMemories(); } }
public ModSettings() { DefaultColonyConstructionRate = new ResourceQuantity(); // TODO - moddable default colony construction rate DefaultColonyConstructionRate.Add(Resource.Minerals, 2000); DefaultColonyConstructionRate.Add(Resource.Organics, 2000); DefaultColonyConstructionRate.Add(Resource.Radioactives, 2000); PopulationModifiers = new SortedDictionary <long, PopulationModifier>(); // TODO - split apart production and construction modifiers as a mod option? MoodProductivityModifiers = new Dictionary <Mood, int>(); // TODO - moddable mood reproduction modifiers MoodReproductionModifiers = new Dictionary <Mood, int>(); MoodReproductionModifiers.Add(Mood.Rioting, -999); MoodReproductionModifiers.Add(Mood.Angry, -5); MoodReproductionModifiers.Add(Mood.Unhappy, -2); MoodReproductionModifiers.Add(Mood.Indifferent, 0); MoodReproductionModifiers.Add(Mood.Happy, 2); MoodReproductionModifiers.Add(Mood.Jubilant, 5); MoodReproductionModifiers.Add(Mood.Emotionless, 2); // TODO - moddable mood construction modifiers MoodConstructionModifiers = new Dictionary <Mood, int>(); MoodConstructionModifiers.Add(Mood.Rioting, 0); MoodConstructionModifiers.Add(Mood.Angry, 100); MoodConstructionModifiers.Add(Mood.Unhappy, 100); MoodConstructionModifiers.Add(Mood.Indifferent, 100); MoodConstructionModifiers.Add(Mood.Happy, 100); MoodConstructionModifiers.Add(Mood.Jubilant, 100); MoodConstructionModifiers.Add(Mood.Emotionless, 100); // TODO - moddable mood thresholds MoodThresholds = new Dictionary <Mood, int>(); MoodThresholds.Add(Mood.Rioting, 750); MoodThresholds.Add(Mood.Angry, 600); MoodThresholds.Add(Mood.Unhappy, 450); MoodThresholds.Add(Mood.Indifferent, 300); MoodThresholds.Add(Mood.Happy, 150); MoodThresholds.Add(Mood.Jubilant, 0); // TODO - moddable planetary conditions thresholds ConditionsThresholds = new Dictionary <Conditions, int>(); ConditionsThresholds.Add(Conditions.Deadly, 0); ConditionsThresholds.Add(Conditions.Harsh, 20); ConditionsThresholds.Add(Conditions.Unpleasant, 35); ConditionsThresholds.Add(Conditions.Average, 50); ConditionsThresholds.Add(Conditions.Mild, 65); ConditionsThresholds.Add(Conditions.Good, 80); ConditionsThresholds.Add(Conditions.Optimal, 95); // TODO - moddable planetary conditions modifiers ConditionsReproductionModifiers = new Dictionary <Conditions, int>(); ConditionsReproductionModifiers.Add(Conditions.Deadly, -20); ConditionsReproductionModifiers.Add(Conditions.Harsh, -5); ConditionsReproductionModifiers.Add(Conditions.Unpleasant, -2); ConditionsReproductionModifiers.Add(Conditions.Average, 0); ConditionsReproductionModifiers.Add(Conditions.Mild, 2); ConditionsReproductionModifiers.Add(Conditions.Good, 5); ConditionsReproductionModifiers.Add(Conditions.Optimal, 8); IntroSongs = new List <string>(); GameplaySongs = new List <string>(); CombatSongs = new List <string>(); VictorySongs = new List <string>(); DefeatSongs = new List <string>(); VictoryPictures = new List <string>(); DefeatPictures = new List <string>(); ValueChangeFrequency = 10; }