Ejemplo n.º 1
0
        public KeyValuePair <bool, double> modReturn;               // Return from DeviceEC

        public override void OnStart(StartState state)
        {
            // don't break tutorial scenarios & do something only in Flight scenario
            if (Lib.DisableScenario(this) || !Lib.IsFlight())
            {
                return;
            }

            // cache list of modules
            module = part.FindModulesImplementing <PartModule>().FindLast(k => k.moduleName == type);

            // get energy from cache
            resources = ResourceCache.GetResource(vessel, "ElectricCharge");
            hasEnergy = resources.Amount > double.Epsilon;

            // Force the update to run at least once
            lastBrokenState       = !isBroken;
            hasEnergyChanged      = !hasEnergy;
            hasFixedEnergyChanged = !hasEnergy;

#if DEBUG
            // setup UI
            Fields["actualCost"].guiActive = true;
            Fields["isBroken"].guiActive   = true;
#endif
        }
Ejemplo n.º 2
0
        void Indicator_ec(Panel p, Vessel v, VesselData vd)
        {
#if !KSP15_16
            if (v.vesselType == VesselType.DeployedScienceController)
            {
                return;
            }
#endif

            ResourceInfo ec            = ResourceCache.GetResource(v, "ElectricCharge");
            Supply       supply        = Profile.supplies.Find(k => k.resource == "ElectricCharge");
            double       low_threshold = supply != null ? supply.low_threshold : 0.15;
            double       depletion     = ec.DepletionTime();

            string tooltip = Lib.BuildString
                             (
                "<align=left /><b>", Local.Monitor_name, "\t", Local.Monitor_level, "\t" + Local.Monitor_duration, "</b>\n",                                                           //name"level"duration
                Lib.Color(Lib.BuildString("EC\t", Lib.HumanReadablePerc(ec.Level), "\t", depletion <= double.Epsilon ? Local.Monitor_depleted : Lib.HumanReadableDuration(depletion)), //"depleted"
                          ec.Level <= 0.005 ? Lib.Kolor.Red : ec.Level <= low_threshold ? Lib.Kolor.Orange : Lib.Kolor.None)
                             );

            Texture2D image = ec.Level <= 0.005
                          ? Textures.battery_red
                          : ec.Level <= low_threshold
                          ? Textures.battery_yellow
                          : Textures.battery_white;

            p.AddRightIcon(image, tooltip);
        }
Ejemplo n.º 3
0
        // execute a script
        public void Execute(Vessel v, ScriptType type)
        {
            // do nothing if there is no EC left on the vessel
            ResourceInfo ec = ResourceCache.GetResource(v, "ElectricCharge");

            if (ec.Amount <= double.Epsilon)
            {
                return;
            }

            // get the script
            Script script;

            if (scripts.TryGetValue(type, out script))
            {
                // execute the script
                script.Execute(GetModuleDevices(v));

                // show message to the user
                // - unless the script is empty (can happen when being edited)
                if (script.states.Count > 0 && v.KerbalismData().cfg_script)
                {
                    Message.Post(Lib.BuildString(Localizer.Format("#KERBALISM_UI_scriptvessel"), " <b>", v.vesselName, "</b>"));
                }
            }
        }
Ejemplo n.º 4
0
        private static bool FixedUpdatePrefix(KerbalismSentinel __instance)
        {
            if (__instance.isTrackingEnabled)
            {
                VesselData vd = __instance.vessel.KerbalismData();
                if (!vd.Connection.linked || vd.Connection.rate < __instance.comms_rate)
                {
                    __instance.isTracking = false;
                    __instance.status     = "Comms connection too weak";
                    return(false);
                }

                ResourceInfo ec = ResourceCache.GetResource(__instance.vessel, "ElectricCharge");
                ec.Consume(__instance.ec_rate * Kerbalism.elapsed_s, ResourceBroker.Scanner);

                if (ec.Amount <= double.Epsilon)
                {
                    __instance.isTracking = false;
                    __instance.status     = Local.Module_Experiment_issue4;                 // "no Electricity"
                    return(false);
                }

                __instance.isTracking = true;
            }

            return(true);
        }
Ejemplo n.º 5
0
        public static List <double> ResourceLevels(Vessel v, List <string> resource_names)
        {
            List <double> result = new List <double>(resource_names.Count);

            foreach (var name in resource_names)
            {
                result.Add(ResourceCache.GetResource(v, name).Level);
            }
            return(result);
        }
