// consume EC for transmission, and transmit science data public static void Update(Vessel v, VesselData vd, ResourceInfo ec, double elapsed_s) { // do nothing if science system is disabled if (!Features.Science) { return; } // consume ec for transmitters ec.Consume(vd.Connection.ec_idle * elapsed_s, ResourceBroker.CommsIdle); // avoid corner-case when RnD isn't live during scene changes // - this avoid losing science if the buffer reach threshold during a scene change if (HighLogic.CurrentGame.Mode != Game.Modes.SANDBOX && ResearchAndDevelopment.Instance == null) { return; } // clear list of files transmitted vd.filesTransmitted.Clear(); // check connection if (vd.Connection == null || !vd.Connection.linked || vd.Connection.rate <= 0.0 || !vd.deviceTransmit || ec.Amount < vd.Connection.ec_idle * elapsed_s) { // reset all files transmit rate foreach (Drive drive in Drive.GetDrives(vd, true)) { foreach (File f in drive.files.Values) { f.transmitRate = 0.0; } } // do nothing else return; } double totalTransmitCapacity = vd.Connection.rate * elapsed_s; double remainingTransmitCapacity = totalTransmitCapacity; GetFilesToTransmit(v, vd); if (xmitFiles.Count == 0) { return; } UnityEngine.Profiling.Profiler.BeginSample("Kerbalism.Science.Update-Loop"); // traverse the list in reverse because : // - warp cache files are at the end, and they are always transmitted regerdless of transmit capacity // - others files are next, sorted in science value per MB ascending order for (int i = xmitFiles.Count - 1; i >= 0; i--) { XmitFile xmitFile = xmitFiles[i]; if (xmitFile.file.size == 0.0) { continue; } // always transmit everything in the warp cache if (!xmitFile.isInWarpCache && remainingTransmitCapacity <= 0.0) { break; } // determine how much data is transmitted double transmitted = xmitFile.isInWarpCache ? xmitFile.file.size : Math.Min(xmitFile.file.size, remainingTransmitCapacity); if (transmitted == 0.0) { continue; } // consume transmit capacity remainingTransmitCapacity -= transmitted; // get science value double xmitScienceValue = transmitted * xmitFile.sciencePerMB; // consume data in the file xmitFile.file.size -= transmitted; // remove science collected (ignoring final science value clamped to subject completion) xmitFile.file.subjectData.RemoveScienceCollectedInFlight(xmitScienceValue); // save transmit rate for the file, and add it to the VesselData list of files being transmitted if (xmitFile.isInWarpCache && xmitFile.realDriveFile != null) { xmitFile.realDriveFile.transmitRate = transmitted / elapsed_s; vd.filesTransmitted.Add(xmitFile.realDriveFile); } else { xmitFile.file.transmitRate = transmitted / elapsed_s; vd.filesTransmitted.Add(xmitFile.file); } if (xmitScienceValue > 0.0) { // add science to the subject (and eventually included subjects), trigger completion events, credit the science, return how much has been credited. vd.scienceTransmitted += xmitFile.file.subjectData.RetrieveScience(xmitScienceValue, true, v.protoVessel, xmitFile.file); } } UnityEngine.Profiling.Profiler.EndSample(); // consume EC cost for transmission (ec_idle is consumed above) double transmittedCapacity = totalTransmitCapacity - remainingTransmitCapacity; double transmissionCost = (vd.Connection.ec - vd.Connection.ec_idle) * (transmittedCapacity / (vd.Connection.rate * elapsed_s)); ec.Consume(transmissionCost * elapsed_s, ResourceBroker.CommsXmit); }
// consume EC for transmission, and transmit science data public static void Update(Vessel v, VesselData vd, ResourceInfo ec, double elapsed_s) { // do nothing if science system is disabled if (!Features.Science) { return; } // consume ec for transmitters ec.Consume(vd.Connection.ec_idle * elapsed_s, ResourceBroker.CommsIdle); // avoid corner-case when RnD isn't live during scene changes // - this avoid losing science if the buffer reach threshold during a scene change if (HighLogic.CurrentGame.Mode != Game.Modes.SANDBOX && ResearchAndDevelopment.Instance == null) { return; } // clear list of files transmitted vd.filesTransmitted.Clear(); // check connection if (vd.Connection == null || !vd.Connection.linked || vd.Connection.rate <= 0.0 || !vd.deviceTransmit || ec.Amount < vd.Connection.ec_idle * elapsed_s) { // reset all files transmit rate foreach (Drive drive in Drive.GetDrives(vd, true)) { foreach (File f in drive.files.Values) { f.transmitRate = 0.0; } } // do nothing else return; } double totalTransmitCapacity = vd.Connection.rate * elapsed_s; double remainingTransmitCapacity = totalTransmitCapacity; double scienceCredited = 0.0; GetFilesToTransmit(v, vd); if (xmitFiles.Count == 0) { return; } UnityEngine.Profiling.Profiler.BeginSample("Kerbalism.Science.Update-Loop"); // traverse the list in reverse because : // - warp cache files are at the end, and they are always transmitted regerdless of transmit capacity // - others files are next, sorted in science value per MB ascending order for (int i = xmitFiles.Count - 1; i >= 0; i--) { XmitFile xmitFile = xmitFiles[i]; if (xmitFile.file.size == 0.0) { continue; } // always transmit everything in the warp cache if (!xmitFile.isInWarpCache && remainingTransmitCapacity <= 0.0) { break; } // determine how much data is transmitted double transmitted = xmitFile.isInWarpCache ? xmitFile.file.size : Math.Min(xmitFile.file.size, remainingTransmitCapacity); if (transmitted == 0.0) { continue; } // consume transmit capacity remainingTransmitCapacity -= transmitted; // get science value double xmitScienceValue = transmitted * xmitFile.sciencePerMB; // consume data in the file xmitFile.file.size -= transmitted; // remove science collected (ignoring final science value clamped to subject completion) xmitFile.file.subjectData.RemoveScienceCollectedInFlight(xmitScienceValue); // fire subject completed events int timesCompleted = xmitFile.file.subjectData.UpdateSubjectCompletion(xmitScienceValue); if (timesCompleted > 0) { SubjectXmitCompleted(xmitFile.file, timesCompleted, v); } // save transmit rate for the file, and add it to the VesselData list of files being transmitted if (xmitFile.isInWarpCache && xmitFile.realDriveFile != null) { xmitFile.realDriveFile.transmitRate = transmitted / elapsed_s; vd.filesTransmitted.Add(xmitFile.realDriveFile); } else { xmitFile.file.transmitRate = transmitted / elapsed_s; vd.filesTransmitted.Add(xmitFile.file); } // clamp science value to subject max value xmitScienceValue = Math.Min(xmitScienceValue, xmitFile.file.subjectData.ScienceRemainingToRetrieve); if (xmitScienceValue > 0.0) { // add credits scienceCredited += xmitScienceValue; // credit the subject xmitFile.file.subjectData.AddScienceToRnDSubject(xmitScienceValue); } } UnityEngine.Profiling.Profiler.EndSample(); vd.scienceTransmitted += scienceCredited; // consume EC cost for transmission (ec_idle is consumed above) double transmittedCapacity = totalTransmitCapacity - remainingTransmitCapacity; double transmissionCost = (vd.Connection.ec - vd.Connection.ec_idle) * (transmittedCapacity / vd.Connection.rate); ec.Consume(transmissionCost, ResourceBroker.CommsXmit); UnityEngine.Profiling.Profiler.BeginSample("Kerbalism.Science.Update-AddScience"); // Add science points, but wait until we have at least 0.1 points to add because AddScience is VERY slow // We don't use "TransactionReasons.ScienceTransmission" because AddScience fire multiple events not meant to be fired continuously // this avoid many side issues (ex : chatterer transmit sound playing continously, strategia "+0.0 science" popup...) ScienceDB.uncreditedScience += scienceCredited; if (ScienceDB.uncreditedScience > 0.1) { if (GameHasRnD) { ResearchAndDevelopment.Instance.AddScience((float)ScienceDB.uncreditedScience, TransactionReasons.None); } ScienceDB.uncreditedScience = 0.0; } UnityEngine.Profiling.Profiler.EndSample(); }