public string Execute(TechTier tier, bool withNodes, [CurrentCharacterIfNull] ICharacter player = null) { var technologies = player.SharedGetTechnologies(); foreach (var techGroup in TechGroup.AvailableTechGroups) { if (techGroup.Tier != tier) { continue; } technologies.ServerAddGroup(techGroup); if (!withNodes) { continue; } foreach (var techNode in techGroup.Nodes) { technologies.ServerAddNode(techNode); } } return($"{player} all tech groups of {tier} added {(withNodes ? "with nodes" : "without nodes")})."); }
public ResearchCategory(ConfigNode n) { this.Name = n.GetValue("name"); this.DisplayName = n.GetValue("display_name"); switch (n.GetValue("type")?.ToLowerInvariant()) { case "space": this.Type = ProductionRestriction.Space; break; case "orbit": this.Type = ProductionRestriction.OrbitOfBody; break; default: this.Type = ProductionRestriction.LandedOnBody; break; } n.TryGetValue("kerbal_years_to_tier1", ref this.kerbalYearsToTier1); n.TryGetValue("kerbal_years_to_tier2", ref this.kerbalYearsToTier2); n.TryGetValue("kerbal_years_to_tier3", ref this.kerbalYearsToTier3); n.TryGetValue("kerbal_years_to_tier4", ref this.kerbalYearsToTier4); this.researchLimits = new ResearchLimit[1 + (int)TechTier.Tier4]; for (TechTier tier = TechTier.Tier0; tier < TechTier.Tier4; ++tier) { this.researchLimits[(int)tier] = new ResearchLimit(n.GetValue($"tier{(int)tier}_limit")); } this.researchLimits[(int)TechTier.Tier4] = ResearchLimit.MaxTierLimit; this.breakThroughMessageTag = n.GetValue("breakthrough_messages"); this.breakThroughExplanationTag = n.GetValue("breakthrough_message_boring"); }
public ViewModelTechTier(TechTier tier) { this.Tier = tier; TechGroup.AvailableTechGroupsChanged += this.AvailableTechGroupsChangedHandler; this.Initialize(); }
public static string DescribeKerbalsWithEffect(string experienceEffect, TechTier tier) { List <ExperienceTraitConfig> careers = GameDatabase.Instance.ExperienceConfigs .GetTraitsWithEffect(experienceEffect) .Select(name => GameDatabase.Instance.ExperienceConfigs.GetExperienceTraitConfig(name)) .ToList(); StringBuilder info = new StringBuilder(); for (int i = 0; i < careers.Count; ++i) { ExperienceEffectConfig effectConfig = careers[i].Effects.First(effect => effect.Name == experienceEffect); int numStars = 1 + (int)tier - int.Parse(effectConfig.Config.GetValue("level")); if (i == careers.Count - 1) { info.Append(" or a "); } else if (i > 0) { info.Append(", "); } info.Append(DescribeKerbalTrait(numStars, careers[i].Title)); } return(info.ToString()); }
public TieredResource( string name, string capacityUnits, ResearchCategory researchCategory, bool canBeStored, bool unstoredExcessCanGoToResearch, bool isHarvestedLocally, TieredResource madeFrom, TechTier madeFromStartsAt, double effT0, double effT1, double effT2, double effT3, double effT4) { this.BaseName = name; this.DisplayName = name; this.CapacityUnits = capacityUnits; this.CanBeStored = canBeStored; this.ExcessProductionCountsTowardsResearch = unstoredExcessCanGoToResearch; this.ResearchCategory = researchCategory; this.IsHarvestedLocally = isHarvestedLocally; this.madeFrom = madeFrom; this.madeFromStartsAt = madeFromStartsAt; this.effectivenessAtTier = new double[5]; this.effectivenessAtTier[0] = effT0; this.effectivenessAtTier[1] = effT1; this.effectivenessAtTier[2] = effT2; this.effectivenessAtTier[3] = effT3; this.effectivenessAtTier[4] = effT4; this.reputationPerUnitAtTier = new float[5]; }
public ResearchData(ResearchCategory category, TechTier currentTier, double accumulatedKerbalDays, double kerbalDaysRequired) { this.Category = category; this.AccumulatedKerbalDays = accumulatedKerbalDays; this.KerbalDaysRequired = kerbalDaysRequired; this.KerbalDaysContributedPerDay = 0; this.currentTier = currentTier; }
private PartSetupDialog(TieredResource product, string body, TechTier tier, TechTier maxTierForPart) { this.Body = body; this.Tier = tier; this.Product = product; this.MaxTierForPart = maxTierForPart; this.RiskLevel = StaticAnalysis.GetTierSuitability(ColonizationResearchScenario.Instance, this.Product, tier, maxTierForPart, this.Body); }
private TieredResource(ConfigNode c, ResearchCategory researchCategory, TieredResource madeFrom, TechTier madeFromStartsAt) { this.BaseName = c.GetValue("name"); this.DisplayName = c.GetValue("display_name"); this.CapacityUnits = c.GetValue("capacity_units"); bool canBeStored = false; c.TryGetValue("can_be_stored", ref canBeStored); this.CanBeStored = canBeStored; bool unstoredExcessCanGoToResearch = false; c.TryGetValue("unstored_excess_can_go_to_research", ref unstoredExcessCanGoToResearch); this.ExcessProductionCountsTowardsResearch = unstoredExcessCanGoToResearch; bool isHarvestedLocally = false; c.TryGetValue("is_harvested_locally", ref isHarvestedLocally); this.IsHarvestedLocally = isHarvestedLocally; this.CrewSkill = c.GetValue("crew_skill"); researchCategory.AddCrewSkill(this.CrewSkill); this.ResearchCategory = researchCategory; // If it's edible, it'll have these set bool allSet = true; double[] effectiveness = new double[1 + (int)TechTier.Tier4]; for (TechTier tech = TechTier.Tier0; tech <= TechTier.Tier4; ++tech) { string name = $"effectiveness_at_tier{(int)tech}"; if (!c.TryGetValue(name, ref effectiveness[(int)tech]) || effectiveness[(int)tech] > 1 || effectiveness[(int)tech] < 0) { allSet = false; break; } } this.effectivenessAtTier = allSet ? effectiveness : null; this.madeFrom = madeFrom; this.madeFromStartsAt = madeFromStartsAt; float[] repGains = new float[1 + (int)TechTier.Tier4]; allSet = true; for (TechTier tech = TechTier.Tier0; tech <= TechTier.Tier4; ++tech) { string name = $"reputation_per_unit_at_tier{(int)tech}"; if (!c.TryGetValue(name, ref repGains[(int)tech])) { allSet = false; break; } } this.reputationPerUnitAtTier = allSet ? repGains : new float[1 + (int)TechTier.Tier4]; }
internal ResourceLode(Waypoint waypoint, TechTier tier) { this.Latitude = waypoint.latitude; this.Longitude = waypoint.longitude; this.bodyName = waypoint.celestialBody.name; this.Identifier = waypoint.navigationId.ToString(); this.DiscoveryTime = Planetarium.GetUniversalTime(); this.Quantity = 500; this.Tier = tier; }
public static RequirementHaveTechGroups RequireAnyFromTier( TechTier tier, ushort count, string description = null) { var techGroups = Api.FindProtoEntities <TechGroup>() .Where(g => g.Tier == tier) .ToList(); return(RequireAny(techGroups, count, description)); }
public static TaskHaveTechGroups RequireAnyFromTier( TechTier tier, ushort count, string description = null) { var techGroups = TechGroup.AvailableTechGroups .Where(g => g.Tier == tier) .ToList(); return(RequireAny(techGroups, count, description)); }
public static void Show(TieredResource product, string body, TechTier tier, TechTier maxTierForPart, Action <PartSetupDialog> onSet) { if (product.ResearchCategory.Type == ProductionRestriction.LandedOnBody && !ColonizationResearchScenario.Instance.UnlockedBodies.Any()) { PopupMessageWithKerbal.ShowPopup("No Bodies Explored", "You need to land and return from a body in order to start a colony on it", "Got it"); } else { new PartSetupDialog(product, body, tier, maxTierForPart).Show(onSet); } }
public static string GetTierLetterOnly(TechTier tier) { return(tier switch { TechTier.Tier1 => Tier1Letter, TechTier.Tier2 => Tier2Letter, TechTier.Tier3 => Tier3Letter, TechTier.Tier4 => Tier4Letter, TechTier.Tier5 => Tier5Letter, _ => throw new ArgumentOutOfRangeException() });
private static void SetToIdealTier(IColonizationResearchScenario colonizationResearch, ITieredProducer producer) { for (TechTier tier = TechTier.Tier4; tier >= TechTier.Tier0; --tier) { var suitability = StaticAnalysis.GetTierSuitability(colonizationResearch, producer.Output, tier, producer.MaximumTier, producer.Body); if (suitability == TierSuitability.Ideal) { producer.Tier = tier; break; } } }
private void AskUserToPickbase(TechTier scannerTier) { var stuffResource = ColonizationResearchScenario.Instance.AllResourcesTypes.FirstOrDefault(r => r.MadeFrom((TechTier)this.minimumTier) == ColonizationResearchScenario.Instance.CrushInsResource); var baseChoices = new List <DialogGUIButton>(); double scannerNetQuality = this.CalculateScannerNetQuality(); Action onlyPossibleChoiceAction = null; foreach (var candidate in FlightGlobals.Vessels) { // Only look at vessels that are on the body of the scanner and are not marked as debris if (candidate.mainBody != this.vessel.mainBody || (candidate.situation != Vessel.Situations.LANDED && candidate.situation != Vessel.Situations.SPLASHED) || candidate.vesselType == VesselType.Debris) { continue; } // Look for a scrounger part if (TryFindScrounger(scannerTier, candidate, stuffResource, out TechTier maxTierScrounger)) { void onSelect() => ResourceLodeScenario.Instance.GetOrCreateResourceLoad(this.vessel, candidate, maxTierScrounger, scannerNetQuality); onlyPossibleChoiceAction = onSelect; DialogGUIButton choice = new DialogGUIButton(candidate.vesselName, onSelect, dismissOnSelect: true); baseChoices.Add(choice); } } if (baseChoices.Count == 0) { ScreenMessages.PostScreenMessage("There doesn't seem to be a base down there"); } else if (baseChoices.Count == 1) { onlyPossibleChoiceAction(); } else { PopupDialog.SpawnPopupDialog( new MultiOptionDialog( "Whatsthisdoeven", "", // This actually shows up on the screen as a sort of a wierd-looking subtitle "Which base shall we Look near?", HighLogic.UISkin, new DialogGUIVerticalLayout(baseChoices.ToArray())), persistAcrossScenes: false, skin: HighLogic.UISkin, isModal: true, titleExtra: "TITLE EXTRA!"); } }
public void OnSetupSelected(PartSetupDialog dialog) { this.tier = (int)dialog.Tier; this.body = dialog.Body ?? NotSet; PksTieredResourceConverter.RiskTolerance = dialog.RiskLevel; PksTieredResourceConverter.DefaultPartSetFor = this.part; PksTieredResourceConverter.LastTierSelected = dialog.Tier; if (dialog.Applicability == PartSetupDialog.DecisionImpact.AllParts) { this.SetupAllParts(); } }
private void GetTargetInfo(out TechTier tier, out string targetBody) { var scanner = this.part.GetComponent <PksTieredResourceConverter>(); Debug.Assert(scanner != null, "GetTargetInfo couldn't find a PksTieredResourceConverter - probably the part is misconfigured"); if (scanner == null) { throw new Exception($"Misconfigured part - {part.name} should have a PksTieredResourceConverter"); } tier = scanner.Tier; targetBody = scanner.Body; }
public override bool RequirementMet(ConfiguredContract contract) { TieredResource resource = ColonizationResearchScenario.Instance.AllResourcesTypes.FirstOrDefault(r => r.ResearchCategory.Name == this.researchCategory); if (resource == null) { Debug.LogError($"Misconfigured PksTierRequirement - unknown resource '{this.researchCategory}'"); return(false); } TechTier tier = ColonizationResearchScenario.Instance.GetMaxUnlockedTier(resource, this.targetBody.name); return((int)tier > this.tier); }
public double GetRatioForTier(TechTier tier) { switch (tier) { default: case TechTier.Tier0: return(ExpectedTier0Ratio); case TechTier.Tier1: return(ExpectedTier1Ratio); case TechTier.Tier2: return(ExpectedTier2Ratio); case TechTier.Tier3: return(ExpectedTier3Ratio); case TechTier.Tier4: return(ExpectedTier4Ratio); } }
public double KerbalYearsToNextTier(TechTier tier) { switch (tier) { case TechTier.Tier0: return(this.kerbalYearsToTier1); case TechTier.Tier1: return(this.kerbalYearsToTier2); case TechTier.Tier2: return(this.kerbalYearsToTier3); case TechTier.Tier3: return(this.kerbalYearsToTier4); case TechTier.Tier4: default: return(double.MaxValue); } }
private static bool TryFindScrounger(TechTier scannerTier, Vessel candidate, TieredResource stuffResource, out TechTier highestScroungerTier) { highestScroungerTier = TechTier.Tier0; // Don't trust KSP to actually always have these things populated; if (candidate.protoVessel == null || candidate.protoVessel.protoPartSnapshots == null) { return(false); } bool hasScrounger = false; foreach (var protoPart in candidate.protoVessel.protoPartSnapshots) { if (protoPart.modules == null) { continue; } // Unloaded vessels have modules, but they're not truly populated - that is, the class for // the module is created, but the members have their default values... So we can find the // stuff that's coded in the part description (in this case) the "output" field here: if (protoPart.partPrefab.Modules.OfType <PksTieredResourceConverter>().Any(c => c.Output == stuffResource)) { hasScrounger = true; // ...But to get hold of the this that are set in the VAB (like the tier), you have // to parse it out of the config nodes. foreach (var protoModule in protoPart.modules.Where(m => m.moduleName == nameof(PksTieredResourceConverter))) { TechTier tier = PksTieredResourceConverter.GetTechTierFromConfig(protoModule.moduleValues); if (tier > scannerTier) { // There's no practical use of finding stuff near this base - even if it has lower // tier scroungers somewhere, the higher tier ones should be taking priority. return(false); } else if (tier > highestScroungerTier) { highestScroungerTier = tier; } } } } return(hasScrounger && stuffResource.MadeFrom(highestScroungerTier) != null); }
public ViewModelTechTier(TechTier tier) { this.Tier = tier; var allGroups = Api.FindProtoEntities <TechGroup>() .Where(g => g.Tier == tier) .OrderBy(g => g.Order) .ThenBy(g => g.ShortId) .Select(g => new ViewModelTechGroup(g)) .ToList(); this.GroupsPrimary = allGroups.Where(g => g.TechGroup.IsPrimary) .ToList(); this.GroupsSecondary = allGroups.Where(g => !g.TechGroup.IsPrimary) .ToList(); }
internal ResearchData GetResearchProgress(TieredResource forResource, string atBody) { double kerbalSecondsSoFar = 0; TechTier currentTier = TechTier.Tier0; if (this.categoryToBodyToProgressMap.TryGetValue(forResource.ResearchCategory, out Dictionary <string, TechProgress> bodyToProgressMap)) { string bodyName = forResource.ProductionRestriction == ProductionRestriction.Space ? "" : atBody; if (bodyToProgressMap.TryGetValue(bodyName, out TechProgress progress)) { currentTier = progress.Tier; kerbalSecondsSoFar = progress.ProgressInKerbalSeconds; } } return(new ResearchData(forResource.ResearchCategory, currentTier, KerbalTime.KerbalSecondsToDays(kerbalSecondsSoFar), KerbalTime.KerbalYearsToDays(forResource.ResearchCategory.KerbalYearsToNextTier(currentTier)))); }
public static string GetTierLetterOnly(TechTier tier) { return((byte)tier switch { 1 => Tier1Letter, 2 => Tier2Letter, 3 => Tier3Letter, 4 => Tier4Letter, 5 => Tier5Letter, // not supported by the vanilla game as we don't use more than 5 tiers (Tier 6 is "Escape") 6 => "VI", 7 => "VII", 8 => "VIII", 9 => "IX", 10 => "X", _ => tier.ToString() });
internal static IEnumerable <WarningMessage> CheckCorrectCapacity(IColonizationResearchScenario colonizationResearch, List <ITieredProducer> producers, Dictionary <string, double> amountAvailable, Dictionary <string, double> storageAvailable) { var production = producers .GroupBy(p => p.Output) .ToDictionary(pair => pair.Key, pair => pair.Sum(p => p.ProductionRate)); var consumption = producers .Where(p => p.Input != null) .GroupBy(p => p.Input) .ToDictionary(pair => pair.Key, pair => pair.Sum(p => p.ProductionRate)); foreach (var inputPair in consumption) { TieredResource inputResource = inputPair.Key; double inputRequired = inputPair.Value; if (inputResource.IsHarvestedLocally) { // Crush-ins -- there are other things that ensure this works. } else if (!production.TryGetValue(inputPair.Key, out double outputAmount)) { // Okay, there's no producer for this - complain if there's no storage that either contains the // required tier or could contain it if it's gathered locally. TechTier requiredTier = producers.Where(p => p.Input == inputResource).Select(p => p.Tier).Min(); bool anyInStorage = Enumerable.Range((int)requiredTier, 1 + (int)TechTier.Tier4) .Any(i => amountAvailable.TryGetValue(inputResource.TieredName((TechTier)i), out var amount) && amount > 0); if (!inputResource.IsHarvestedLocally && !anyInStorage) { yield return(new WarningMessage() { Message = $"The ship needs {inputResource.BaseName} to produce {producers.First(p => p.Input == inputResource).Output.BaseName}", IsClearlyBroken = false, FixIt = null }); } } else if (outputAmount < inputRequired) { yield return(new WarningMessage() { Message = $"The ship needs at least {inputRequired} production of {inputResource.BaseName} but it is only producing {outputAmount}", IsClearlyBroken = false, FixIt = null }); } } }
public double Get(TechTier tier, bool isSpecialized) { if (PveSystem.SharedIsPve(false)) { return(0); } var tierIndex = (int)tier - (int)TechConstants.PvPTimeGateStartsFromTier; if (tierIndex < 0) { return(0); } var index = 2 * tierIndex + (isSpecialized ? 1 : 0); return(this.TimeGates[index]); }
private static bool TryCreateFromNode(ConfigNode node, out TechProgress progress) { TechTier tierAtBody = TechTier.Tier0; double progressToNext = 0; if (!node.TryGetEnum <TechTier>("tier", ref tierAtBody, TechTier.Tier0) || !node.TryGetValue("progress", ref progressToNext)) { progress = null; return(false); } progress = new TechProgress() { ProgressInKerbalSeconds = progressToNext, Tier = tierAtBody }; return(true); }
public bool TryFindResourceLodeInRange(Vessel vessel, TechTier tier, out ResourceLode resourceLode) { // There's only allowed one resource load - you have to harvest it until it's gone // So find the thing first. resourceLode = this.activeLodes.FirstOrDefault(rl => rl.bodyName == vessel.mainBody.name && rl.Tier == tier); if (resourceLode == null) { return(false); } // Ensure that there's a waypoint if (!Waypoints.TryFindWaypointById(resourceLode.Identifier, out Waypoint waypoint)) { waypoint = Waypoints.CreateWaypointAt("Resource Lode", vessel.mainBody, resourceLode.Latitude, resourceLode.Longitude); resourceLode.WaypointRecreated(waypoint); } return(Waypoints.StraightLineDistanceInMeters(vessel, waypoint) < 150.0); }
public TieredResource( string name, string capacityUnits, ResearchCategory researchCategory, bool canBeStored, bool unstoredExcessCanGoToResearch, bool isHarvestedLocally, TieredResource madeFrom, TechTier madeFromStartsAt) { this.BaseName = name; this.DisplayName = name; this.CapacityUnits = capacityUnits; this.CanBeStored = canBeStored; this.ExcessProductionCountsTowardsResearch = unstoredExcessCanGoToResearch; this.ResearchCategory = researchCategory; this.IsHarvestedLocally = isHarvestedLocally; this.madeFrom = madeFrom; this.madeFromStartsAt = madeFromStartsAt; this.reputationPerUnitAtTier = name == "Shinies" ? new float[] { 1.0f, 1.0f, 1.0f, 1.0f, 1.0f } : new float[5]; }
public static string DisplayName(this TechTier techTier) => techTier.ToString();