Ejemplo n.º 6
0
        public static void Update(Vessel v)
        {
            // do nothing if not an eva kerbal
            if (!v.isEVA)
            {
                return;
            }

            // get KerbalEVA module
            KerbalEVA kerbal = Lib.FindModules <KerbalEVA>(v)[0];

            // Stock KSP adds 5 units of monoprop to EVAs. We want to limit that amount
            // to whatever was available in the ship, so we don't magically create EVA prop out of nowhere
            if (Cache.HasVesselObjectsCache(v, "eva_prop"))
            {
                var quantity = Cache.VesselObjectsCache <double>(v, "eva_prop");
                Cache.RemoveVesselObjectsCache(v, "eva_prop");
                Lib.SetResource(kerbal.part, Lib.EvaPropellantName(), quantity, Lib.EvaPropellantCapacity());
            }

            // get resource handler
            ResourceInfo ec = ResourceCache.GetResource(v, "ElectricCharge");

            // determine if headlamps need ec
            // - not required if there is no EC capacity in eva kerbal (no ec supply in profile)
            // - not required if no EC cost for headlamps is specified (set by the user)
            bool need_ec = ec.Capacity > double.Epsilon && Settings.HeadLampsCost > double.Epsilon;

            // consume EC for the headlamps
            if (need_ec && kerbal.lampOn)
            {
                ec.Consume(Settings.HeadLampsCost * Kerbalism.elapsed_s, ResourceBroker.Light);
            }

            // force the headlamps on/off
            HeadLamps(kerbal, kerbal.lampOn && (!need_ec || ec.Amount > double.Epsilon));

            // if dead
            if (IsDead(v))
            {
                // enforce freezed state
                Freeze(kerbal);

                // disable modules
                DisableModules(kerbal);

                // remove plant flag action
                kerbal.flagItems = 0;
            }
        }
Ejemplo n.º 7
0
        // return total radiation emitted in a vessel
        public static double Total(Vessel v)
        {
            // get resource cache
            ResourceInfo ec = ResourceCache.GetResource(v, "ElectricCharge");

            double tot = 0.0;

            if (v.loaded)
            {
                foreach (var emitter in Lib.FindModules <Emitter>(v))
                {
                    if (ec.Amount > double.Epsilon || emitter.ec_rate <= double.Epsilon)
                    {
                        if (emitter.running)
                        {
                            if (emitter.radiation > 0)
                            {
                                tot += emitter.radiation * emitter.radiation_impact;
                            }
                            else
                            {
                                tot += emitter.radiation;                              // always account for full shielding effect
                            }
                        }
                    }
                }
            }
            else
            {
                foreach (ProtoPartModuleSnapshot m in Lib.FindModules(v.protoVessel, "Emitter"))
                {
                    if (ec.Amount > double.Epsilon || Lib.Proto.GetDouble(m, "ec_rate") <= double.Epsilon)
                    {
                        if (Lib.Proto.GetBool(m, "running"))
                        {
                            var rad = Lib.Proto.GetDouble(m, "radiation");
                            if (rad < 0)
                            {
                                tot += rad;
                            }
                            else
                            {
                                tot += rad * Lib.Proto.GetDouble(m, "radiation_factor");
                            }
                        }
                    }
                }
            }
            return(tot);
        }
Ejemplo n.º 8
0
        public override void OnUpdate()
        {
            if (!Lib.IsFlight() || module == null)
            {
                return;
            }

            // get energy from cache
            resources = ResourceCache.GetResource(vessel, "ElectricCharge");
            hasEnergy = resources.Amount > double.Epsilon;

            // Update UI only if hasEnergy has changed or if is broken state has changed
            if (isBroken)
            {
                if (isBroken != lastBrokenState)
                {
                    lastBrokenState = isBroken;
                    Update_UI(!isBroken);
                }
            }
            else if (hasEnergyChanged != hasEnergy)
            {
                Lib.LogDebugStack("Energy state has changed: {0}", hasEnergy);

                hasEnergyChanged = hasEnergy;
                lastBrokenState  = false;
                // Update UI
                Update_UI(hasEnergy);
            }
            // Constantly Update UI for special modules
            if (isBroken)
            {
                Constant_OnGUI(!isBroken);
            }
            else
            {
                Constant_OnGUI(hasEnergy);
            }

            if (!hasEnergy || isBroken)
            {
                actualCost  = 0;
                isConsuming = false;
            }
            else
            {
                isConsuming = GetIsConsuming();
            }
        }
