static ConfigNode resource_values(ProtoPartResourceSnapshot res)
        {
            var node = new ConfigNode("RESOURCE");

            res.Save(node);
            return(node);
        }
        protected void TransferResourceFromEVA(string resourceName)
        {
            double availableSpace = GetResourceAmount(resourceName, true) - GetResourceAmount(resourceName);
            double toAdd          = 0d;

            for (int i = 0; i < FlightGlobals.ActiveVessel.evaController.ModuleInventoryPartReference.InventorySlots; i++)
            {
                if (availableSpace > 0d)
                {
                    if (!FlightGlobals.ActiveVessel.evaController.ModuleInventoryPartReference.IsSlotEmpty(i))
                    {
                        StoredPart sPart = FlightGlobals.ActiveVessel.evaController.ModuleInventoryPartReference.storedParts[i];
                        if (sPart.partName == RefuelCargoPartName)
                        {
                            ProtoPartResourceSnapshot res = sPart.snapshot.resources.Find(x => x.resourceName == resourceName);
                            double availableResource      = res.amount;
                            double addable = UtilMath.Min(availableSpace, availableResource);
                            toAdd += addable;

                            Utils.Log($"Removed {addable} {resourceName} from {sPart.partName} ({availableResource} units in part, {availableSpace} space in target)");

                            availableSpace = UtilMath.Clamp(availableSpace - addable, 0, availableSpace);
                            res.amount     = UtilMath.Clamp(res.amount - addable, 0d, res.maxAmount);
                        }
                    }
                }
            }
            ScreenMessages.PostScreenMessage(new ScreenMessage(Localizer.Format("#LOC_SystemHeat_ModuleSystemHeatFissionFuelContainer_Message_Stored",
                                                                                toAdd.ToString("F2"),
                                                                                resourceName,
                                                                                part.partInfo.title
                                                                                ), 5.0f, ScreenMessageStyle.UPPER_CENTER));;
            Utils.Log($"Added {toAdd} {resourceName} to {part.partInfo.title}");
            part.RequestResource(resourceName, -toAdd, ResourceFlowMode.NO_FLOW);
        }
Exemple #3
0
        static void ProcessNonRechargeBattery(Vessel v, ProtoPartSnapshot p, ProtoPartModuleSnapshot m, PartModule fission_generator, Resource_info ec, double elapsed_s)
        {
            ProtoPartResourceSnapshot proto_ec = p.resources.Find(k => k.resourceName == "ElectricCharge");

            proto_ec.maxAmount = proto_ec.amount;
            ec.Sync(v, elapsed_s);
        }
