// 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); }
// 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); }
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); }
/// <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)); }
/// <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); }
/* ************************************************************************************************ * 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(""); } }