protected void saveState()
 {
     if (HighLogic.LoadedSceneIsFlight)
     {
         ConfigNode config   = PluginHelper.getPluginSaveFile();
         string     vesselID = vessel.id.ToString();
         if (config.HasNode("VESSEL_SEISMIC_PROBE_" + vesselID))
         {
             ConfigNode probe_node = config.GetNode("VESSEL_SEISMIC_PROBE_" + vesselID);
             if (probe_node.HasValue("is_active"))
             {
                 probe_node.SetValue("is_active", probeIsEnabled.ToString());
             }
             else
             {
                 probe_node.AddValue("is_active", probeIsEnabled.ToString());
             }
             if (probe_node.HasValue("celestial_body"))
             {
                 probe_node.SetValue("celestial_body", vessel.mainBody.flightGlobalsIndex.ToString());
             }
             else
             {
                 probe_node.AddValue("celestial_body", vessel.mainBody.flightGlobalsIndex.ToString());
             }
         }
         else
         {
             ConfigNode probe_node = config.AddNode("VESSEL_SEISMIC_PROBE_" + vesselID);
             probe_node.AddValue("is_active", probeIsEnabled.ToString());
             probe_node.AddValue("celestial_body", vessel.mainBody.flightGlobalsIndex.ToString());
         }
         config.Save(PluginHelper.getPluginSaveFilePath());
     }
 }
 protected override void cleanUpScienceData()
 {
     if (science_vess_ref != null)
     {
         ConfigNode config = PluginHelper.getPluginSaveFile();
         if (config.HasNode("SEISMIC_SCIENCE_" + vessel.mainBody.name.ToUpper()))
         {
             ConfigNode planet_data = config.GetNode("SEISMIC_SCIENCE_" + vessel.mainBody.name.ToUpper());
             if (planet_data.HasNode(science_vess_ref))
             {
                 ConfigNode impact_node = planet_data.GetNode(science_vess_ref);
                 if (impact_node.HasValue("transmitted"))
                 {
                     impact_node.SetValue("transmitted", "True");
                 }
                 config.Save(PluginHelper.getPluginSaveFilePath());
             }
         }
     }
 }