Exemple #4
0
        /// <summary>Returns KIS resource description for the propellant in the part.</summary>
        /// <param name="item">Item to get resource for.</param>
        /// <returns>Resource description.</returns>
        ProtoPartResourceSnapshot GetCanisterFuelResource(KIS_Item item)
        {
            var resources = KISAPI.PartNodeUtils.GetResources(item.partNode);

            if (resources.Length == 0)
            {
                throw new Exception("Bad save state: no resource on the part");
            }
            var itemResource = resources[0]; // Always use the first one.

            if (itemResource.resourceName == _mainResourceName)
            {
                return(itemResource);
            }
            // A mod that changes the default resource has been installed or removed. Update the part state.
            DebugEx.Warning(
                "Fixing saved state of the resource: oldName={0}, newName={1}",
                itemResource.resourceName, _mainResourceName);
            KISAPI.PartNodeUtils.DeleteResource(item.partNode, itemResource.resourceName);
            itemResource = new ProtoPartResourceSnapshot(part.Resources[0])
            {
                amount = itemResource.amount
            };
            KISAPI.PartNodeUtils.AddResource(item.partNode, itemResource);
            return(itemResource);
        }
 /// <summary>
 /// Create a CacheResource
 /// </summary>
 /// <param name="inputprotoPartResourceSnapshot"></param>
 /// <param name="resourcename"></param>
 /// <param name="inputamount"></param>
 /// <param name="maxamount"></param>
 public CacheResource(uint craftId, ProtoPartResourceSnapshot inputprotoPartResourceSnapshot, string resourcename, double inputamount, double maxamount)
 {
     protoPartResourceSnapshot = new DictionaryValueList <string, ProtoPartResourceSnapshot>();
     this.protoPartResourceSnapshot.Add(GetKey(craftId, inputprotoPartResourceSnapshot), inputprotoPartResourceSnapshot);
     this.resourceName     = resourcename;
     this.amount           = inputamount;
     this.maxAmount        = maxamount;
     this.timeWarpOverflow = new CacheTimeWarpBuffer();
 }
 public ResourceProxy(ProtoPartResourceSnapshot res)
     : base(resource_values(res))
 {
     if (res.resourceRef != null)
     {
         resourceRef = res.resourceRef;
     }
     protoRef = res;
 }
        public static HashSet <ProtoPartResourceSnapshot> AddResource(VesselData data, float amount, string name, HashSet <ProtoPartResourceSnapshot> modified)
        {
            BackgroundProcessing.Debug("AddResource called, adding " + amount + " " + name, DebugLevel.ALL);

            if (!data.storage.ContainsKey(name))
            {
                return(modified);
            }

            bool reduce = amount < 0;

            List <ProtoPartResourceSnapshot> relevantStorage = data.storage[name];

            for (int i = 0; i < relevantStorage.Count; ++i)
            {
                ProtoPartResourceSnapshot r = relevantStorage[i];

                if (amount == 0)
                {
                    break;
                }
                float n; float m;

                n = (float)r.amount;
                m = (float)r.maxAmount;
                if (
                    !(float.IsInfinity(n) || float.IsInfinity(m))
                    )
                {
                    n += amount; amount = 0;

                    if (reduce)
                    {
                        if (n < 0 && i < relevantStorage.Count - 1)
                        {
                            amount = n; n = 0;
                        }
                    }
                    else
                    {
                        if (n > m && i < relevantStorage.Count - 1)
                        {
                            amount = n - m; n = m;
                        }
                    }

                    r.amount = n;
                }

                modified.Add(r);
            }

            return(modified);
        }
        private void consumeResources(ProtoVessel v, float amount)
        {
            int l = v.protoPartSnapshots.Count;

            for (int i = 0; i < l; i++)
            {
                ProtoPartSnapshot part = v.protoPartSnapshots[i];

                if (part == null)
                {
                    continue;
                }

                int r = part.resources.Count;

                for (int j = 0; j < r; j++)
                {
                    ProtoPartResourceSnapshot resource = part.resources[j];

                    if (resource == null)
                    {
                        continue;
                    }

                    if (resource.resourceName != "ElectricCharge")
                    {
                        continue;
                    }

                    double partialEC = amount;

                    double rAmount = 0;

                    resource.resourceValues.TryGetValue("amount", ref rAmount);

                    if (partialEC >= rAmount)
                    {
                        partialEC = rAmount;
                    }

                    rAmount -= partialEC;

                    resource.resourceValues.SetValue("amount", rAmount.ToString());

                    amount -= (float)partialEC;

                    if (amount <= 0)
                    {
                        return;
                    }
                }
            }
        }
