Esempio n. 1
0
        // credit science for the experiment subject specified
        public static float Credit(string subject_id, double size, bool transmitted, ProtoVessel pv)
        {
            var credits = Value(subject_id, size);

            // credit the science
            var subject = ResearchAndDevelopment.GetSubjectByID(subject_id);

            if (subject == null)
            {
                Lib.Log("WARNING: science subject " + subject_id + " cannot be credited in R&D");
            }
            else
            {
                subject.science        += credits / HighLogic.CurrentGame.Parameters.Career.ScienceGainMultiplier;
                subject.scientificValue = ResearchAndDevelopment.GetSubjectValue(subject.science, subject);
                ResearchAndDevelopment.Instance.AddScience(credits, transmitted ? TransactionReasons.ScienceTransmission : TransactionReasons.VesselRecovery);

                // fire game event
                // - this could be slow or a no-op, depending on the number of listeners
                //   in any case, we are buffering the transmitting data and calling this
                //   function only once in a while
                GameEvents.OnScienceRecieved.Fire(credits, subject, pv, false);

                API.OnScienceReceived.Fire(credits, subject, pv, transmitted);
            }

            // return amount of science credited
            return(credits);
        }
Esempio n. 2
0
        // credit science for the experiment subject specified
        public static double credit(string subject_id, double size, bool transmitted, ProtoVessel pv)
        {
            // get science subject
            // - if null, we are in sandbox mode
            ScienceSubject subject = ResearchAndDevelopment.GetSubjectByID(subject_id);

            if (subject == null)
            {
                return(0.0);
            }

            // get science value
            // - the stock system 'degrade' science value after each credit, we don't
            float R       = ResearchAndDevelopment.GetReferenceDataValue((float)size, subject);
            float S       = subject.science;
            float C       = subject.scienceCap;
            float credits = Mathf.Max(Mathf.Min(S + Mathf.Min(R, C), C) - S, 0.0f);

            // credit the science
            subject.science        += credits;
            subject.scientificValue = ResearchAndDevelopment.GetSubjectValue(subject.science, subject);
            credits *= HighLogic.CurrentGame.Parameters.Career.ScienceGainMultiplier;
            ResearchAndDevelopment.Instance.AddScience(credits, transmitted ? TransactionReasons.ScienceTransmission : TransactionReasons.VesselRecovery);

            // fire game event
            // - this could be slow or a no-op, depending on the number of listeners
            //   in any case, we are buffering the transmitting data and calling this
            //   function only once in a while
            GameEvents.OnScienceRecieved.Fire(credits, subject, pv, false);

            // return amount of science credited
            return(credits);
        }
Esempio n. 3
0
        public void AddScienceToRnDSubject(double scienceValue)
        {
            if (!ExistsInRnD)
            {
                CreateSubjectInRnD();
            }

            RnDSubject.science         = Math.Min((float)(RnDSubject.science + scienceValue), RnDSubject.scienceCap);
            RnDSubject.scientificValue = ResearchAndDevelopment.GetSubjectValue(RnDSubject.science, RnDSubject);
        }
Esempio n. 4
0
        /// <summary>
        /// Gets the subject with the specified ID as a floating-point fraction.
        /// </summary>
        /// <param name="subjectID"></param>
        /// <returns></returns>
        public static float Get(string subjectID)
        {
            if (ResearchAndDevelopment.Instance == null)
            {
                return(1);                                         // it's a sandbox game
            }
            ScienceSubject subject = ResearchAndDevelopment.GetSubjectByID(subjectID);

            // subject will be null if we've never retrieved this science result before
            return((subject == null) ? 1 : ResearchAndDevelopment.GetSubjectValue(subject.science, subject));
        }