Example #3
0
        public void onVesselAboutToBeDestroyed(EventReport report)
        {
            Debug.Log("[KSP Interstellar] Handling Impactor");

            ConfigNode config;
            ConfigNode science_node;

            Vessel vessel = report.origin.vessel;
            float  vesselMass;
            int    science_experiment_number = 0;

            string vessel_impact_node_string  = string.Concat("IMPACT_", vessel.id.ToString());
            string vessel_seismic_node_string = string.Concat("SEISMIC_SCIENCE_", vessel.mainBody.name.ToUpper());

            // Do nothing if we don't have a vessel.  This seems improbable, but who knows.
            if (vessel == null)
            {
                Debug.Log("[KSP Interstellar] Impactor: Ignored because the vessel is undefined.");
                return;
            }

            // Do nothing if we have recorded an impact less than 10 physics updates ago.  This probably means this call
            // is a duplicate of a previous call.
            if (Planetarium.GetUniversalTime() - this.lastImpactTime < TimeWarp.fixedDeltaTime * 10f)
            {
                Debug.Log("[KSP Interstellar] Impactor: Ignored because we've just recorded an impact.");
                return;
            }

            // Do nothing if we are a debris item less than ten physics-updates old.  That probably means we were
            // generated by a recently-recorded impact.
            if (vessel.vesselType == VesselType.Debris && vessel.missionTime < Time.fixedDeltaTime * 10f)
            {
                Debug.Log("[KSP Interstellar] Impactor: Ignored due to vessel being brand-new debris.");
                return;
            }

            vesselMass = vessel.GetTotalMass();

            // Do nothing if we aren't very near the terrain.  Note that using heightFromTerrain probably allows
            // impactors against the ocean floor... good luck.
            float vesselDimension = vessel.MOI.magnitude / vesselMass;

            if (vessel.heightFromSurface > Mathf.Max(vesselDimension, 0.75f))
            {
                Debug.Log("[KSP Interstellar] Impactor: Ignored due to vessel altitude being too high.");
                return;
            }

            // Do nothing if we aren't impacting the surface.
            if (!(
                    report.other.ToLower().Contains(string.Intern("surface")) ||
                    report.other.ToLower().Contains(string.Intern("terrain")) ||
                    report.other.ToLower().Contains(vessel.mainBody.name.ToLower())
                    ))
            {
                Debug.Log("[KSP Interstellar] Impactor: Ignored due to not impacting the surface.");
                return;
            }

            /*
             * NOTE: This is a deviation from current KSPI behavior.  KSPI currently registers an impact over 40 m/s
             * regardless of its mass; this means that trivially light impactors (single instruments, even) could
             * trigger the experiment.
             *
             * The guard below requires that the impactor have at least as much vertical impact energy as a 1 Mg
             * object traveling at 40 m/s.  This means that nearly-tangential impacts or very light impactors will need
             * to be much faster, but that heavier impactors may be slower.
             *
             * */
            if (
                (Math.Pow(vessel.verticalSpeed, 2d) * vesselMass / 2d < 800d) &&
                (vessel.verticalSpeed > 20d)
                )
            {
                Debug.Log("[KSP Interstellar] Impactor: Ignored due to vessel imparting too little impact energy.");
                return;
            }

            config = PluginHelper.getPluginSaveFile();
            if (config.HasNode(vessel_seismic_node_string))
            {
                science_node = config.GetNode(vessel_seismic_node_string);
                science_experiment_number = science_node.nodes.Count;

                if (science_node.HasNode(vessel_impact_node_string))
                {
                    Debug.Log("[KSP Interstellar] Impactor: Ignored because this vessel's impact has already been recorded.");
                    return;
                }
            }
            else
            {
                science_node = config.AddNode(vessel_seismic_node_string);
                science_node.AddValue("name", "interstellarseismicarchive");
            }

            int      body            = vessel.mainBody.flightGlobalsIndex;
            Vector3d net_vector      = Vector3d.zero;
            bool     first           = true;
            double   net_science     = 0;
            double   initial_science = 0;

            foreach (Vessel conf_vess in FlightGlobals.Vessels)
            {
                String vessel_probe_node_string = string.Concat("VESSEL_SEISMIC_PROBE_", conf_vess.id.ToString());

                if (config.HasNode(vessel_probe_node_string))
                {
                    ConfigNode probe_node = config.GetNode(vessel_probe_node_string);

                    // If the seismometer is inactive, skip it.
                    bool is_active = false;
                    if (probe_node.HasValue("is_active"))
                    {
                        bool.TryParse(probe_node.GetValue("is_active"), out is_active);
                        if (!is_active)
                        {
                            continue;
                        }
                    }

                    // If the seismometer is on another planet, skip it.
                    int planet = -1;
                    if (probe_node.HasValue("celestial_body"))
                    {
                        int.TryParse(probe_node.GetValue("celestial_body"), out planet);
                        if (planet != body)
                        {
                            continue;
                        }
                    }

                    // do sciency stuff
                    Vector3d surface_vector = (conf_vess.transform.position - FlightGlobals.Bodies[body].transform.position);
                    surface_vector = surface_vector.normalized;
                    if (first)
                    {
                        first           = false;
                        net_vector      = surface_vector;
                        net_science     = 50 * PluginHelper.getImpactorScienceMultiplier(body);
                        initial_science = net_science;
                    }
                    else
                    {
                        net_science += (1.0 - Vector3d.Dot(surface_vector, net_vector.normalized)) * 50 * PluginHelper.getImpactorScienceMultiplier(body);
                        net_vector   = net_vector + surface_vector;
                    }
                }
            }

            net_science = Math.Min(net_science, initial_science * 3.5); // no more than 3.5x boost to science by using multiple detectors
            if (net_science > 0 && !double.IsInfinity(net_science) && !double.IsNaN(net_science))
            {
                double science_coeff = -science_experiment_number / 2.0;
                net_science = net_science * Math.Exp(science_coeff);
                ScreenMessages.PostScreenMessage("Impact Recorded, science report can now be accessed from one of your accelerometers deployed on this body.", 5f, ScreenMessageStyle.UPPER_CENTER);
                this.lastImpactTime = Planetarium.GetUniversalTime();
                Debug.Log("[KSP Interstellar] Impactor: Impact registered!");

                ConfigNode impact_node = new ConfigNode(vessel_impact_node_string);
                impact_node.AddValue(string.Intern("transmitted"), bool.FalseString);
                impact_node.AddValue(string.Intern("vesselname"), vessel.vesselName);
                impact_node.AddValue(string.Intern("science"), net_science);
                impact_node.AddValue(string.Intern("number"), (science_experiment_number + 1).ToString("0"));
                science_node.AddNode(impact_node);

                config.Save(PluginHelper.getPluginSaveFilePath());
            }
        }
        public override void OnFixedUpdate()
        {
            String[] resources_to_supply = { FNResourceManager.FNRESOURCE_MEGAJOULES, FNResourceManager.FNRESOURCE_WASTEHEAT };
            this.resources_to_supply = resources_to_supply;

            base.OnFixedUpdate();

            ConfigNode config          = PluginHelper.getPluginSaveFile();
            float      powerInputIncr  = 0;
            float      powerInputRelay = 0;
            int        activeSatsIncr  = 0;
            float      rangelosses     = 0;

            if (config != null && IsEnabled)
            {
                if (getResourceBarRatio(FNResourceManager.FNRESOURCE_WASTEHEAT) >= 0.95)
                {
                    IsEnabled = false;
                    deactivate_timer++;
                    if (FlightGlobals.ActiveVessel == vessel && deactivate_timer > 2)
                    {
                        ScreenMessages.PostScreenMessage("Warning Dangerous Overheating Detected: Emergency microwave power shutdown occuring NOW!", 5.0f, ScreenMessageStyle.UPPER_CENTER);
                    }
                    return;
                }
                deactivate_timer = 0;

                //Check to see if active vessel is a relay - for now we do not want a relay to connect to another relay to prevent energy loops
                String aid = vessel.id.ToString();
                if (config.HasValue(aid) == true)
                {
                    String agenType = config.GetValue(aid + "type");
                    if (agenType == "relay")
                    {
                        aIsRelay = true;
                    }
                    else
                    {
                        aIsRelay = false;
                    }
                }

                //if (activeCount % 100 == 0) {
                List <Vessel> vessels = FlightGlobals.Vessels;
                //print(vessels.Count.ToString() + "\n");

                //loop through vessels and attempt to add any active sattilites
                foreach (Vessel vess in vessels)
                {
                    String vid   = vess.id.ToString();
                    String vname = vess.vesselName.ToString().ToLower();
                    //print(vid + "\n");

                    //prevent adding active vessel as sat, skip calculations on debris, only add vessels with config value and line of sight to active vessel
                    if (vess.isActiveVessel == false && vname.IndexOf("debris") == -1 && config.HasValue(vid) == true && lineOfSightTo(vess) == true)
                    {
                        String powerinputsat = config.GetValue(vid);
                        String vgenType      = config.GetValue(vid + "type");
                        // if sat is not relay/nuclear check that it has line of site to sun
                        // NOTE: we need to add a check for relay to check lineOfSiteToSource(vess), and if solar a lineOfSiteFromSourceToSun - to check that the source which it is relaying is still attached to it, and if it is a solar source that it is recieving solar energy
                        if ((vgenType == "solar" && PluginHelper.lineOfSightToSun(vess)) || vgenType == "relay" || vgenType == "nuclear")
                        {
                            float inputPowerFixedAlt = 0;                                    // = float.Parse (powerinputsat) * PluginHelper.getSatFloatCurve ().Evaluate ((float)FlightGlobals.Bodies [0].GetAltitude (vess.transform.position));
                            float distance           = (float)Vector3d.Distance(vessel.transform.position, vess.transform.position);
                            float powerdissip        = (float)(Math.Tan(angle) * distance * Math.Tan(angle) * distance);
                            powerdissip = Math.Max(powerdissip / collectorArea, 1);
                            if (vgenType != "relay" && inputPowerFixedAlt > 0)
                            {
                                rangelosses += powerdissip;
                                //Scale energy reception based on angle of reciever to transmitter
                                Vector3d direction_vector = (vess.transform.position - vessel.transform.position).normalized;
                                float    facing_factor    = Vector3.Dot(part.transform.up, direction_vector);
                                facing_factor   = Mathf.Max(0, facing_factor);
                                powerInputIncr += inputPowerFixedAlt / powerdissip * facing_factor;
                                activeSatsIncr++;
                                connectedrelaysf = 0;
                                //print ("warp: sat added - genType: " + vgenType);
                            }
                            // only attach to one relay IF no sattilites are available for direct connection
                            else if (aIsRelay == false && activeSatsIncr < 1 && inputPowerFixedAlt > 0)
                            {
                                rangelosses = powerdissip;
                                //Scale energy reception based on angle of reciever to transmitter
                                Vector3d direction_vector = (vess.transform.position - vessel.transform.position).normalized;
                                float    facing_factor    = Vector3.Dot(part.transform.up, direction_vector);
                                facing_factor    = Mathf.Max(0, facing_factor);
                                powerInputRelay  = inputPowerFixedAlt / powerdissip * facing_factor;
                                connectedrelaysf = 1;
                                activeSatsIncr   = 0;
                                //print ("warp: relay added");
                            }
                        }
                    }
                }

                float atmosphericefficiency = (float)Math.Exp(-FlightGlobals.getStaticPressure(vessel.transform.position) / 5);

                if (activeSatsIncr > 0 && powerInputIncr > 0)
                {
                    this.rangelosses = rangelosses / activeSatsIncr;
                    totefff          = efficiency * atmosphericefficiency * 100 / rangelosses;
                    powerInput       = powerInputIncr * efficiency * atmosphericefficiency;
                    connectedsatsf   = activeSatsIncr;
                    //print ("warp: connected sat");
                }
                else if (connectedrelaysf > 0 && powerInputRelay > 0)
                {
                    this.rangelosses = rangelosses / connectedrelaysf;
                    totefff          = efficiency * atmosphericefficiency * 100 / rangelosses;
                    powerInput       = powerInputRelay * efficiency * atmosphericefficiency;
                    connectedsatsf   = 0;
                    //print("warp: connected relay");
                }
                else
                {
                    connectedrelaysf = 0;
                    connectedsatsf   = 0;
                    powerInput       = 0;
                    //print ("warp: no active sats or relays available");
                }
                //}
            }
            else
            {
                connectedrelaysf = 0;
                connectedsatsf   = 0;
                powerInput       = 0;
            }


            float powerInputMegajoules = powerInput / 1000.0f;

            supplyFNResource(powerInputMegajoules * TimeWarp.fixedDeltaTime, FNResourceManager.FNRESOURCE_MEGAJOULES);
            float waste_head_production = powerInput / 1000.0f / efficiency * (1.0f - efficiency);

            supplyFNResource(waste_head_production * TimeWarp.fixedDeltaTime, FNResourceManager.FNRESOURCE_WASTEHEAT);
            //activeCount++;
        }
        public override void OnFixedUpdate()
        {
            activeCount++;
            nuclear_power         = 0;
            solar_power           = 0;
            displayed_solar_power = 0;
            if (IsEnabled && !relay)
            {
                double powerDraw = 0.0;

                try
                {
                    ORSResourceManager manager = getOvermanagerForResource(FNResourceManager.FNRESOURCE_MEGAJOULES).getManagerForVessel(vessel);
                    if (manager != null)
                    {
                        powerDraw = manager.PowerDraws.Where(pm => !(pm.Key is MicrowavePowerTransmitter && (pm.Key as MicrowavePowerTransmitter) == this)).Sum(pm => pm.Value);
                    }
                }
                catch (ArgumentNullException)
                {
                    powerDraw = 0.0;
                }

                foreach (FNGenerator generator in generators)
                {
                    if (generator.isActive())
                    {
                        FNThermalSource thermal_source = generator.getThermalSource();
                        if (thermal_source != null && !thermal_source.isVolatileSource() && thermal_source.isActive())
                        {
                            double output = generator.getMaxPowerOutput();
                            output -= powerDraw / (double)generators.Count(g => g.isActive() && g.getThermalSource().isActive());
                            output  = output * transmitPower / 100.0;
                            double gpower = consumeFNResource(output * TimeWarp.fixedDeltaTime, FNResourceManager.FNRESOURCE_MEGAJOULES);
                            nuclear_power += gpower * 1000 / TimeWarp.fixedDeltaTime;
                        }
                    }
                }

                foreach (ModuleDeployableSolarPanel panel in panels)
                {
                    double output          = panel.flowRate;
                    double spower          = part.RequestResource("ElectricCharge", output * TimeWarp.fixedDeltaTime);
                    double inv_square_mult = Math.Pow(Vector3d.Distance(FlightGlobals.Bodies[PluginHelper.REF_BODY_KERBIN].transform.position, FlightGlobals.Bodies[PluginHelper.REF_BODY_KERBOL].transform.position), 2) / Math.Pow(Vector3d.Distance(vessel.transform.position, FlightGlobals.Bodies[PluginHelper.REF_BODY_KERBOL].transform.position), 2);
                    displayed_solar_power += spower / TimeWarp.fixedDeltaTime;
                    //scale solar power to what it would be in Kerbin orbit for file storage
                    solar_power += spower / TimeWarp.fixedDeltaTime / inv_square_mult;
                }
            }

            if (double.IsInfinity(nuclear_power) || double.IsNaN(nuclear_power))
            {
                nuclear_power = 0;
            }

            if (double.IsInfinity(solar_power) || double.IsNaN(solar_power))
            {
                solar_power = 0;
            }

            if (activeCount % 1000 == 9)
            {
                ConfigNode config   = PluginHelper.getPluginSaveFile();
                string     vesselID = vessel.id.ToString();
                if (config.HasNode("VESSEL_MICROWAVE_POWER_" + vesselID))
                {
                    ConfigNode power_node = config.GetNode("VESSEL_MICROWAVE_POWER_" + vesselID);
                    if (power_node.HasValue("nuclear_power"))
                    {
                        power_node.SetValue("nuclear_power", MicrowavePowerTransmitter.getEnumeratedNuclearPowerForVessel(vessel).ToString("E"));
                    }
                    else
                    {
                        power_node.AddValue("nuclear_power", MicrowavePowerTransmitter.getEnumeratedNuclearPowerForVessel(vessel).ToString("E"));
                    }
                    if (power_node.HasValue("solar_power"))
                    {
                        power_node.SetValue("solar_power", MicrowavePowerTransmitter.getEnumeratedSolarPowerForVessel(vessel).ToString("E"));
                    }
                    else
                    {
                        power_node.AddValue("solar_power", MicrowavePowerTransmitter.getEnumeratedSolarPowerForVessel(vessel).ToString("E"));
                    }
                }
                else
                {
                    ConfigNode power_node = config.AddNode("VESSEL_MICROWAVE_POWER_" + vesselID);
                    power_node.AddValue("nuclear_power", MicrowavePowerTransmitter.getEnumeratedNuclearPowerForVessel(vessel).ToString("E"));
                    power_node.AddValue("solar_power", MicrowavePowerTransmitter.getEnumeratedSolarPowerForVessel(vessel).ToString("E"));
                }

                if (config.HasNode("VESSEL_MICROWAVE_RELAY_" + vesselID))
                {
                    ConfigNode relay_node = config.GetNode("VESSEL_MICROWAVE_RELAY_" + vesselID);
                    if (relay_node.HasValue("relay"))
                    {
                        relay_node.SetValue("relay", MicrowavePowerTransmitter.vesselIsRelay(vessel).ToString());
                    }
                    else
                    {
                        relay_node.AddValue("relay", MicrowavePowerTransmitter.vesselIsRelay(vessel).ToString());
                    }
                }
                else
                {
                    ConfigNode relay_node = config.AddNode("VESSEL_MICROWAVE_RELAY_" + vesselID);
                    relay_node.AddValue("relay", MicrowavePowerTransmitter.vesselIsRelay(vessel).ToString());
                }

                config.Save(PluginHelper.getPluginSaveFilePath());
            }
            activeCount++;
        }