Exemple #9
0
        /// <summary>Adds a new resource into the config node.</summary>
        /// <param name="partNode">
        /// The part's config or a persistent state. It can be a top-level node or the <c>PART</c> node.
        /// </param>
        /// <param name="resource">
        /// The resource definition. If there is a resource with the same name in the node, it will be
        /// replaced.
        /// </param>
        public void AddResource(ConfigNode partNode, ProtoPartResourceSnapshot resource)
        {
            if (partNode.HasNode("PART"))
            {
                partNode = partNode.GetNode("PART");
            }
            DeleteResource(partNode, resource.resourceName);
            var resourceNode = new ConfigNode("RESOURCE");

            resource.Save(resourceNode);
            partNode.AddNode(resourceNode);
        }
        /// <summary>
        /// Create or update a InterestedVessels entry's CachedResources for a ProtoVessel.
        /// </summary>
        /// <param name="vessel"></param>
        public static void CreatecachedVesselResources(ProtoVessel vessel)
        {
            if (UnloadedResources.InterestedVessels == null)
            {
                UnloadedResources.InterestedVessels = new DictionaryValueList <ProtoVessel, InterestedVessel>();
            }
            List <CacheResource> cacheresources = new List <CacheResource>();

            for (int i = 0; i < vessel.protoPartSnapshots.Count; i++)
            {
                ProtoPartSnapshot protoPartSnapshot = vessel.protoPartSnapshots[i];
                for (int j = 0; j < protoPartSnapshot.resources.Count; j++)
                {
                    ProtoPartResourceSnapshot protoPartResourceSnapshot = protoPartSnapshot.resources[j];
                    bool found = false;
                    for (int k = 0; k < cacheresources.Count; k++)
                    {
                        if (cacheresources[k].resourceName == protoPartResourceSnapshot.resourceName)
                        {
                            cacheresources[k].amount    += protoPartResourceSnapshot.amount;
                            cacheresources[k].maxAmount += protoPartResourceSnapshot.maxAmount;
                            cacheresources[k].protoPartResourceSnapshot.Add(CacheResource.GetKey(protoPartSnapshot, protoPartResourceSnapshot), protoPartResourceSnapshot);
                            found = true;
                            break;
                        }
                    }
                    if (!found)
                    {
                        CacheResource newresource = new CacheResource(protoPartSnapshot.craftID, protoPartResourceSnapshot, protoPartResourceSnapshot.resourceName, protoPartResourceSnapshot.amount, protoPartResourceSnapshot.maxAmount);
                        cacheresources.Add(newresource);
                    }
                }
            }
            if (UnloadedResources.InterestedVessels.Contains(vessel))
            {
                UnloadedResources.InterestedVessels[vessel].CachedResources = cacheresources;
            }
            else
            {
                InterestedVessel iVessel = new InterestedVessel(vessel.vesselRef, vessel);
                iVessel.CachedResources = cacheresources;
                UnloadedResources.InterestedVessels.Add(vessel, iVessel);
                UnloadedResources.InterestedVessels[vessel].TimeLastRefresh = Time.time;
            }
        }
        public static bool HasResource(Vessel Vsl, string resource)
        {
            ProtoPartSnapshot[] Parts = Vsl.protoVessel.protoPartSnapshots.ToArray();
            for (var i = 0; i < Parts.Length; i++)
            {
                ProtoPartSnapshot           Part      = Parts[i];
                ProtoPartResourceSnapshot[] Resources = Part.resources.ToArray();
                for (var k = 0; k < Resources.Length; k++)
                {
                    ProtoPartResourceSnapshot Resrc = Resources[k];
                    if (Resrc.resourceName == resource && Resrc.amount > 0)
                    {
                        return(true);
                    }
                }
            }

            return(false);
        }
        public static float getMaxTotalVesselEC(ProtoVessel v)
        {
            double ec = 0;

            int l = v.protoPartSnapshots.Count;

            for (int i = 0; i < l; i++)
            {
                ProtoPartSnapshot part = v.protoPartSnapshots[i];

                if (part == null)
                {
                    continue;
                }

                int r = part.resources.Count;

                for (int j = 0; j < r; j++)
                {
                    ProtoPartResourceSnapshot resource = part.resources[j];

                    if (resource == null)
                    {
                        continue;
                    }

                    if (resource.resourceName != "ElectricCharge")
                    {
                        continue;
                    }

                    double amount = 0;

                    resource.resourceValues.TryGetValue("maxAmount", ref amount);

                    ec += amount;
                }
            }

            //log("Vessel EC: {0:N4}", logLevels.warning, ec);

            return((float)ec);
        }