Ejemplo n.º 9
0
        public void FixedUpdate()
        {
            // do nothing in the editor
            if (Lib.IsEditor())
            {
                return;
            }

            // if has any animation playing, consume energy.
            if (Is_consuming_energy())
            {
                // get resource handler
                ResourceInfo ec = ResourceCache.GetResource(vessel, "ElectricCharge");

                // consume ec
                ec.Consume(ec_rate * Kerbalism.elapsed_s, ResourceBroker.GravityRing);
            }
        }
Ejemplo n.º 10
0
        private void EvaluateStatus()
        {
            UnityEngine.Profiling.Profiler.BeginSample("Kerbalism.VesselData.EvaluateStatus");
            // determine if there is enough EC for a powered state
            powered = Lib.IsPowered(Vessel);

            // calculate crew info for the vessel
            crewCount    = Lib.CrewCount(Vessel);
            crewCapacity = Lib.CrewCapacity(Vessel);

            // malfunction stuff
            malfunction = Reliability.HasMalfunction(Vessel);
            critical    = Reliability.HasCriticalFailure(Vessel);

            // communications info
            connection = ConnectionInfo.Update(Vessel, powered, EnvBlackout);

            // habitat data
            habitatInfo.Update(Vessel);
            volume   = Habitat.Tot_volume(Vessel);
            surface  = Habitat.Tot_surface(Vessel);
            pressure = Math.Min(Habitat.Pressure(Vessel), habitatInfo.MaxPressure);

            evas          = (uint)(Math.Max(0, ResourceCache.GetResource(Vessel, "Nitrogen").Amount - 330) / Settings.LifeSupportAtmoLoss);
            poisoning     = Habitat.Poisoning(Vessel);
            shielding     = Habitat.Shielding(Vessel);
            livingSpace   = Habitat.Living_space(Vessel);
            volumePerCrew = Habitat.Volume_per_crew(Vessel);
            comforts      = new Comforts(Vessel, EnvLanded, crewCount > 1, connection.linked && connection.rate > double.Epsilon);

            // data about greenhouses
            greenhouses = Greenhouse.Greenhouses(Vessel);

            Drive.GetCapacity(this, out drivesFreeSpace, out drivesCapacity);

            // solar panels data
            if (Vessel.loaded)
            {
                solarPanelsAverageExposure = SolarPanelFixer.GetSolarPanelsAverageExposure(solarPanelsExposure);
                solarPanelsExposure.Clear();
            }
            UnityEngine.Profiling.Profiler.EndSample();
        }
Ejemplo n.º 11
0
        public static void Update(Vessel v)
        {
            // do nothing if not an eva kerbal
            if (!v.isEVA)
            {
                return;
            }

            // get KerbalEVA module
            KerbalEVA kerbal = Lib.FindModules <KerbalEVA>(v)[0];

            // get resource handler
            ResourceInfo ec = ResourceCache.GetResource(v, "ElectricCharge");

            // determine if headlamps need ec
            // - not required if there is no EC capacity in eva kerbal (no ec supply in profile)
            // - not required if no EC cost for headlamps is specified (set by the user)
            bool need_ec = ec.Capacity > double.Epsilon && Settings.HeadLampsCost > double.Epsilon;

            // consume EC for the headlamps
            if (need_ec && kerbal.lampOn)
            {
                ec.Consume(Settings.HeadLampsCost * Kerbalism.elapsed_s, ResourceBroker.Light);
            }

            // force the headlamps on/off
            HeadLamps(kerbal, kerbal.lampOn && (!need_ec || ec.Amount > double.Epsilon));

            // if dead
            if (IsDead(v))
            {
                // enforce freezed state
                Freeze(kerbal);

                // disable modules
                DisableModules(kerbal);

                // remove plant flag action
                kerbal.flagItems = 0;
            }
        }
Ejemplo n.º 12
0
        public void SetupRescue(Vessel v)
        {
            // do nothing if no resource on rescue
            if (on_rescue <= double.Epsilon)
            {
                return;
            }

            // if the vessel has no capacity
            if (ResourceCache.GetResource(v, resource).Capacity <= double.Epsilon)
            {
                // find the first useful part
                Part p = v.parts.Find(k => k.CrewCapacity > 0 || k.FindModuleImplementing <KerbalEVA>() != null);

                // add capacity
                Lib.AddResource(p, resource, 0.0, on_rescue);
            }

            // add resource to the vessel
            ResourceCache.Produce(v, resource, on_rescue, ResourceBroker.Generic);
        }