Example #6
0
        public override void OnFixedUpdate()
        {
            activeCount++;


            if (IsEnabled)
            {
                List <Part> vesselparts = vessel.parts;
                float       electrical_current_available = 0;
                for (int i = 0; i < vesselparts.Count; ++i)
                {
                    Part           cPart = vesselparts.ElementAt(i);
                    PartModuleList pml   = cPart.Modules;
                    for (int j = 0; j < pml.Count; ++j)
                    {
                        var curFNGen    = pml.GetModule(j) as FNGenerator;
                        var curMwRec    = pml.GetModule(j) as MicrowavePowerReceiver;
                        var curSolarPan = pml.GetModule(j) as ModuleDeployableSolarPanel;
                        if (curFNGen != null)
                        {
                            float consumeMJ = curFNGen.getMaxPowerOutput() * TimeWarp.fixedDeltaTime;
                            float cvalue    = consumeFNResource(consumeMJ, FNResourceManager.FNRESOURCE_MEGAJOULES);
                            electrical_current_available = cvalue * 1000 / TimeWarp.fixedDeltaTime;
                            nuclear = true;
                        }
                        else if (curMwRec != null && nuclear == false)
                        {
                            //electrical_current_available = curMwRec.powerInput;
                            part.RequestResource("ElectricCharge", electrical_current_available * TimeWarp.fixedDeltaTime);
                            microwave = true;
                        }
                        else if (curSolarPan != null && nuclear == false && microwave == false)
                        {
                            electrical_current_available += curSolarPan.flowRate;
                            part.RequestResource("ElectricCharge", electrical_current_available * TimeWarp.fixedDeltaTime);
                            solar = true;
                        }
                    }
                }
                inputPower = electrical_current_available;
            }
            else
            {
                inputPower = 0;
            }

            if (activeCount % 1000 == 9)
            {
                ConfigNode config  = PluginHelper.getPluginSaveFile();
                string     genType = "undefined";

                //float inputPowerFixedAlt = (float) ((double)inputPower * (Math.Pow(FlightGlobals.Bodies[0].GetAltitude(vessel.transform.position), 2)) / PluginHelper.FIXED_SAT_ALTITUDE / PluginHelper.FIXED_SAT_ALTITUDE);
                float inputPowerFixedAlt = 0;
                if (nuclear == true)
                {
                    inputPowerFixedAlt = inputPower;
                    //print ("warp: nuclear inputPower " + inputPowerFixedAlt);
                    genType = "nuclear";
                }
                else if (microwave == true)
                {
                    inputPowerFixedAlt = inputPower;
                    //print ("warp: relay inputPower " + inputPowerFixedAlt);
                    genType = "relay";
                }
                else if (solar == true)
                {
                    //inputPowerFixedAlt = inputPower / PluginHelper.getSatFloatCurve ().Evaluate ((float)FlightGlobals.Bodies [0].GetAltitude (vessel.transform.position));
                    //print ("warp: solar inputPower " + inputPowerFixedAlt);
                    genType = "solar";
                }

                if (genType != "undefined")
                {
                    string vesselIDSolar = vessel.id.ToString();
                    string outputPower   = inputPowerFixedAlt.ToString("0.000");
                    if (!config.HasValue(vesselIDSolar))
                    {
                        config.AddValue(vesselIDSolar, outputPower);
                    }
                    else
                    {
                        config.SetValue(vesselIDSolar, outputPower);
                    }

                    if (!config.HasValue(vesselIDSolar + "type"))
                    {
                        config.AddValue(vesselIDSolar + "type", genType);
                    }
                    else
                    {
                        config.SetValue(vesselIDSolar + "type", genType);
                    }

                    config.Save(PluginHelper.getPluginSaveFilePath());
                }
            }
        }