Exemple #13
0
        /// <summary>Creates a new item, given a saved state.</summary>
        /// <remarks>
        /// It's intentionally private. The items must be restored thru the factory methods.
        /// </remarks>
        /// <seealso cref="RestoreItemFromNode"/>
        KIS_Item(AvailablePart availablePart, ConfigNode itemNode,
                 ModuleKISInventory inventory, int quantity)
        {
            this.availablePart = availablePart;
            this.inventory     = inventory;
            this.quantity      = quantity;
            SetPrefabModule();
            this.stackable = CheckItemStackable(availablePart);
            this.partNode  = new ConfigNode();
            itemNode.GetNode("PART").CopyTo(partNode);
            ConfigAccessor.ReadFieldsFromNode(
                itemNode, GetType(), this, group: StdPersistentGroups.PartPersistant);
            this.itemVolume = KISAPI.PartUtils.GetPartVolume(availablePart, partNode: partNode);

            // COMPATIBILITY: Set/restore the dry cost and mass.
            // TODO(ihsoft): This code is only needed for the pre-1.17 KIS version saves. Drop it one day.
            if (this.itemDryMass < float.Epsilon || this.itemDryCost < float.Epsilon)
            {
                this._itemDryMass = KISAPI.PartUtils.GetPartDryMass(availablePart, partNode: partNode);
                this._itemDryCost = KISAPI.PartUtils.GetPartDryCost(availablePart, partNode: partNode);
                DebugEx.Warning("Calculated values for a pre 1.17 version save: dryMass={0}, dryCost={1}",
                                this.itemDryMass, this.itemDryCost);
            }

            // COMPATIBILITY: Set/restore the resources cost and mass.
            // TODO(ihsoft): This code is only needed for the pre-1.17 KIS version saves. Drop it one day.
            var resourceNodes = PartNodeUtils.GetModuleNodes(partNode, "RESOURCE");

            if (resourceNodes.Any() &&
                (this.itemResourceMass < float.Epsilon || this.itemResourceCost < float.Epsilon))
            {
                var oldResourceMass = this.itemResourceMass;
                foreach (var resourceNode in resourceNodes)
                {
                    var resource = new ProtoPartResourceSnapshot(resourceNode);
                    this._resourceMass += (float)resource.amount * resource.definition.density;
                    this._resourceCost += (float)resource.amount * resource.definition.unitCost;
                }
                DebugEx.Warning("Calculated values for a pre 1.17 version save:"
                                + " oldResourceMass={0}, newResourceMass={1}, resourceCost={2}",
                                oldResourceMass, this.itemResourceMass, this.itemResourceCost);
            }
        }
        bool CheckForEC(Vessel vessel)
        {
            // Need to add a check for range here

            double ec = 0;

            if (vessel.loaded)
            {
                for (int i = vessel.parts.Count - 1; i >= 0; i--)
                {
                    Part p = vessel.parts[i];
                    for (int i1 = p.Resources.Count - 1; i1 >= 0; i1--)
                    {
                        PartResource r = p.Resources[i1];
                        if (r.resourceName == "ElectricCharge")
                        {
                            ec += r.amount;
                        }
                    }
                }
            }
            else
            {
                ProtoVessel proto = vessel.protoVessel;

                var res = new SortedDictionary <string, ResourceData>();
                for (int i = proto.protoPartSnapshots.Count - 1; i >= 0; i--)
                {
                    ProtoPartSnapshot p = proto.protoPartSnapshots[i];

                    for (int i1 = p.resources.Count - 1; i1 >= 0; i1--)
                    {
                        ProtoPartResourceSnapshot r = p.resources[i1];
                        if (r.resourceName == "ElectricCharge")
                        {
                            ec += r.amount;
                        }
                    }
                }
            }
            return(ec > 0.001);
        }
