/// <summary> /// Creates a new instance of the Experiment class. /// </summary> /// <param name="experiment">The ScienceExperiment to be used.</param> /// <param name="situation">The Situation this experiment is valid in.</param> /// <param name="onboardScience">A collection of all onboard ScienceData.</param> public ScienceInstance(ScienceExperiment experiment, Situation situation, ScienceContext Sci) { _experiment = experiment; _situation = situation; ScienceSubject = null; Update(Sci); }
/// <summary> /// Creates a new instance of the Experiment class. /// </summary> /// <param name="experiment">The ScienceExperiment to be used.</param> /// <param name="situation">The Situation this experiment is valid in.</param> /// <param name="onboardScience">A collection of all onboard ScienceData.</param> public ScienceInstance( ScienceExperiment experiment, Situation situation, ScienceContext Sci ) { _experiment = experiment; _situation = situation; ScienceSubject = null; Update( Sci ); }
/// <summary> /// Calls the Update method on all experiments. /// </summary> public void UpdateExperiments( ) { var StartTime = DateTime.Now; // _logger.Trace( "UpdateExperiments" ); ScienceContext Sci = new ScienceContext( ); // _logger.Trace( "onboardScience contains " + onboardScience.Count() + " items" ); // _logger.Trace( "AllExperiments contains " + AllExperiments.Count( ) + " items" ); // _logger.Trace( "SciDict contains " + SciDict.Count( ) + " items" ); // foreach( var K in SciDict.Keys ) // _logger.Trace( K + "=" + SciDict[K].title ); foreach (var exp in AllScienceInstances) { exp.Update(Sci); } var Elapsed = DateTime.Now - StartTime; _logger.Trace("UpdateExperiments Done - " + Elapsed.ToString( ) + "ms"); }
/// <summary> /// Updates the IsUnlocked, CompletedScience, TotalScience, OnboardScience, and IsComplete fields. /// </summary> /// <param name="onboardScience">The total onboard ScienceData.</param> public void Update(ScienceContext Sci) { if (Sci.ScienceSubjects.ContainsKey(Id)) { ScienceSubject = Sci.ScienceSubjects[Id]; } else { ScienceSubject = new ScienceSubject(ScienceExperiment, Situation.ExperimentSituation, Situation.Body.CelestialBody, Situation.SubBiome ?? Situation.Biome ?? string.Empty); } IsUnlocked = Sci.UnlockedInstruments.IsUnlocked(ScienceExperiment.id) && (Situation.Body.Reached != null); CompletedScience = ScienceSubject.science * HighLogic.CurrentGame.Parameters.Career.ScienceGainMultiplier; TotalScience = ScienceSubject.scienceCap * HighLogic.CurrentGame.Parameters.Career.ScienceGainMultiplier; IsComplete = CompletedScience > TotalScience || TotalScience - CompletedScience < 0.1; var multiplier = ScienceExperiment.baseValue / ScienceExperiment.scienceCap; OnboardScience = 0; if (Sci.OnboardScienceList.ContainsKey(ScienceSubject.id)) { var data = Sci.OnboardScienceList[ScienceSubject.id]; // var _logger = new Logger( "Experiment" ); // _logger.Trace( ScienceSubject.id + " found " + data.Count( ) + " items" ); for (int x = 0; x < data.Count; x++) { var next = (TotalScience - (CompletedScience + OnboardScience)) * multiplier; OnboardScience += next; } } var AllCollectedScience = CompletedScience + OnboardScience; IsCollected = AllCollectedScience > TotalScience || TotalScience - AllCollectedScience < 0.1; }
/// <summary> /// Updates the IsUnlocked, CompletedScience, TotalScience, OnboardScience, and IsComplete fields. /// </summary> /// <param name="onboardScience">The total onboard ScienceData.</param> public void Update(ScienceContext Sci) { if (Sci.ScienceSubjects.ContainsKey(Id)) { ScienceSubject = Sci.ScienceSubjects[Id]; } else { ScienceSubject = new ScienceSubject(ScienceExperiment, Situation.ExperimentSituation, Situation.Body.CelestialBody, Situation.SubBiome ?? Situation.Biome ?? string.Empty); } // Check if given body is reached first. We don't have to check if experiment's part is unlocked if body has not been reached. // If compiler didn't optimized the test, it should be much faster. IsUnlocked = Situation.Body.Reached && Sci.UnlockedInstruments.IsUnlocked(ScienceExperiment.id); CompletedScience = ScienceSubject.science * HighLogic.CurrentGame.Parameters.Career.ScienceGainMultiplier; TotalScience = ScienceSubject.scienceCap * HighLogic.CurrentGame.Parameters.Career.ScienceGainMultiplier; IsComplete = CompletedScience > TotalScience || TotalScience - CompletedScience < 0.1; var multiplier = ScienceExperiment.baseValue / ScienceExperiment.scienceCap; OnboardScience = 0; if (Sci.OnboardScienceList.ContainsKey(ScienceSubject.id)) { var data = Sci.OnboardScienceList[ScienceSubject.id]; // var _logger = new Logger( "Experiment" ); // _logger.Trace( ScienceSubject.id + " found " + data.Count( ) + " items" ); for (int x = 0; x < data.Count; x++) { var next = (TotalScience - (CompletedScience + OnboardScience)) * multiplier; OnboardScience += next; } } var AllCollectedScience = CompletedScience + OnboardScience; IsCollected = AllCollectedScience > TotalScience || TotalScience - AllCollectedScience < 0.1; }
/// <summary> /// Refreshes the experiment cache. THIS IS VERY EXPENSIVE. /// CB: Actually doesn't seem much worse than UpdateExperiments() /// </summary> public void RefreshExperimentCache( ) { // Init var StartTime = DateTime.Now; ScienceContext Sci = new ScienceContext( ); BodySituationFilter BodyFilter = new BodySituationFilter( ); // _logger.Info( "RefreshExperimentCache" ); // Quick check for things we depend on if( ResearchAndDevelopment.Instance == null || PartLoader.Instance == null ) { _logger.Debug( "ResearchAndDevelopment and PartLoader must be instantiated." ); AllScienceInstances = new List<ScienceInstance>( ); UpdateFilter( ); return; } // Temporary experiment list var exps = new List<ScienceInstance>( ); // Unlocked experiment list UnlockedInstrumentList.Clear( ); // Loop around all experiments foreach( var X in Sci.Experiments ) { var experiment = X.Key; //_logger.Trace( experiment.experimentTitle ); // Where the experiment is possible uint sitMask = experiment.situationMask; uint biomeMask = experiment.biomeMask; /* Need to look at public bool BiomeIsRelevantWhile( ExperimentSituations situation ); public bool IsAvailableWhile( ExperimentSituations situation, CelestialBody body ); On ScienceExperiment */ // OrbitalScience support - where the experiment is possible if( sitMask == 0 && Sci.Experiments[ experiment ] != null ) { var sitMaskField = Sci.Experiments[ experiment ].GetType( ).GetField( "sitMask" ); if( sitMaskField != null ) { sitMask = (uint)(int)sitMaskField.GetValue( Sci.Experiments[ experiment ] ); // _logger.Trace( "Setting sitMask to " + sitMask + " for " + experiment.experimentTitle ); } if( biomeMask == 0 ) { var biomeMaskField = Sci.Experiments[ experiment ].GetType( ).GetField( "bioMask" ); if( biomeMaskField != null ) { biomeMask = (uint)(int)biomeMaskField.GetValue( Sci.Experiments[ experiment ] ); // _logger.Trace( "Setting biomeMask to " + biomeMask + " for " + experiment.experimentTitle ); } } } List<ExperimentSituations> SituationList = Enum.GetValues( typeof( ExperimentSituations ) ).Cast<ExperimentSituations>( ).ToList<ExperimentSituations>( ); List<Body> BodyList = new List<Body>( Sci.BodyList.Values.ToList( ) ); // Check for CelestialBodyFilter if( Sci.Experiments[ experiment ] != null ) { // _logger.Trace( Sci.Experiments[ experiment ].experimentID ); if( CelestialBodyFilters.Filters.HasValue( Sci.Experiments[ experiment ].experimentID ) ) { string FilterText = CelestialBodyFilters.Filters.GetValue( Sci.Experiments[ experiment ].experimentID ); BodyFilter.Filter( BodyList, SituationList, FilterText ); } } // Check this experiment in all biomes on all bodies foreach( var body in BodyList ) { if( experiment.requireAtmosphere && !body.HasAtmosphere ) continue; // If the whole planet doesn't have an atmosphere, then there's not much point continuing. foreach( var situation in SituationList ) { if( situation == ExperimentSituations.SrfSplashed && !body.HasOcean ) continue; // Some planets don't have an ocean for us to be splashed down in. if( situation == ExperimentSituations.SrfLanded && !body.HasSurface ) continue; // Jool and the Sun don't have a surface. if( ( situation == ExperimentSituations.FlyingHigh || situation == ExperimentSituations.FlyingLow ) && !body.HasAtmosphere ) continue; // Some planets don't have an atmosphere for us to fly in. if( ( sitMask & (uint)situation ) == 0 ) continue; // This experiment isn't valid for our current situation. if( body.Biomes.Any( ) && ( biomeMask & (uint)situation ) != 0 ) { foreach( var biome in body.Biomes ) exps.Add( new ScienceInstance( experiment, new Situation( body, situation, biome ), Sci ) ); } else exps.Add( new ScienceInstance( experiment, new Situation( body, situation ), Sci ) ); } } // Can't really avoid magic constants here - Kerbin and Shores if( ( ( sitMask & (uint)ExperimentSituations.SrfLanded ) != 0 ) && ( ( biomeMask & (uint)ExperimentSituations.SrfLanded ) != 0 ) ) { if( Sci.Kerbin != null && Sci.KscBiomes.Count > 0 ) { if( BodyList.Contains( Sci.BodyList[ Sci.Kerbin ] ) ) // If we haven't filtered it out { // _logger.Trace( "BabyBiomes " + experiment.experimentTitle + ": " + sitMask ); foreach( var kscBiome in Sci.KscBiomes ) // Ew. exps.Add( new ScienceInstance( experiment, new Situation( Sci.BodyList[ Sci.Kerbin ], ExperimentSituations.SrfLanded, "Shores", kscBiome ), Sci ) ); } } } } // Done replace the old list with the new one AllScienceInstances = exps; // We need to redo the filter UpdateFilter( ); var Elapsed = DateTime.Now - StartTime; _logger.Trace( "RefreshExperimentCache Done - " + Elapsed.ToString( ) + "ms" ); }
/// <summary> /// Calls the Update method on all experiments. /// </summary> public void UpdateExperiments( ) { var StartTime = DateTime.Now; // _logger.Trace( "UpdateExperiments" ); ScienceContext Sci = new ScienceContext( ); // _logger.Trace( "onboardScience contains " + onboardScience.Count() + " items" ); // _logger.Trace( "AllExperiments contains " + AllExperiments.Count( ) + " items" ); // _logger.Trace( "SciDict contains " + SciDict.Count( ) + " items" ); // foreach( var K in SciDict.Keys ) // _logger.Trace( K + "=" + SciDict[K].title ); foreach( var exp in AllScienceInstances ) { exp.Update( Sci ); } var Elapsed = DateTime.Now - StartTime; _logger.Trace( "UpdateExperiments Done - " + Elapsed.ToString( ) + "ms" ); }
/// <summary> /// Updates the IsUnlocked, CompletedScience, TotalScience, OnboardScience, and IsComplete fields. /// </summary> /// <param name="onboardScience">The total onboard ScienceData.</param> public void Update( ScienceContext Sci ) { if( Sci.ScienceSubjects.ContainsKey( Id ) ) ScienceSubject = Sci.ScienceSubjects[ Id ]; else ScienceSubject = new ScienceSubject(ScienceExperiment, Situation.ExperimentSituation, Situation.Body.CelestialBody, Situation.SubBiome ?? Situation.Biome ?? string.Empty); IsUnlocked = UnlockedInstrumentList.IsUnlocked( ScienceExperiment.id ) && ( Situation.Body.Reached != null ); CompletedScience = ScienceSubject.science * HighLogic.CurrentGame.Parameters.Career.ScienceGainMultiplier; TotalScience = ScienceSubject.scienceCap * HighLogic.CurrentGame.Parameters.Career.ScienceGainMultiplier; IsComplete = CompletedScience > TotalScience || TotalScience - CompletedScience < 0.1; var multiplier = ScienceExperiment.baseValue / ScienceExperiment.scienceCap; OnboardScience = 0; if( Sci.OnboardScienceList.ContainsKey( ScienceSubject.id ) ) { var data = Sci.OnboardScienceList[ ScienceSubject.id ]; // var _logger = new Logger( "Experiment" ); // _logger.Trace( ScienceSubject.id + " found " + data.Count( ) + " items" ); foreach (var i in data) { var next = (TotalScience - (CompletedScience + OnboardScience)) * multiplier; OnboardScience += next; } } var AllCollectedScience = CompletedScience + OnboardScience; IsCollected = AllCollectedScience > TotalScience || TotalScience - AllCollectedScience < 0.1; }
// Called by Unity once to initialize the class, just before Update is called. public void Start( ) { _logger.Trace("Start"); if (_addonInitialized == true) { // For some reason the addon can be instantiated several times by the KSP addon loader (generally when going to/from the VAB), // even though we set onlyOnce to true in the KSPAddon attribute. HammerMusicMute( ); // Ensure we enforce music volume anyway return; } _addonInitialized = true; _active = false; // Config Config = new Config( ); Config.Load( ); // Music Muting if (Config.MusicStartsMuted) { Muted = true; ScreenMessages.PostScreenMessage("[x] Science! - Music Mute"); } GameEvents.onGameSceneSwitchRequested.Add(this.onGameSceneSwitchRequested); GameEvents.onLevelWasLoaded.Add(this.onLevelWasLoaded); // _logger.Trace( "Making DMagic Factory" ); DMagic = new DMagicFactory( ); // _logger.Trace( "Made DMagic Factory" ); // _logger.Trace( "Making ScienceContext" ); Science = new ScienceContext(this); // _logger.Trace( "Made ScienceContext" ); // Start event handlers ScienceEventHandler = new xScienceEventHandler(this); // Settings window _settingsWindow = new SettingsWindow(this); Config.UseBlizzysToolbarChanged += Settings_UseBlizzysToolbarChanged; Config.RighClickMutesMusicChanged += Settings_RighClickMutesMusicChanged; // Help window _helpWindow = new HelpWindow(this); // Status window _alertNoise = gameObject.AddComponent <Noise>( ); _statusWindow = new StatusWindow(this); _statusWindow.NoiseEvent += OnPlayNoise; _statusWindow.WindowClosed += OnStatusWindowClosed; _statusWindow.OnCloseEvent += OnStatusWindowClosed; _statusWindow.OnOpenEvent += OnStatusWindowOpened; // Checklist window _checklistWindow = new ScienceWindow(this, _settingsWindow, _helpWindow); _checklistWindow.OnCloseEvent += OnChecklistWindowClosed; _checklistWindow.OnOpenEvent += OnChecklistWindowOpened; // ShipState Window _shipStateWindow = new ShipStateWindow(this); // Save and load checklist window config when the game scene is changed // We are only visible in some scenes GameEvents.onGameSceneSwitchRequested.Add(new EventData <GameEvents.FromToAction <GameScenes, GameScenes> > .OnEvent(this.OnGameSceneSwitch)); // Callbacks for buttons - we init when the "Launcher" toolbar is ready GameEvents.onGUIApplicationLauncherReady.Add(Load); GameEvents.onGUIApplicationLauncherDestroyed.Add(Unload); // Callbacks for F2 GameEvents.onHideUI.Add(OnHideUI); GameEvents.onShowUI.Add(OnShowUI); DontDestroyOnLoad(this); _logger.Trace("Done Start"); }
/// <summary> /// Refreshes the experiment cache. THIS IS VERY EXPENSIVE. /// CB: Actually doesn't seem much worse than UpdateExperiments() /// </summary> public void RefreshExperimentCache( ) { // Init var StartTime = DateTime.Now; ScienceContext Sci = new ScienceContext( ); BodySituationFilter BodyFilter = new BodySituationFilter( ); // _logger.Info( "RefreshExperimentCache" ); // Quick check for things we depend on if (ResearchAndDevelopment.Instance == null || PartLoader.Instance == null) { _logger.Debug("ResearchAndDevelopment and PartLoader must be instantiated."); AllScienceInstances = new List <ScienceInstance>( ); UpdateFilter( ); return; } // Temporary experiment list var exps = new List <ScienceInstance>( ); // Unlocked experiment list UnlockedInstrumentList.Clear( ); // Loop around all experiments foreach (var X in Sci.Experiments) { var experiment = X.Key; //_logger.Trace( experiment.experimentTitle ); // Where the experiment is possible uint sitMask = experiment.situationMask; uint biomeMask = experiment.biomeMask; /* Need to look at * public bool BiomeIsRelevantWhile( ExperimentSituations situation ); * public bool IsAvailableWhile( ExperimentSituations situation, CelestialBody body ); * On ScienceExperiment */ // OrbitalScience support - where the experiment is possible if (sitMask == 0 && Sci.Experiments[experiment] != null) { var sitMaskField = Sci.Experiments[experiment].GetType( ).GetField("sitMask"); if (sitMaskField != null) { sitMask = (uint)(int)sitMaskField.GetValue(Sci.Experiments[experiment]); // _logger.Trace( "Setting sitMask to " + sitMask + " for " + experiment.experimentTitle ); } if (biomeMask == 0) { var biomeMaskField = Sci.Experiments[experiment].GetType( ).GetField("bioMask"); if (biomeMaskField != null) { biomeMask = (uint)(int)biomeMaskField.GetValue(Sci.Experiments[experiment]); // _logger.Trace( "Setting biomeMask to " + biomeMask + " for " + experiment.experimentTitle ); } } } List <ExperimentSituations> SituationList = Enum.GetValues(typeof(ExperimentSituations)).Cast <ExperimentSituations>( ).ToList <ExperimentSituations>( ); List <Body> BodyList = new List <Body>(Sci.BodyList.Values.ToList( )); // Check for CelestialBodyFilter if (Sci.Experiments[experiment] != null) { // _logger.Trace( Sci.Experiments[ experiment ].experimentID ); if (CelestialBodyFilters.Filters.HasValue(Sci.Experiments[experiment].experimentID)) { string FilterText = CelestialBodyFilters.Filters.GetValue(Sci.Experiments[experiment].experimentID); BodyFilter.Filter(BodyList, SituationList, FilterText); } } // Check this experiment in all biomes on all bodies foreach (var body in BodyList) { if (experiment.requireAtmosphere && !body.HasAtmosphere) { continue; // If the whole planet doesn't have an atmosphere, then there's not much point continuing. } foreach (var situation in SituationList) { if (situation == ExperimentSituations.SrfSplashed && !body.HasOcean) { continue; // Some planets don't have an ocean for us to be splashed down in. } if (situation == ExperimentSituations.SrfLanded && !body.HasSurface) { continue; // Jool and the Sun don't have a surface. } if ((situation == ExperimentSituations.FlyingHigh || situation == ExperimentSituations.FlyingLow) && !body.HasAtmosphere) { continue; // Some planets don't have an atmosphere for us to fly in. } if ((sitMask & (uint)situation) == 0) { continue; // This experiment isn't valid for our current situation. } if (body.Biomes.Any( ) && (biomeMask & (uint)situation) != 0) { foreach (var biome in body.Biomes) { exps.Add(new ScienceInstance(experiment, new Situation(body, situation, biome), Sci)); } } else { exps.Add(new ScienceInstance(experiment, new Situation(body, situation), Sci)); } } } // Can't really avoid magic constants here - Kerbin and Shores if (((sitMask & (uint)ExperimentSituations.SrfLanded) != 0) && ((biomeMask & (uint)ExperimentSituations.SrfLanded) != 0)) { if (Sci.Kerbin != null && Sci.KscBiomes.Count > 0) { if (BodyList.Contains(Sci.BodyList[Sci.Kerbin])) // If we haven't filtered it out { // _logger.Trace( "BabyBiomes " + experiment.experimentTitle + ": " + sitMask ); foreach (var kscBiome in Sci.KscBiomes) // Ew. { exps.Add(new ScienceInstance(experiment, new Situation(Sci.BodyList[Sci.Kerbin], ExperimentSituations.SrfLanded, "Shores", kscBiome), Sci)); } } } } } // Done replace the old list with the new one AllScienceInstances = exps; // We need to redo the filter UpdateFilter( ); var Elapsed = DateTime.Now - StartTime; _logger.Trace("RefreshExperimentCache Done - " + Elapsed.ToString( ) + "ms"); }