From 97a87a8d84aafebe93c899424b9ea43de7bf3f35 Mon Sep 17 00:00:00 2001 From: hvacengi Date: Fri, 2 Dec 2016 16:42:08 -0500 Subject: [PATCH] Fix science transmit value Fixes #1795 ScienceExperimentFields.cs * Protect ScienceValue method from null ref for subjectByID * TransmitValue now ues ExperimentResultDialogPage to get the transmit value, ensuring it replicates the display readout (partial fix for #1835) --- .../ScienceExperimentFields.cs | 4 ++- src/kOS/Suffixed/ScienceDataValue.cs | 31 +++++++++++++------ 2 files changed, 25 insertions(+), 10 deletions(-) diff --git a/src/kOS/Suffixed/PartModuleField/ScienceExperimentFields.cs b/src/kOS/Suffixed/PartModuleField/ScienceExperimentFields.cs index cb78e79c2..f10be8797 100644 --- a/src/kOS/Suffixed/PartModuleField/ScienceExperimentFields.cs +++ b/src/kOS/Suffixed/PartModuleField/ScienceExperimentFields.cs @@ -11,10 +11,12 @@ namespace kOS.Suffixed.PartModuleField [kOS.Safe.Utilities.KOSNomenclature("ScienceExperimentModule")] public abstract class ScienceExperimentFields : PartModuleFields { + protected global::Part part; protected IScienceDataContainer container; public ScienceExperimentFields(PartModule module, SharedObjects shared) : base(module, shared) { this.container = module as IScienceDataContainer; + part = module.part; if (container == null) { @@ -54,7 +56,7 @@ public virtual bool HasData() public virtual ListValue Data() { - return new ListValue(container.GetData().Select(s => new ScienceDataValue(s)).Cast()); + return new ListValue(container.GetData().Select(s => new ScienceDataValue(s, part)).Cast()); } public virtual void DumpData() diff --git a/src/kOS/Suffixed/ScienceDataValue.cs b/src/kOS/Suffixed/ScienceDataValue.cs index 458bfaf57..8e811c13f 100644 --- a/src/kOS/Suffixed/ScienceDataValue.cs +++ b/src/kOS/Suffixed/ScienceDataValue.cs @@ -8,10 +8,12 @@ namespace kOS.Suffixed public class ScienceDataValue : Structure { private ScienceData scienceData; + private global::Part hostPart; - public ScienceDataValue(ScienceData scienceData) + public ScienceDataValue(ScienceData scienceData, global::Part hostPart) { this.scienceData = scienceData; + this.hostPart = hostPart; InitializeSuffixes(); } @@ -27,18 +29,29 @@ private void InitializeSuffixes() public float ScienceValue() { ScienceSubject subjectByID = ResearchAndDevelopment.GetSubjectByID(scienceData.subjectID); - - return ResearchAndDevelopment.GetScienceValue(scienceData.dataAmount, subjectByID, 1) * - HighLogic.CurrentGame.Parameters.Career.ScienceGainMultiplier; + + if (subjectByID != null) // fix return values in sandbox mode + { + return ResearchAndDevelopment.GetScienceValue(scienceData.dataAmount, subjectByID, 1) * + HighLogic.CurrentGame.Parameters.Career.ScienceGainMultiplier; + } + else + { + return 0; + } } public float TransmitValue() { - ScienceSubject subjectByID = ResearchAndDevelopment.GetSubjectByID(scienceData.subjectID); - - // TODO: make sure transmitValue became transmitBonus - return ResearchAndDevelopment.GetScienceValue(scienceData.dataAmount, subjectByID, scienceData.transmitBonus) * - HighLogic.CurrentGame.Parameters.Career.ScienceGainMultiplier; + // By using ExperimentResultDialogPage we ensure that the logic calculating the value is exactly the same + // as that used KSP's dialog. The page type doesn't include any UI code itself, it just does the math to + // confirm the values, and stores some callbacks for the UI to call when buttons are pressed. + ExperimentResultDialogPage page = new ExperimentResultDialogPage( + hostPart, scienceData, scienceData.baseTransmitValue, scienceData.transmitBonus, // the parameters with data we care aboue + false, "", false, // disable transmit warning and reset option, these are used for the UI only + new ScienceLabSearch(hostPart.vessel, scienceData), // this is used to calculate the transmit bonus, I think... + null, null, null, null); // null callbacks, no sense in creating objects when we won't actually perform the callback. + return page.baseTransmitValue * page.TransmitBonus; } public new string ToString()