Exemple #15
0
 public Resource(T res)
 {
     if (res == null)
     {
         throw new NullReferenceException("Resource<T>: res cannot be null");
     }
     if (!(is_resource || is_proto))
     {
         throw new NotSupportedException("Resource<T>: T should be either " +
                                         "PartResource or ProtoPartResourceSnapshot");
     }
     if (is_resource)
     {
         this.res = (PartResource)(object)res;
     }
     else
     {
         pres = (ProtoPartResourceSnapshot)(object)res;
     }
 }
        protected double GetResourceEVAAmount(string resourceName)
        {
            double amt = 0d;

            if (FlightGlobals.ActiveVessel.evaController != null)
            {
                for (int i = 0; i < FlightGlobals.ActiveVessel.evaController.ModuleInventoryPartReference.InventorySlots; i++)
                {
                    if (!FlightGlobals.ActiveVessel.evaController.ModuleInventoryPartReference.IsSlotEmpty(i))
                    {
                        StoredPart sPart = FlightGlobals.ActiveVessel.evaController.ModuleInventoryPartReference.storedParts[i];
                        if (sPart.partName == RefuelCargoPartName)
                        {
                            ProtoPartResourceSnapshot res = sPart.snapshot.resources.Find(x => x.resourceName == resourceName);
                            amt += res.amount;
                        }
                    }
                }
            }
            return(amt);
        }
        public static int GetResourceCount(Vessel Vsl, string resource)
        {
            ProtoPartSnapshot[] Parts = Vsl.protoVessel.protoPartSnapshots.ToArray();
            int resourceCount         = 0;

            for (var i = 0; i < Parts.Length; i++)
            {
                ProtoPartSnapshot           Part      = Parts[i];
                ProtoPartResourceSnapshot[] Resources = Part.resources.ToArray();
                for (var k = 0; k < Resources.Length; k++)
                {
                    ProtoPartResourceSnapshot Resrc = Resources[k];
                    if (Resrc.resourceName == resource)
                    {
                        resourceCount += (int)Resrc.amount;
                    }
                }
            }

            return(resourceCount);
        }
            public static CacheResource Load(ConfigNode node, ProtoVessel protoVessel)
            {
                string resName = "";

                node.TryGetValue("resourceName", ref resName);
                double amt    = 0;
                double maxamt = 0;

                node.TryGetValue("amount", ref amt);
                node.TryGetValue("maxAmount", ref maxamt);
                DictionaryValueList <string, ProtoPartResourceSnapshot> protoresSnapshots = new DictionaryValueList <string, ProtoPartResourceSnapshot>();

                ConfigNode[] protoresourcesnapNodes = node.GetNodes("RESOURCE");
                for (int rsI = 0; rsI < protoresourcesnapNodes.Length; rsI++)
                {
                    string keyField = protoresourcesnapNodes[rsI].GetValue("craftID");
                    ProtoPartResourceSnapshot protoresSnap       = new ProtoPartResourceSnapshot(protoresourcesnapNodes[rsI]);
                    ProtoPartResourceSnapshot protoVesselResSnap = GetMatchingResourceSnapShot(keyField, protoresSnap, protoVessel);
                    if (protoVesselResSnap != null)
                    {
                        protoresSnapshots.Add(keyField, protoVesselResSnap);
                    }
                }
                if (protoresSnapshots.Count > 0)
                {
                    Dictionary <string, ProtoPartResourceSnapshot> .Enumerator ppRSenumerator = protoresSnapshots.GetDictEnumerator();
                    ppRSenumerator.MoveNext();
                    string        resourceKey      = "";
                    uint          craftID          = CacheResource.RetrieveKey(ppRSenumerator.Current.Key, out resourceKey);
                    CacheResource newCacheResource = new CacheResource(craftID, ppRSenumerator.Current.Value, resName, amt, maxamt);
                    while (ppRSenumerator.MoveNext())
                    {
                        newCacheResource.protoPartResourceSnapshot.Add(ppRSenumerator.Current.Key, ppRSenumerator.Current.Value);
                    }
                    ppRSenumerator.Dispose();
                    return(newCacheResource);
                }
                return(null);
            }
        public static ProtoPartResourceSnapshot GetMatchingResourceSnapShot(string keyField, ProtoPartResourceSnapshot protoresSnap, ProtoVessel protoVessel)
        {
            ProtoPartResourceSnapshot returnSnapshot = null;
            string resourceKey = "";
            uint   craftID     = CacheResource.RetrieveKey(keyField, out resourceKey);

            for (int pvPartI = 0; pvPartI < protoVessel.protoPartSnapshots.Count; pvPartI++)
            {
                if (protoVessel.protoPartSnapshots[pvPartI].craftID == craftID)
                {
                    bool found = false;
                    for (int ppSnapI = 0; ppSnapI < protoVessel.protoPartSnapshots[pvPartI].resources.Count; ppSnapI++)
                    {
                        if (protoVessel.protoPartSnapshots[pvPartI].resources[ppSnapI].resourceName == resourceKey)
                        {
                            //Compare the loaded values to the protoVessel snapshot.
                            //If loaded is more then DO WE? update the protoVessel. Let's just report it for now.
                            if (protoVessel.protoPartSnapshots[pvPartI].resources[ppSnapI].amount != protoresSnap.amount)
                            {
                                RSTUtils.Utilities.Log("ProtoVessel resource amounts differ");
                            }
                            if (protoVessel.protoPartSnapshots[pvPartI].resources[ppSnapI].maxAmount != protoresSnap.maxAmount)
                            {
                                RSTUtils.Utilities.Log("ProtoVessel resource max amounts differ");
                            }
                            returnSnapshot = protoVessel.protoPartSnapshots[pvPartI].resources[ppSnapI];
                            break;
                        }
                    }
                    if (found)
                    {
                        break;
                    }
                }
            }

            return(returnSnapshot);
        }
Exemple #20
0
        private static double GetUnloadedVesselMass(string name, ProtoVessel protoVessel)
        {
            double num = 0.0;

            for (int i = 0; i < protoVessel.protoPartSnapshots.Count; i++)
            {
                ProtoPartSnapshot protoPartSnapshot = protoVessel.protoPartSnapshots[i];
                num += (double)protoPartSnapshot.mass;
                for (int j = 0; j < protoPartSnapshot.resources.Count; j++)
                {
                    ProtoPartResourceSnapshot protoPartResourceSnapshot = protoPartSnapshot.resources[j];
                    if (protoPartResourceSnapshot != null)
                    {
                        if (protoPartResourceSnapshot.definition != null)
                        {
                            num += protoPartResourceSnapshot.amount * (double)protoPartResourceSnapshot.definition.density;
                        }
                        //else
                        //    Debug.Log("Vessel: " + name + ", resource: " + protoPartResourceSnapshot.resourceName + ", no definition");
                    }
                }
            }
            return(num);
        }