Example #7
0
        public override void OnStart(PartModule.StartState state)
        {
            if (state == StartState.Editor)
            {
                return;
            }
            reprocessor  = new FuelReprocessor(part);
            anti_factory = new AntimatterFactory(part);
            ConfigNode config = PluginHelper.getPluginSaveFile();

            part.force_activate();

            anim  = part.FindModelAnimators(animName1).FirstOrDefault();
            anim2 = part.FindModelAnimators(animName2).FirstOrDefault();
            if (anim != null && anim2 != null)
            {
                anim[animName1].layer  = 1;
                anim2[animName2].layer = 1;
                if (IsEnabled)
                {
                    //anim [animName1].normalizedTime = 1f;
                    //anim2 [animName2].normalizedTime = 1f;
                    //anim [animName1].speed = -1f;
                    //anim2 [animName2].speed = -1f;
                    anim.Blend(animName1, 1, 0);
                    anim2.Blend(animName2, 1, 0);
                }
                else
                {
                    //anim [animName1].normalizedTime = 0f;
                    //anim2 [animName2].normalizedTime = 0f;
                    //anim [animName1].speed = 1f;
                    //anim2 [animName2].speed = 1f;
                    //anim.Blend (animName1, 0, 0);
                    //anim2.Blend (animName2, 0, 0);
                    play_down = false;
                }
                //anim.Play ();
                //anim2.Play ();
            }

            if (IsEnabled && last_active_time != 0)
            {
                float global_rate_multipliers = 1;
                crew_capacity_ratio     = ((float)part.protoModuleCrew.Count) / ((float)part.CrewCapacity);
                global_rate_multipliers = global_rate_multipliers * crew_capacity_ratio;

                if (active_mode == 0)
                { // Science persistence
                    double now                 = Planetarium.GetUniversalTime();
                    double time_diff           = now - last_active_time;
                    float  altitude_multiplier = (float)(vessel.altitude / (vessel.mainBody.Radius));
                    altitude_multiplier = Math.Max(altitude_multiplier, 1);
                    float stupidity = 0;
                    foreach (ProtoCrewMember proto_crew_member in part.protoModuleCrew)
                    {
                        stupidity += proto_crew_member.stupidity;
                    }
                    stupidity = 1.5f - stupidity / 2.0f;
                    double science_to_add = GameConstants.baseScienceRate * time_diff / 86400 * electrical_power_ratio * stupidity * global_rate_multipliers * PluginHelper.getScienceMultiplier(vessel.mainBody.flightGlobalsIndex, vessel.LandedOrSplashed) / ((float)Math.Sqrt(altitude_multiplier));
                    //Debug.Log(science_to_add);
                    //Debug.Log(GameConstants.baseScienceRate);
                    //Debug.Log(time_diff);
                    //Debug.Log(electrical_power_ratio);
                    //Debug.Log(stupidity);
                    //Debug.Log(global_rate_multipliers);
                    //Debug.Log(PluginHelper.getScienceMultiplier(vessel.mainBody.flightGlobalsIndex, vessel.LandedOrSplashed));
                    //Debug.Log(altitude_multiplier);
                    //part.RequestResource ("Science", -science_to_add);
                    science_awaiting_addition = science_to_add;
                }
                else if (active_mode == 2)
                { // Antimatter persistence
                    double now       = Planetarium.GetUniversalTime();
                    double time_diff = now - last_active_time;

                    List <PartResource> partresources = new List <PartResource>();
                    part.GetConnectedResources(PartResourceLibrary.Instance.GetDefinition("Antimatter").id, PartResourceLibrary.Instance.GetDefinition("Antimatter").resourceFlowMode, partresources);
                    float currentAntimatter_missing = 0;
                    foreach (PartResource partresource in partresources)
                    {
                        currentAntimatter_missing += (float)(partresource.maxAmount - partresource.amount);
                    }



                    float  total_electrical_power_provided = (float)(electrical_power_ratio * (GameConstants.baseAMFPowerConsumption + GameConstants.basePowerConsumption) * 1E6);
                    double antimatter_mass = total_electrical_power_provided / GameConstants.warpspeed / GameConstants.warpspeed * 1E6 / 20000.0;
                    float  antimatter_peristence_to_add = (float)-Math.Min(currentAntimatter_missing, antimatter_mass * time_diff);
                    part.RequestResource("Antimatter", antimatter_peristence_to_add);
                }
            }
        }
        public override void OnStart(PartModule.StartState state)
        {
            String[] resources_to_supply = { FNResourceManager.FNRESOURCE_MEGAJOULES, FNResourceManager.FNRESOURCE_WASTEHEAT, FNResourceManager.FNRESOURCE_THERMALPOWER };
            this.resources_to_supply = resources_to_supply;
            base.OnStart(state);
            if (state == StartState.Editor)
            {
                return;
            }

            if (part.FindModulesImplementing <MicrowavePowerTransmitter>().Count == 1)
            {
                part_transmitter = part.FindModulesImplementing <MicrowavePowerTransmitter>().First();
                has_transmitter  = true;
            }

            if (animTName != null)
            {
                animT = part.FindModelAnimators(animTName).FirstOrDefault();
                if (animT != null)
                {
                    animT[animTName].layer          = 1;
                    animT[animTName].normalizedTime = 0f;
                    animT[animTName].speed          = 0.001f;
                    animT.Play();
                }
            }

            if (animName != null)
            {
                anim = part.FindModelAnimators(animName).FirstOrDefault();
                if (anim != null)
                {
                    anim[animName].layer = 1;
                    if (connectedsatsi > 0 || connectedrelaysi > 0)
                    {
                        anim[animName].normalizedTime = 1f;
                        anim[animName].speed          = -1f;
                    }
                    else
                    {
                        anim[animName].normalizedTime = 0f;
                        anim[animName].speed          = 1f;
                    }
                    anim.Play();
                }
            }
            vmps = new List <VesselMicrowavePersistence>();
            vrps = new List <VesselRelayPersistence>();
            ConfigNode config = PluginHelper.getPluginSaveFile();

            foreach (Vessel vess in FlightGlobals.Vessels)
            {
                String vesselID = vess.id.ToString();

                if (vess.isActiveVessel == false && vess.vesselName.ToLower().IndexOf("debris") == -1)
                {
                    if (config.HasNode("VESSEL_MICROWAVE_POWER_" + vesselID))
                    {
                        ConfigNode power_node    = config.GetNode("VESSEL_MICROWAVE_POWER_" + vesselID);
                        double     nuclear_power = 0;
                        double     solar_power   = 0;
                        if (power_node.HasValue("nuclear_power"))
                        {
                            nuclear_power = double.Parse(power_node.GetValue("nuclear_power"));
                        }
                        if (power_node.HasValue("solar_power"))
                        {
                            solar_power = double.Parse(power_node.GetValue("solar_power"));
                        }
                        if (nuclear_power > 0 || solar_power > 0)
                        {
                            VesselMicrowavePersistence vmp = new VesselMicrowavePersistence(vess);
                            vmp.setSolarPower(solar_power);
                            vmp.setNuclearPower(nuclear_power);
                            vmps.Add(vmp);
                        }
                    }

                    if (config.HasNode("VESSEL_MICROWAVE_RELAY_" + vesselID))
                    {
                        ConfigNode relay_node = config.GetNode("VESSEL_MICROWAVE_RELAY_" + vesselID);
                        if (relay_node.HasValue("relay"))
                        {
                            bool relay = bool.Parse(relay_node.GetValue("relay"));
                            if (relay)
                            {
                                VesselRelayPersistence vrp = new VesselRelayPersistence(vess);
                                vrp.setActive(relay);
                                vrps.Add(vrp);
                            }
                        }
                    }
                }
            }
            penaltyFreeDistance = Math.Sqrt(1 / ((microwaveAngleTan * microwaveAngleTan) / collectorArea));

            this.part.force_activate();
        }
        protected override bool generateScienceData()
        {
            ScienceExperiment experiment = ResearchAndDevelopment.GetExperiment("FNSeismicProbeExperiment");

            if (experiment == null)
            {
                return(false);
            }
            //ScienceSubject subject = ResearchAndDevelopment.GetExperimentSubject(experiment, ExperimentSituations.SrfLanded, vessel.mainBody, "surface");
            //if (subject == null) {
            //    return false;
            //}
            //subject.scientificValue = 1;
            //subject.scienceCap = float.MaxValue;
            //subject.science = 1;
            //subject.subjectValue = 1;
            result_title   = "Impactor Experiment";
            result_string  = "No useful seismic data has been recorded.";
            transmit_value = 0;
            recovery_value = 0;
            data_size      = 0;
            xmit_scalar    = 1;
            ref_value      = 1;

            // science_data = new ScienceData(0, 1, 0, subject.id, "data");

            ConfigNode config = PluginHelper.getPluginSaveFile();

            if (config.HasNode("SEISMIC_SCIENCE_" + vessel.mainBody.name.ToUpper()))
            {
                ConfigNode planet_data = config.GetNode("SEISMIC_SCIENCE_" + vessel.mainBody.name.ToUpper());
                foreach (ConfigNode probe_data in planet_data.nodes)
                {
                    if (probe_data.name.Contains("IMPACT_"))
                    {
                        science_vess_ref = probe_data.name;
                        bool   transmitted    = false;
                        string vessel_name    = "";
                        float  science_amount = 0;
                        int    exp_number     = 1;
                        if (probe_data.HasValue("transmitted"))
                        {
                            transmitted = bool.Parse(probe_data.GetValue("transmitted"));
                        }
                        if (probe_data.HasValue("vesselname"))
                        {
                            vessel_name = probe_data.GetValue("vesselname");
                        }
                        if (probe_data.HasValue("science"))
                        {
                            science_amount = float.Parse(probe_data.GetValue("science"));
                        }
                        if (probe_data.HasValue("number"))
                        {
                            exp_number = int.Parse(probe_data.GetValue("number"));
                        }
                        if (!transmitted)
                        {
                            ScienceSubject subject = ResearchAndDevelopment.GetExperimentSubject(experiment, ExperimentSituations.SrfLanded, vessel.mainBody, vessel.mainBody.name + "'s surface.");
                            if (subject == null)
                            {
                                return(false);
                            }
                            result_string           = vessel_name + " impacted into " + vessel.mainBody.name + " producing seismic activity.  From this data, information on the structure of " + vessel.mainBody.name + "'s crust can be determined.";
                            transmit_value          = science_amount;
                            recovery_value          = science_amount;
                            subject.subjectValue    = 1;
                            subject.scientificValue = 1;
                            subject.scienceCap      = 50 * PluginHelper.getImpactorScienceMultiplier(vessel.mainBody.flightGlobalsIndex) * 10;
                            //subject.science = 0;
                            data_size    = science_amount * 2.5f;
                            science_data = new ScienceData(science_amount, 1, 0, subject.id, "Impactor Data");
                            ref_value    = 50 * PluginHelper.getImpactorScienceMultiplier(vessel.mainBody.flightGlobalsIndex);
                            return(true);
                        }
                    }
                }
            }
            return(false);
        }