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")}).");
        }
Exemple #2
0
        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");
        }
Exemple #3
0
        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];
        }
Exemple #9
0
 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);
     }
 }
Exemple #13
0
 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()
     });
Exemple #14
0
 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;
         }
     }
 }
Exemple #15
0
        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!");
            }
        }
Exemple #16
0
 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();
     }
 }
Exemple #17
0
        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);
            }
        }
Exemple #20
0
        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);
            }
        }
Exemple #21
0
        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();
        }
Exemple #23
0
        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))));
        }
Exemple #24
0
 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()
     });
Exemple #25
0
        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
                    });
                }
            }
        }
Exemple #26
0
        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]);
        }
Exemple #27
0
        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);
        }
Exemple #28
0
        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();