Exemple #21
0
        public static void ProtoBreak(Vessel v, ProtoPartSnapshot p, ProtoPartModuleSnapshot m)
        {
            // get reliability module prefab
            string      type        = Lib.Proto.GetString(m, "type", string.Empty);
            Reliability reliability = p.partPrefab.FindModulesImplementing <Reliability>().Find(k => k.type == type);

            if (reliability == null)
            {
                return;
            }

            // if manned, or if safemode didn't trigger
            if (Cache.VesselInfo(v).crew_capacity > 0 || Lib.RandomDouble() > Settings.SafeModeChance)
            {
                // flag as broken
                Lib.Proto.Set(m, "broken", true);

                // determine if this is a critical failure
                bool critical = Lib.RandomDouble() < Settings.CriticalChance;
                Lib.Proto.Set(m, "critical", critical);

                // for each associated module
                foreach (var proto_module in p.modules.FindAll(k => k.moduleName == reliability.type))
                {
                    // disable the module
                    Lib.Proto.Set(proto_module, "isEnabled", false);
                }

                // type-specific hacks
                switch (reliability.type)
                {
                case "ProcessController":
                    foreach (ProcessController pc in p.partPrefab.FindModulesImplementing <ProcessController>())
                    {
                        ProtoPartResourceSnapshot res = p.resources.Find(k => k.resourceName == pc.resource);
                        if (res != null)
                        {
                            res.flowState = false;
                        }
                    }
                    break;
                }

                // show message
                Broken_msg(v, reliability.title, critical);
            }
            // safe mode
            else
            {
                // reset age
                Lib.Proto.Set(m, "last", 0.0);
                Lib.Proto.Set(m, "next", 0.0);

                // notify user
                Safemode_msg(v, reliability.title);
            }

            // in any case, incentive redundancy
            if (Settings.IncentiveRedundancy)
            {
                Incentive_redundancy(v, reliability.redundancy);
            }
        }
Exemple #22
0
 public KethaneProtoBattery(ProtoPartResourceSnapshot res)
 {
     protoResource = res;
 }
 public static string GetKey(uint craftID, ProtoPartResourceSnapshot resourceSnapshot)
 {
     return(craftID + "," + resourceSnapshot.resourceName);
 }
 public static string GetKey(ProtoPartSnapshot partSnapshot, ProtoPartResourceSnapshot resourceSnapshot)
 {
     return(partSnapshot.craftID + "," + resourceSnapshot.resourceName);
 }
Exemple #25
0
        /// <summary>
        /// We need to delay the EVA propellant modifications because ToEVA is called too early, before the EVA kerbal
        /// Start() code has run.
        /// </summary>
        IEnumerator PostEVATweaks(Part vesselHatch, Part kerbalPart, string evaPropName)
        {
            yield return(null);

            double evaPropQuantity = 0.0;
            bool   hasJetPack      = false;

#if KSP15_16 || KSP17 || KSP18 || KSP110
            hasJetPack = true;
            double evaPropCapacity = Lib.EvaPropellantCapacity();

            // take as much of the propellant as possible. just imagine: there are 1.3 units left, and 12 occupants
            // in the ship. you want to send out an engineer to fix the chemical plant that produces monoprop,
            // and have to get from one end of the station to the other with just 0.1 units in the tank...
            // nope.
            evaPropQuantity = vesselHatch.RequestResource(evaPropName, evaPropCapacity);

            // 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
            Lib.SetResource(kerbalPart, evaPropName, evaPropQuantity, evaPropCapacity);
#else
            // Since KSP 1.11, EVA prop is stored on "EVA jetpack" inventory part, and filled in the editor, removing
            // the need for handling where the EVA propellant comes from (there is no more magic refill in stock).
            // However, stock doesn't provide any way to refill the jetpack, so we still handle that.

            KerbalEVA kerbalEVA = kerbalPart.FindModuleImplementing <KerbalEVA>();
            List <ProtoPartResourceSnapshot> propContainers = new List <ProtoPartResourceSnapshot>();
            if (kerbalEVA.ModuleInventoryPartReference != null)
            {
                foreach (StoredPart storedPart in kerbalEVA.ModuleInventoryPartReference.storedParts.Values)
                {
                    // Note : the "evaJetpack" string is hardcoded in the KSP source
                    if (storedPart.partName == "evaJetpack")
                    {
                        hasJetPack = true;
                    }

                    ProtoPartResourceSnapshot prop = storedPart.snapshot.resources.Find(p => p.resourceName == evaPropName);
                    if (prop != null)
                    {
                        propContainers.Add(prop);
                    }
                }
            }

            if (propContainers.Count > 0)
            {
                foreach (ProtoPartResourceSnapshot propContainer in propContainers)
                {
                    if (propContainer.amount < propContainer.maxAmount)
                    {
                        double vesselPropTransferred = vesselHatch.RequestResource(evaPropName, propContainer.maxAmount - propContainer.amount);
                        propContainer.amount = Math.Min(propContainer.amount + vesselPropTransferred, propContainer.maxAmount);
                    }
                    evaPropQuantity += propContainer.amount;
                }
            }
#endif

            // show warning if there is little or no EVA propellant in the suit
            if (hasJetPack && evaPropQuantity <= 0.05 && !Lib.Landed(vesselHatch.vessel))
            {
                Message.Post(Severity.danger,
                             Local.CallBackMsg_EvaNoMP.Format("<b>" + evaPropName + "</b>"), Local.CallBackMsg_EvaNoMP2);           //Lib.BuildString("There isn't any <<1>> in the EVA JetPack")"Don't let the ladder go!"
            }
        }