Ejemplo n.º 13
0
        void Indicator_supplies(Panel p, Vessel v, VesselData vd)
        {
            List <string> tooltips     = new List <string>();
            uint          max_severity = 0;

            if (vd.CrewCount > 0)
            {
                foreach (Supply supply in Profile.supplies.FindAll(k => k.resource != "ElectricCharge"))
                {
                    ResourceInfo res       = ResourceCache.GetResource(v, supply.resource);
                    double       depletion = res.DepletionTime();

                    if (res.Capacity > double.Epsilon)
                    {
                        if (tooltips.Count == 0)
                        {
                            tooltips.Add(String.Format("<align=left /><b>{0,-18}\t" + Local.Monitor_level + "\t" + Local.Monitor_duration + "</b>", Local.Monitor_name));                                             //level"duration"name"
                        }
                        tooltips.Add(Lib.Color(
                                         String.Format("{0,-18}\t{1}\t{2}", supply.resource, Lib.HumanReadablePerc(res.Level), depletion <= double.Epsilon ? Local.Monitor_depleted : Lib.HumanReadableDuration(depletion)),               //"depleted"
                                         res.Level <= 0.005 ? Lib.Kolor.Red : res.Level <= supply.low_threshold ? Lib.Kolor.Orange : Lib.Kolor.None
                                         ));

                        uint severity = res.Level <= 0.005 ? 2u : res.Level <= supply.low_threshold ? 1u : 0;
                        max_severity = Math.Max(max_severity, severity);
                    }
                }
            }

            Texture2D image = max_severity == 2
                          ? Textures.box_red
                          : max_severity == 1
                          ? Textures.box_yellow
                          : Textures.box_white;

            p.AddRightIcon(image, string.Join("\n", tooltips.ToArray()));
        }
Ejemplo n.º 14
0
        // return total radiation emitted in a vessel
        public static double Total(Vessel v)
        {
            // get resource cache
            ResourceInfo ec = ResourceCache.GetResource(v, "ElectricCharge");

            double total = 0.0;

            if (v.loaded)
            {
                foreach (var shield in Lib.FindModules <PassiveShield>(v))
                {
                    if (ec.Amount > 0 || shield.ec_rate <= 0)
                    {
                        if (shield.deployed)
                        {
                            total += shield.radiation;
                        }
                    }
                }
            }
            else
            {
                foreach (ProtoPartModuleSnapshot m in Lib.FindModules(v.protoVessel, "PassiveShield"))
                {
                    if (ec.Amount > 0 || Lib.Proto.GetDouble(m, "ec_rate") <= 0)
                    {
                        if (Lib.Proto.GetBool(m, "deployed"))
                        {
                            var rad = Lib.Proto.GetDouble(m, "radiation");
                            total += rad;
                        }
                    }
                }
            }
            return(total);
        }
Ejemplo n.º 15
0
        public void Update()
        {
            // update RMB ui
            Events["Toggle"].guiName = deployed ? Local.Generic_RETRACT : Local.Generic_DEPLOY;
            Events["Toggle"].active  = (deploy.Length > 0) && (part.FindModuleImplementing <Habitat>() == null) && !deploy_anim.Playing() && !waitRotation && ResourceCache.GetResource(vessel, "ElectricCharge").Amount > ec_rate;

            // in flight
            if (Lib.IsFlight())
            {
                // if deployed
                if (deployed)
                {
                    // if there is no ec
                    if (ResourceCache.GetResource(vessel, "ElectricCharge").Amount < 0.01)
                    {
                        // pause rotate animation
                        // - safe to pause multiple times
                        Set_rotation(false);
                    }
                    // if there is enough ec instead and is not deploying
                    else if (Should_start_rotation())
                    {
                        // resume rotate animation
                        // - safe to resume multiple times
                        Set_rotation(true);
                    }
                }
                // stop loop animation if exist and we are retracting
                else
                {
                    // Call transform.stop() if it is rotating and the Stop method wasn't called.
                    Set_rotation(false);
                }

                // When is not rotating
                if (waitRotation)
                {
                    if (rotateIsTransform && !rotate_transf.IsRotating())
                    {
                        // start retract animation in the correct direction, when is not rotating
                        if (animBackwards)
                        {
                            deploy_anim.Play(deployed, false);
                        }
                        else
                        {
                            deploy_anim.Play(!deployed, false);
                        }
                        waitRotation = false;
                    }
                    else if (!rotateIsTransform && !rotate_anim.Playing())
                    {
                        if (animBackwards)
                        {
                            deploy_anim.Play(deployed, false);
                        }
                        else
                        {
                            deploy_anim.Play(!deployed, false);
                        }
                        waitRotation = false;
                    }
                }

                if (rotateIsTransform && rotate_transf != null)
                {
                    rotate_transf.DoSpin();
                }
                if (counterWeightRotateIsTransform && counterWeightRotate_transf != null)
                {
                    Lib.Log("KGR: counterweight do spin");
                    counterWeightRotate_transf.DoSpin();
                }
            }
        }