Esempio n. 5
0
        /// <summary>
        /// Add science points to the RnD stock subject (create it if necessary), do it recursively for any included subject, then credit the total science gained.
        /// </summary>
        /// <param name="scienceValue">science point amount</param>
        /// <param name="showMessage">if true, the "subject completed" message will be shown on screen if scienceValue is enough to complete the subject</param>
        /// <param name="fromVessel">passed to the OnScienceRecieved gameevent on subject completion. Can be null if not available</param>
        /// <param name="file">if not null, the "subject completed" completed message will use the result text stored in the file. If null, it will be a generic message</param>
        /// <returns>The amount of science credited, accounting for the subject + included subjects remaining science value</returns>
        public double RetrieveScience(double scienceValue, bool showMessage = false, ProtoVessel fromVessel = null, File file = null)
        {
            if (!ExistsInRnD)
            {
                CreateSubjectInRnD();
            }

            double scienceRetrieved = Math.Min(ScienceRemainingToRetrieve, scienceValue);

            if (!API.preventScienceCrediting)
            {
                ScienceDB.uncreditedScience += scienceRetrieved;
            }

            // fire subject completed events
            int timesCompleted = UpdateSubjectCompletion(scienceValue);

            if (timesCompleted > 0)
            {
                OnSubjectCompleted(showMessage, fromVessel, file);
            }

            RnDSubject.science         = Math.Min((float)(RnDSubject.science + scienceValue), RnDSubject.scienceCap);
            RnDSubject.scientificValue = ResearchAndDevelopment.GetSubjectValue(RnDSubject.science, RnDSubject);

            if (API.subjectsReceivedEventEnabled)
            {
                bool exists = false;
                for (int i = 0; i < ScienceDB.subjectsReceivedBuffer.Count; i++)
                {
                    if (ScienceDB.subjectsReceivedBuffer[i].id == RnDSubject.id)
                    {
                        ScienceDB.subjectsReceivedValueBuffer[i] += scienceRetrieved;
                        exists = true;
                        break;
                    }
                }
                if (!exists)
                {
                    ScienceDB.subjectsReceivedBuffer.Add(RnDSubject);
                    ScienceDB.subjectsReceivedValueBuffer.Add(scienceRetrieved);
                }
            }

            foreach (SubjectData overridenSubject in IncludedSubjects)
            {
                scienceRetrieved += overridenSubject.RetrieveScience(scienceValue, showMessage && overridenSubject.TimesCompleted == 0, fromVessel);
            }

            return(scienceRetrieved);
        }