Exemple #26
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);
        }
Exemple #27
0
        static void ProcessCryoTank(Vessel v, ProtoPartSnapshot p, ProtoPartModuleSnapshot m, PartModule cryotank, Vessel_resources resources, Resource_info ec, double elapsed_s)
        {
            // Note. Currently background simulation of Cryotanks has an irregularity in that boiloff of a fuel type in a tank removes resources from all tanks
            // but at least some simulation is better than none ;)

            // get list of fuels, do nothing if no fuels
            IList fuels = Lib.ReflectionValue <IList>(cryotank, "fuels");

            if (fuels == null)
            {
                return;
            }

            // is cooling available, note: comparing against amount in previous simulation step
            bool available = (Lib.Proto.GetBool(m, "CoolingEnabled") && ec.amount > double.Epsilon);

            // get cooling cost
            double cooling_cost = Lib.ReflectionValue <float>(cryotank, "CoolingCost");

            string fuel_name    = "";
            double amount       = 0.0;
            double total_cost   = 0.0;
            double boiloff_rate = 0.0;

            foreach (var item in fuels)
            {
                fuel_name = Lib.ReflectionValue <string>(item, "fuelName");
                // if fuel_name is null, don't do anything
                if (fuel_name == null)
                {
                    continue;
                }

                //get fuel resource
                Resource_info fuel = resources.Info(v, fuel_name);

                // if there is some fuel
                // note: comparing against amount in previous simulation step
                if (fuel.amount > double.Epsilon)
                {
                    // Try to find resource "fuel_name" in PartResources
                    ProtoPartResourceSnapshot proto_fuel = p.resources.Find(k => k.resourceName == fuel_name);

                    // If part doesn't have the fuel, don't do anything.
                    if (proto_fuel == null)
                    {
                        continue;
                    }

                    // get amount in the part
                    amount = proto_fuel.amount;

                    // if cooling is enabled and there is enough EC
                    if (available)
                    {
                        // calculate ec consumption
                        total_cost += cooling_cost * amount * 0.001;
                    }
                    // if cooling is disabled or there wasn't any EC
                    else
                    {
                        // get boiloff rate per-second
                        boiloff_rate = Lib.ReflectionValue <float>(item, "boiloffRate") / 360000.0f;

                        // let it boil off
                        fuel.Consume(amount * (1.0 - Math.Pow(1.0 - boiloff_rate, elapsed_s)));
                    }
                }
            }

            // apply EC consumption
            ec.Consume(total_cost * elapsed_s);
        }