Ejemplo n.º 16
0
 /// <summary>
 /// Return vessel shielding factor.
 /// </summary>
 public static double Shielding(Vessel v)
 {
     return(Radiation.ShieldingEfficiency(ResourceCache.GetResource(v, "Shielding").Level));
 }
Ejemplo n.º 17
0
 // return waste level in a vessel atmosphere
 public static double Poisoning(Vessel v)
 {
     // the proportion of co2 in the atmosphere is simply the level of WasteAtmo
     return(ResourceCache.GetResource(v, "WasteAtmosphere").Level);
 }
Ejemplo n.º 18
0
 // return normalized pressure in a vessel
 public static double Pressure(Vessel v)
 {
     // the pressure is simply the atmosphere level
     return(ResourceCache.GetResource(v, "Atmosphere").Level);
 }
Ejemplo n.º 19
0
 // return habitat surface in a vessel in m^2
 public static double Tot_surface(Vessel v)
 {
     // we use capacity: this mean that partially pressurized parts will still count,
     return(ResourceCache.GetResource(v, "Shielding").Capacity);
 }
Ejemplo n.º 20
0
 // return habitat volume in a vessel in m^3
 public static double Tot_volume(Vessel v)
 {
     // we use capacity: this mean that partially pressurized parts will still count,
     return(ResourceCache.GetResource(v, "Atmosphere").Capacity / 1e3);
 }
Ejemplo n.º 21
0
        // trigger a random breakdown event
        public static void Breakdown(Vessel v, ProtoCrewMember c)
        {
            // constants
            const double res_penalty = 0.1;                    // proportion of food lost on 'depressed' and 'wrong_valve'

            // get a supply resource at random
            ResourceInfo res = null;

            if (Profile.supplies.Count > 0)
            {
                Supply supply = Profile.supplies[Lib.RandomInt(Profile.supplies.Count)];
                res = ResourceCache.GetResource(v, supply.resource);
            }

            // compile list of events with condition satisfied
            List <KerbalBreakdown> events = new List <KerbalBreakdown>
            {
                KerbalBreakdown.mumbling                 //< do nothing, here so there is always something that can happen
            };

            if (Lib.HasData(v))
            {
                events.Add(KerbalBreakdown.fat_finger);
            }
            if (Reliability.CanMalfunction(v))
            {
                events.Add(KerbalBreakdown.rage);
            }
            if (res != null && res.Amount > double.Epsilon)
            {
                events.Add(KerbalBreakdown.wrong_valve);
            }

            // choose a breakdown event
            KerbalBreakdown breakdown = events[Lib.RandomInt(events.Count)];

            // generate message
            string text    = "";
            string subtext = "";

            switch (breakdown)
            {
            case KerbalBreakdown.mumbling:
                text    = "$ON_VESSEL$KERBAL has been in space for too long";
                subtext = "Mumbling incoherently";
                break;

            case KerbalBreakdown.fat_finger:
                text    = "$ON_VESSEL$KERBAL is pressing buttons at random on the control panel";
                subtext = "Science data has been lost";
                break;

            case KerbalBreakdown.rage:
                text    = "$ON_VESSEL$KERBAL is possessed by a blind rage";
                subtext = "A component has been damaged";
                break;

            case KerbalBreakdown.wrong_valve:
                text    = "$ON_VESSEL$KERBAL opened the wrong valve";
                subtext = res.ResourceName + " has been lost";
                break;
            }

            // post message first so this one is shown before malfunction message
            Message.Post(Severity.breakdown, Lib.ExpandMsg(text, v, c), subtext);

            // trigger the event
            switch (breakdown)
            {
            case KerbalBreakdown.mumbling:
                break;                         // do nothing

            case KerbalBreakdown.fat_finger:
                Lib.RemoveData(v);
                break;

            case KerbalBreakdown.rage:
                Reliability.CauseMalfunction(v);
                break;

            case KerbalBreakdown.wrong_valve:
                res.Consume(res.Amount * res_penalty, "breakdown");
                break;
            }

            // remove reputation
            if (HighLogic.CurrentGame.Mode == Game.Modes.CAREER)
            {
                Reputation.Instance.AddReputation(-Settings.KerbalBreakdownReputationPenalty, TransactionReasons.Any);
            }
        }