Esempio n. 6
0
        /* ************************************************************************************************
        * Function Name: DoScience
        * Input: Position of the target, whether or not we're dealing with the FungEye or CactEye optics,
        *          the current field of view, and a screenshot.
        * Output: None
        * Purpose: This function will generate a science report based on the input parameters. This is an
        * override of a function prototype. This will generate a science report based on the target
        * celestial body. Science reports will only be generated if the target is a celestial body,
        * if the target is not the sun, if the target is visible in the scope, and if the telescope
        * is zoomed in far enough.
        * ************************************************************************************************/
        public override string DoScience(Vector3 TargetPosition, float scienceMultiplier, float FOV, Texture2D Screenshot)
        {
            CelestialBody Target = FlightGlobals.Bodies.Find(n => n.GetName() == FlightGlobals.fetch.VesselTarget.GetName());
            CelestialBody Home   = this.vessel.mainBody;

            //Sandbox or Career mode logic handled by gui.
            //if (HighLogic.CurrentGame.Mode == Game.Modes.SANDBOX)
            //{
            //    //CactEyeGUI.DisplayText("Science experiments unavailable in sandbox mode!");
            //    return;
            //}
            if (FlightGlobals.fetch.VesselTarget.GetType().Name != "CelestialBody")
            {
                //Invalid target type
                if (CactEyeConfig.DebugMode)
                {
                    Debug.Log("CactEye 2: Wide Field Camera: Invalid Target Type.");
                }
                return(Type + ": Invalid Target Type.");
            }
            else if (Target == FlightGlobals.Bodies[0])
            {
                //Cannot target the sun
                if (CactEyeConfig.DebugMode)
                {
                    Debug.Log("CactEye 2: Wide Field Camera: Cannot target the sun.");
                }
                return(Type + ": Cannot target the sun.");
            }
            else if (TargetPosition == new Vector3(-1, -1, 0))
            {
                //target not in scope
                if (CactEyeConfig.DebugMode)
                {
                    Debug.Log("CactEye 2: Wide Field Camera: Target not in scope.");
                }
                return(Type + ": Target not in scope field of view.");
            }

            //This has a tendency to be rather tempermental. If a player is getting false "Scope not zoomed in far enough" errors,
            //then the values here will need to be adjusted.
            else if (FOV > CactEyeAPI.bodySize[Target] * 50f)
            {
                //Scope not zoomed in far enough
                if (CactEyeConfig.DebugMode)
                {
                    Debug.Log("CactEye 2: Wide Field Camera: Scope not zoomed in far enough.");
                    Debug.Log("CactEye 2: Wide Field Camera: " + FOV.ToString());
                    Debug.Log("CactEye 2: Wide Field Camera: " + (CactEyeAPI.bodySize[Target] * 50f).ToString());
                }
                return(Type + ": Scope not zoomed in far enough.");
            }

            //Check to see if target is blocked.
            else if (CactEyeAPI.CheckOccult(Target) != "")
            {
                if (CactEyeConfig.DebugMode)
                {
                    Debug.Log("CactEye 2: Target is occulted by another body.");
                }
                return(Type + ": Target is occulted by another body.");
            }

            else
            {
                float             SciencePoints       = 0f;
                float             ScienceAdjustedCap  = 0f;
                float             ScienceAvailableCap = 0f;
                string            TargetName          = Target.name;
                ScienceExperiment WideFieldExperiment;
                ScienceSubject    WideFieldSubject;

                bool          withParent;
                CelestialBody parentBody;


                ExperimentID = "CactEyePlanetary";
                try
                {
                    WideFieldExperiment    = ResearchAndDevelopment.GetExperiment(ExperimentID);
                    WideFieldSubject       = ResearchAndDevelopment.GetExperimentSubject(WideFieldExperiment, ExperimentSituations.InSpaceHigh, Target, "VisualObservation" + Target.name, "");
                    WideFieldSubject.title = "CactEye Visual Planetary Observation of " + Target.name;
                    SciencePoints          = WideFieldExperiment.baseValue * WideFieldExperiment.dataScale * maxScience * scienceMultiplier;
                    if (CactEyeConfig.DebugMode)
                    {
                        Debug.Log("Cacteye 2: SciencePoints: " + SciencePoints);
                        Debug.Log("Cacteye 2: Current Science: " + WideFieldSubject.science);
                        Debug.Log("Cacteye 2: Current Cap: " + WideFieldSubject.scienceCap);
                        Debug.Log("Cacteye 2: ScienceValue: " + WideFieldSubject.scientificValue);
                        Debug.Log("Cacteye 2: SubjectValue: " + ResearchAndDevelopment.GetSubjectValue(SciencePoints, WideFieldSubject));
                        Debug.Log("Cacteye 2: RnDScienceValue: " + ResearchAndDevelopment.GetScienceValue(SciencePoints, WideFieldSubject, 1.0f));
                        Debug.Log("Cacteye 2: RnDReferenceDataValue: " + ResearchAndDevelopment.GetReferenceDataValue(SciencePoints, WideFieldSubject));
                    }
                    //Modify Science cap and points gathered based on telescope and processor
                    ScienceAdjustedCap = WideFieldExperiment.scienceCap * WideFieldExperiment.dataScale * maxScience * scienceMultiplier;

                    //Since it's not clear how KSP figures science points, reverse engineer based off of what this will return.
                    ScienceAvailableCap = ScienceAdjustedCap - ((SciencePoints / ResearchAndDevelopment.GetScienceValue(SciencePoints, WideFieldSubject, 1.0f)) * WideFieldSubject.science);
                    if (CactEyeConfig.DebugMode)
                    {
                        Debug.Log("Cacteye 2: Adjusted Cap: " + ScienceAdjustedCap);
                        Debug.Log("Cacteye 2: Available Cap: " + ScienceAvailableCap);
                    }
                    if (ScienceAvailableCap < 0)
                    {
                        ScienceAvailableCap = 0;
                    }
                    if (SciencePoints > ScienceAvailableCap)
                    {
                        SciencePoints = ScienceAvailableCap;
                    }


                    if (CactEyeConfig.DebugMode)
                    {
                        Debug.Log("CactEye 2: SciencePoints: " + SciencePoints.ToString());
                    }


                    ScienceData Data = new ScienceData(SciencePoints, 1f, 0f, WideFieldSubject.id, WideFieldSubject.title);
                    StoredData.Add(Data);
                    ReviewData(Data, Screenshot);
                    if (RBWrapper.APIRBReady)
                    {
                        Debug.Log("CactEye 2: Wrapper ready");

                        RBWrapper.CelestialBodyInfo cbi;

                        RBWrapper.RBactualAPI.CelestialBodies.TryGetValue(Target, out cbi);
                        if (!cbi.isResearched)
                        {
                            int RBFoundScience = (int)(8f * WideFieldExperiment.dataScale);
                            RBWrapper.RBactualAPI.FoundBody(RBFoundScience, Target, out withParent, out parentBody);
                        }
                        else
                        {
                            System.Random rnd = new System.Random();
                            RBWrapper.RBactualAPI.Research(Target, rnd.Next(1, 11));
                        }
                    }
                    else
                    {
                        Debug.Log("CactEye 2: Wrapper not ready");
                    }
                }

                catch (Exception e)
                {
                    Debug.Log("CactEye 2: Excpetion 5: Was not able to find Experiment with ExperimentID: " + ExperimentID.ToString());
                    Debug.Log(e.ToString());

                    return("An error occurred. Please post on the Official CactEye 2 thread on the Kerbal Forums.");
                }

                return("");
            }
        }