Exemple #28
0
 public ResourceInfo(object obj)
 {
     _resourceInfo = (ProtoPartResourceSnapshot)obj;
 }
        /// <summary>
        /// Request Resource processing on a ProtoVessel.
        /// If the ProtoVessel is not known or resources not cached for the ProtoVessel will automatically add them to the Cached data.
        /// </summary>
        /// <param name="vessel">ProtoVessel reference</param>
        /// <param name="resourceName">Name of the Resource we want to process</param>
        /// <param name="amount">The amount of the resource we want to process</param>
        /// <param name="amountReceived">returns the amount processed for the request in this variable</param>
        /// <param name="pushing">default of false (which means take resource). If true will push (put resource)</param>
        public static void RequestResource(ProtoVessel vessel, string resourceName, double amount, out double amountReceived, bool pushing = false)
        {
            amountReceived = 0d;
            if (UnloadedResources.InterestedVessels == null)
            {
                UnloadedResources.InterestedVessels = new DictionaryValueList <ProtoVessel, InterestedVessel>();
            }
            //If there are no cachedResources for the vessel create one.
            if (!UnloadedResources.InterestedVessels.Contains(vessel))
            {
                CacheResources.CreatecachedVesselResources(vessel);
            }

            //Double check, not really necessary. Now find the resource amounts if in the vessel.
            if (UnloadedResources.InterestedVessels.Contains(vessel))
            {
                List <CacheResources.CacheResource> vslresources = UnloadedResources.InterestedVessels[vessel].CachedResources;
                for (int i = 0; i < vslresources.Count; i++)
                {
                    CacheResources.CacheResource cacheResource = vslresources[i];
                    if (cacheResource.resourceName == resourceName)
                    {
                        if (!pushing)  //We are taking resource
                        {
                            if (cacheResource.amount > 0 || cacheResource.timeWarpOverflow.totalAmount > 0)
                            {
                                if (cacheResource.timeWarpOverflow.totalAmount > 0 && TimeWarp.fetch != null && TimeWarp.CurrentRateIndex > CacheResources.timeWarpStep) //If we have timewarp Overflow check that first.
                                {
                                    double amountTaken = 0;
                                    cacheResource.timeWarpOverflow.Take(amount, out amountTaken);
                                    amountReceived += amountTaken;
                                    amount         -= amountTaken;
                                    if (amount <= 0) //Did we get all we need already? If so return.
                                    {
                                        return;
                                    }
                                }
                                //TimewarpOverflow didn't have enough or didn't have what we need. so now the partResrouceSnapshot
                                Dictionary <string, ProtoPartResourceSnapshot> .Enumerator ppRSenumerator = cacheResource.protoPartResourceSnapshot.GetDictEnumerator();
                                while (ppRSenumerator.MoveNext())
                                {
                                    ProtoPartResourceSnapshot partResourceSnapshot = ppRSenumerator.Current.Value;

                                    if (partResourceSnapshot.amount > 0)
                                    {
                                        if (partResourceSnapshot.amount <= amount) //Not enough but take what it has
                                        {
                                            amountReceived             += partResourceSnapshot.amount;
                                            amount                     -= partResourceSnapshot.amount;
                                            cacheResource.amount       -= partResourceSnapshot.amount;
                                            partResourceSnapshot.amount = 0;
                                        }
                                        else //this part has more than we need.
                                        {
                                            amountReceived              += amount;
                                            cacheResource.amount        -= amount;
                                            partResourceSnapshot.amount -= amount;
                                            amount = 0;
                                        }
                                    }
                                    if (amount <= 0) //Did we get all we wanted? if so return.
                                    {
                                        ppRSenumerator.Dispose();
                                        return;
                                    }
                                }
                                ppRSenumerator.Dispose();
                            }
                        }
                        else  //We are putting a resource
                        {
                            //Get how much space there is in this part.
                            double spaceAvailable = cacheResource.maxAmount - cacheResource.amount;
                            if (spaceAvailable > 0) //If we have space put some in.
                            {
                                Dictionary <string, ProtoPartResourceSnapshot> .Enumerator ppRSenumerator = cacheResource.protoPartResourceSnapshot.GetDictEnumerator();
                                while (ppRSenumerator.MoveNext())
                                {
                                    ProtoPartResourceSnapshot partResourceSnapshot = ppRSenumerator.Current.Value;
                                    double partspaceAvailable = partResourceSnapshot.maxAmount - partResourceSnapshot.amount;
                                    if (partspaceAvailable > 0)
                                    {
                                        if (amount > partspaceAvailable) //If we can't fit it all in this part. Put what we can.
                                        {
                                            partResourceSnapshot.amount = partResourceSnapshot.maxAmount;
                                            cacheResource.amount       += partspaceAvailable;
                                            amount         -= partspaceAvailable;
                                            amountReceived += partspaceAvailable;
                                        }
                                        else //If we can fit it all in this part, put it in.
                                        {
                                            partResourceSnapshot.amount += amount;
                                            cacheResource.amount        += amount;
                                            amountReceived += amount;
                                            amount          = 0;
                                        }
                                        if (amount <= 0) //Did we get all we wanted? if so return.
                                        {
                                            return;
                                        }
                                    }
                                }
                            }
                            //If we get here we had more than can fit in the parts... But if TimeWarp is too high, we put it in the overflow.
                            if (TimeWarp.fetch != null && amount > 0)
                            {
                                if (TimeWarp.CurrentRateIndex > CacheResources.timeWarpStep) //But only if timewarp rate is high enough.
                                {
                                    cacheResource.timeWarpOverflow.Add(amount);
                                    amountReceived += amount;
                                    amount          = 0;
                                    return;
                                }
                            }
                        }
                    }
                } //End For loop all vessel resources.
            }
        }
 public void Add(ProtoPartResourceSnapshot resource)
 {
     resources.Add(resource);
 }