Ejemplo n.º 22
0
        void FromEVA(GameEvents.FromToAction <Part, Part> data)
        {
            // contract configurator calls this event with both parts being the same when it adds a passenger
            if (data.from == data.to)
            {
                return;
            }

            // for each resource in the eva kerbal
            for (int i = 0; i < data.from.Resources.Count; ++i)
            {
                // get the resource
                PartResource res = data.from.Resources[i];

                // add leftovers to the vessel
                data.to.RequestResource(res.resourceName, -res.amount);
            }

#if !KSP15_16 && !KSP17 && !KSP18 && !KSP110
            string evaPropName = Lib.EvaPropellantName();
            if (evaPropName != "EVA Propellant")
            {
                KerbalEVA kerbalEVA = data.from.FindModuleImplementing <KerbalEVA>();
                List <ProtoPartResourceSnapshot> propContainers = new List <ProtoPartResourceSnapshot>();
                if (kerbalEVA.ModuleInventoryPartReference != null)
                {
                    foreach (StoredPart storedPart in kerbalEVA.ModuleInventoryPartReference.storedParts.Values)
                    {
                        ProtoPartResourceSnapshot propContainer = storedPart.snapshot.resources.Find(p => p.resourceName == evaPropName);
                        if (propContainer != null && propContainer.amount > 0.0)
                        {
                            propContainers.Add(propContainer);
                        }
                    }
                }

                if (propContainers.Count > 0)
                {
                    // get vessel resources handler
                    ResourceInfo evaPropOnVessel  = ResourceCache.GetResource(data.to.vessel, evaPropName);
                    double       storageAvailable = evaPropOnVessel.Capacity - evaPropOnVessel.Amount;

                    foreach (ProtoPartResourceSnapshot propContainer in propContainers)
                    {
                        double stored = Math.Min(propContainer.amount, storageAvailable);
                        storageAvailable -= stored;
                        evaPropOnVessel.Produce(stored, ResourceBroker.Generic);
                        propContainer.amount = Math.Max(propContainer.amount - stored, 0.0);

                        if (storageAvailable <= 0.0)
                        {
                            break;
                        }
                    }

                    // Explaination :
                    // - The ProtoCrewMember has already been removed from the EVA part and added to the vessel part
                    // - It's inventory has already been saved
                    // - The stock ModuleInventoryPart.RefillEVAPropellantOnBoarding() method has already been called
                    // So to set the correct amount of EVA prop, we :
                    // - Harmony patch ModuleInventoryPart.RefillEVAPropellantOnBoarding() so it doesn't refill anything
                    // - Grab the ProtoCrewMember on the vessel part
                    // - Call the SaveInventory() method again, with the modified amount on the inventory StoredPart
                    data.to.protoModuleCrew[data.to.protoModuleCrew.Count - 1].SaveInventory(kerbalEVA.ModuleInventoryPartReference);
                }
            }
#endif

            // merge drives data
            Drive.Transfer(data.from.vessel, data.to.vessel, true);

            // forget EVA vessel data
            Cache.PurgeVesselCaches(data.from.vessel);
            //Drive.Purge(data.from.vessel);

            // update boarded vessel
            this.OnVesselModified(data.to.vessel);

            // execute script
            data.to.vessel.KerbalismData().computer.Execute(data.to.vessel, ScriptType.eva_in);
        }
Ejemplo n.º 23
0
 public static double ResourceLevel(Vessel v, string resource_name)
 {
     return(ResourceCache.GetResource(v, resource_name).Level);
 }
Ejemplo n.º 24
0
 public static double ResourceCapacity(Vessel v, string resource_name)
 {
     return(ResourceCache.GetResource(v, resource_name).Capacity);
 }
Ejemplo n.º 25
0
 public static double ResourceAmount(Vessel v, string resource_name)
 {
     return(ResourceCache.GetResource(v, resource_name).Amount);
 }
Ejemplo n.º 26
0
        public void FixedUpdate()
        {
            // do nothing in the editor
            if (Lib.IsEditor())
            {
                return;
            }

            // if enabled
            if (running)
            {
                // if a researcher is not required, or the researcher is present
                if (!researcher_cs || researcher_cs.Check(part.protoModuleCrew))
                {
                    // get next sample to analyze
                    current_sample = NextSample(vessel);

                    double rate = analysis_rate;
                    if (researcher_cs)
                    {
                        int    bonus     = researcher_cs.Bonus(part.protoModuleCrew);
                        double crew_gain = 1 + bonus * Settings.LaboratoryCrewLevelBonus;
                        crew_gain = Lib.Clamp(crew_gain, 1, Settings.MaxLaborartoryBonus);
                        rate     *= crew_gain;
                    }

                    // if there is a sample to analyze
                    if (current_sample != null)
                    {
                        // consume EC
                        ec = ResourceCache.GetResource(vessel, "ElectricCharge");
                        ec.Consume(ec_rate * Kerbalism.elapsed_s, "laboratory");

                        // if there was ec
                        // - comparing against amount in previous simulation step
                        if (ec.Amount > double.Epsilon)
                        {
                            // analyze the sample
                            status  = Analyze(vessel, current_sample, rate * Kerbalism.elapsed_s);
                            running = status == Status.RUNNING;
                        }
                        // if there was no ec
                        else
                        {
                            status = Status.NO_EC;
                        }
                    }
                    // if there is no sample to analyze
                    else
                    {
                        status = Status.NO_SAMPLE;
                    }
                }
                // if a researcher is required, but missing
                else
                {
                    status = Status.NO_RESEARCHER;
                }
            }
            // if disabled
            else
            {
                status = Status.DISABLED;
            }
        }
Ejemplo n.º 27
0
        public void Execute(Vessel v, VesselData vd, VesselResources resources, double elapsed_s)
        {
            // store list of crew to kill
            List <ProtoCrewMember> deferred_kills = new List <ProtoCrewMember>();

            // get input resource handler
            ResourceInfo res = input.Length > 0 ? resources.GetResource(v, input) : null;

            // determine message variant
            uint variant = vd.EnvTemperature < Settings.LifeSupportSurvivalTemperature ? 0 : 1u;

            // get product of all environment modifiers
            double k = Modifiers.Evaluate(v, vd, resources, modifiers);

            bool lifetime_enabled = PreferencesRadiation.Instance.lifetime;

            // for each crew
            foreach (ProtoCrewMember c in Lib.CrewList(v))
            {
                // get kerbal data
                KerbalData kd = DB.Kerbal(c.name);

                // skip rescue kerbals
                if (kd.rescue)
                {
                    continue;
                }

                // skip disabled kerbals
                if (kd.disabled)
                {
                    continue;
                }

                // get kerbal property data from db
                RuleData rd = kd.Rule(name);
                rd.lifetime = lifetime_enabled && lifetime;

                // influence consumption by elapsed time
                double step = elapsed_s;

                // if interval-based
                if (interval > 0.0)
                {
                    // accumulate time
                    rd.time_since += elapsed_s;

                    // determine number of intervals that has passed (can be 2 or more if elapsed_s > interval * 2)
                    step = Math.Floor(rd.time_since / interval);

                    // consume time
                    rd.time_since -= step * interval;
                }

                // if there is a resource specified
                if (res != null && rate > double.Epsilon)
                {
                    // get rate including per-kerbal variance
                    double resRate =
                        rate                                                        // consumption rate
                        * Variance(name, c, individuality)                          // kerbal-specific variance
                        * k;                                                        // product of environment modifiers

                    // determine amount of resource to consume

                    double required = resRate * step;                           // seconds elapsed or interval amount

                    // remember if a meal is consumed/produced in this simulation step
                    if (interval > 0.0)
                    {
                        double ratePerStep = resRate / interval;
                        res.UpdateIntervalRule(-required, -ratePerStep, name);
                        if (output.Length > 0)
                        {
                            ResourceCache.GetResource(v, output).UpdateIntervalRule(required * ratio, ratePerStep * ratio, name);
                        }
                    }

                    // if continuous, or if one or more intervals elapsed
                    if (step > 0.0)
                    {
                        // if there is no output
                        if (output.Length == 0)
                        {
                            // simply consume (that is faster)
                            res.Consume(required, name);
                        }
                        // if there is an output
                        else
                        {
                            // transform input into output resource
                            // - rules always dump excess overboard (because it is waste)
                            ResourceRecipe recipe = new ResourceRecipe(name);
                            recipe.AddInput(input, required);
                            recipe.AddOutput(output, required * ratio, true);
                            resources.AddRecipe(recipe);
                        }
                    }
                }

                // if continuous, or if one or more intervals elapsed
                if (step > 0.0)
                {
                    // degenerate:
                    // - if the environment modifier is not telling to reset (by being zero)
                    // - if this rule is resource-less, or if there was not enough resource in the vessel
                    if (k > 0.0 && (input.Length == 0 || res.Amount <= double.Epsilon))
                    {
                        rd.problem += degeneration                                   // degeneration rate per-second or per-interval
                                      * k                                            // product of environment modifiers
                                      * step                                         // seconds elapsed or by number of steps
                                      * Variance(name, c, variance);                 // kerbal-specific variance
                    }
                    // else slowly recover
                    else
                    {
                        rd.problem *= 1.0 / (1.0 + Math.Max(interval, 1.0) * step * 0.002);
                    }
                }

                bool do_breakdown = false;

                if (breakdown)
                {
                    // don't do breakdowns and don't show stress message if disabled
                    if (!PreferencesComfort.Instance.stressBreakdowns)
                    {
                        return;
                    }

                    // stress level
                    double breakdown_probability = rd.problem / warning_threshold;
                    breakdown_probability = Lib.Clamp(breakdown_probability, 0.0, 1.0);

                    // use the stupidity of a kerbal.
                    // however, nobody is perfect - not even a kerbal with a stupidity of 0.
                    breakdown_probability *= c.stupidity * 0.6 + 0.4;

                    // apply the weekly error rate
                    breakdown_probability *= PreferencesComfort.Instance.stressBreakdownRate;

                    // now we have the probability for one failure per week, based on the
                    // individual stupidity and stress level of the kerbal.

                    breakdown_probability = (breakdown_probability * elapsed_s) / (Lib.DaysInYear * Lib.HoursInDay * 3600);
                    if (breakdown_probability > Lib.RandomDouble())
                    {
                        do_breakdown = true;

                        // we're stressed out and just made a major mistake, this further increases the stress level...
                        rd.problem += warning_threshold * 0.05;                         // add 5% of the warning treshold to current stress level
                    }
                }

                // kill kerbal if necessary
                if (rd.problem >= fatal_threshold)
                {
#if DEBUG || DEVBUILD
                    Lib.Log("Rule " + name + " kills " + c.name + " at " + rd.problem + " " + degeneration + "/" + k + "/" + step + "/" + Variance(name, c, variance));
#endif
                    if (fatal_message.Length > 0)
                    {
                        Message.Post(breakdown ? Severity.breakdown : Severity.fatality, Lib.ExpandMsg(fatal_message, v, c, variant));
                    }

                    if (breakdown)
                    {
                        do_breakdown = true;

                        // move back between warning and danger level
                        rd.problem = (warning_threshold + danger_threshold) * 0.5;

                        // make sure next danger message is shown
                        rd.message = 1;
                    }
                    else
                    {
                        deferred_kills.Add(c);
                    }
                }
                // show messages
                else if (rd.problem >= danger_threshold && rd.message < 2)
                {
                    if (danger_message.Length > 0)
                    {
                        Message.Post(Severity.danger, Lib.ExpandMsg(danger_message, v, c, variant));
                    }
                    rd.message = 2;
                }
                else if (rd.problem >= warning_threshold && rd.message < 1)
                {
                    if (warning_message.Length > 0)
                    {
                        Message.Post(Severity.warning, Lib.ExpandMsg(warning_message, v, c, variant));
                    }
                    rd.message = 1;
                }
                else if (rd.problem < warning_threshold && rd.message > 0)
                {
                    if (relax_message.Length > 0)
                    {
                        Message.Post(Severity.relax, Lib.ExpandMsg(relax_message, v, c, variant));
                    }
                    rd.message = 0;
                }

                if (do_breakdown)
                {
                    // trigger breakdown event
                    Misc.Breakdown(v, c);
                }
            }

            // execute the deferred kills
            foreach (ProtoCrewMember c in deferred_kills)
            {
                Misc.Kill(v, c);
            }
        }