Exemple #1
0
        public PayloadResource Clone()
        {
            PayloadResource copy = new PayloadResource();

            copy.name   = name;
            copy.amount = amount;
            copy.mass   = mass;
            return(copy);
        }
Exemple #2
0
        // Returns a list of resources which the given vessel has available capacity to receive in an transport-mission:
        public static List <PayloadResource> GetFreeResourcesCapacities(Vessel vessel)
        {
            var availableResources = new List <PayloadResource>();

            try
            {
                foreach (var protoPart in vessel.protoVessel.protoPartSnapshots)
                {
                    foreach (var protoResource in protoPart.resources)
                    {
                        // We manipulate resources of unloaded vessels in "AddResources" below, which does not update "protoResource.amount", so we have
                        // to read the config-node here:
                        var free = protoResource.maxAmount - protoResource.amount;
                        if (free < 0.01)
                        {
                            continue;              // Too small amounts would get shown as 0.00, which would be confusing, so we ignore them just like 0.
                        }
                        if (!KSTS.resourceDictionary.ContainsKey(protoResource.resourceName))
                        {
                            continue;
                        }
                        var resource = KSTS.resourceDictionary[protoResource.resourceName];
                        if (resource.density <= 0)
                        {
                            continue;
                        }

                        var availableResource = availableResources.Find(x => x.name == protoResource.resourceName);
                        if (availableResource != null)
                        {
                            availableResource.amount += free;
                        }
                        else
                        {
                            availableResource        = new PayloadResource();
                            availableResource.amount = free;
                            availableResource.mass   = resource.density;
                            availableResource.name   = protoResource.resourceName;
                            availableResources.Add(availableResource);
                        }
                    }
                }
            }
            catch (Exception e)
            {
                Debug.LogError("[KSTS] GetFreeResourcesCapacities(" + vessel.vesselName.ToString() + "): " + e.ToString());
            }
            return(availableResources);
        }
Exemple #3
0
        // Gathers all important current stats for the given vessel (eg its mass, price, etc):
        public static RecordingVesselStats GetStats(FlightRecording recording, Vessel vessel)
        {
            RecordingVesselStats stats = new RecordingVesselStats();

            stats.hasCrew          = vessel.GetCrewCount() > 0;
            stats.payloadResources = new Dictionary <string, PayloadResource>();
            stats.dockingPortTypes = new List <string>();

            foreach (Part part in vessel.parts)
            {
                string partName = SanitizeParteName(part.name);

                // Check for modules which enable the vessel to perform certain actions:
                List <ModuleDockingNode> dockingNodes = part.FindModulesImplementing <ModuleDockingNode>();
                if (dockingNodes.Count() > 0)
                {
                    stats.hasDockingPort = true;
                    foreach (ModuleDockingNode dockingNode in dockingNodes)
                    {
                        if (!stats.dockingPortTypes.Contains(dockingNode.nodeType.ToString()))
                        {
                            stats.dockingPortTypes.Add(dockingNode.nodeType.ToString());                                                                    // Docking-nodes have differnt sizes, like "node0", "node1", etc
                        }
                    }
                }
                if (part.FindModulesImplementing <ModuleDecouple>().Count() > 0)
                {
                    stats.hasSeperator = true;
                }
                if (part.FindModulesImplementing <ModuleAnchoredDecoupler>().Count() > 0)
                {
                    stats.hasSeperator = true;
                }
                if (part.FindModulesImplementing <ModuleRCS>().Count() > 0)
                {
                    stats.hasRCS = true;
                }

                // Mass of the part and its resources:
                stats.mass += part.mass + part.resourceMass;

                // Sum up all the parts resources:
                double resourceCost    = 0;
                double resourceCostMax = 0;
                foreach (PartResource resource in part.Resources)
                {
                    PartResourceDefinition resourceDefinition = null;
                    if (!KSTS.resourceDictionary.TryGetValue(resource.resourceName.ToString(), out resourceDefinition))
                    {
                        Debug.LogError("[KSTS] RecordingVesselStats.GetStats(): resource '" + resource.resourceName.ToString() + "' not found in dictionary");
                    }
                    else
                    {
                        // Cost:
                        resourceCost    += (double)(resource.amount * resourceDefinition.unitCost);
                        resourceCostMax += (double)(resource.maxAmount * resourceDefinition.unitCost);

                        // Track remaining amout for payload delivery (only resources which have a weight):
                        if (resourceDefinition.density > 0 && resource.amount > 0)
                        {
                            PayloadResource payloadResource = null;
                            if (stats.payloadResources.TryGetValue(resource.resourceName.ToString(), out payloadResource))
                            {
                                stats.payloadResources.Remove(resource.resourceName.ToString());
                                payloadResource.amount += resource.amount;
                            }
                            else
                            {
                                payloadResource        = new PayloadResource();
                                payloadResource.amount = resource.amount;
                                payloadResource.name   = resource.resourceName.ToString();
                                payloadResource.mass   = resourceDefinition.density;
                            }
                            stats.payloadResources.Add(resource.resourceName.ToString(), payloadResource);
                        }
                    }
                }
                stats.cost += resourceCost;

                // The cost of the part is only available in the AvailablePart-class:
                AvailablePart availablePart = null;
                if (!KSTS.partDictionary.TryGetValue(partName, out availablePart))
                {
                    Debug.LogError("[KSTS] RecordingVesselStats.GetStats(): part '" + partName + "' not found in dictionary");
                }
                else
                {
                    // The cost of the part already includes the resource-costs, when completely filled:
                    double dryCost = availablePart.cost - resourceCostMax;
                    stats.cost += dryCost;
                }
            }

            // Find all crewed parts:
            List <string> crewedPartIds = new List <string>();

            foreach (ProtoCrewMember crewMember in vessel.GetVesselCrew())
            {
                if (crewMember.seat == null || crewMember.seat.part == null)
                {
                    continue;
                }
                if (crewedPartIds.Contains(crewMember.seat.part.flightID.ToString()))
                {
                    continue;
                }
                crewedPartIds.Add(crewMember.seat.part.flightID.ToString());
            }

            // Find all valid subassemblies, which can be detached from the control-part:
            stats.payloadAssemblies = new Dictionary <string, PayloadAssembly>();
            stats.FindPayloadAssemblies(recording, vessel.rootPart, null, crewedPartIds);

            return(stats);
        }
Exemple #4
0
        public void DeployPayloadResources(Dictionary <string, double> requestedResources)
        {
            double dumpedMass  = 0;
            double dumpedFunds = 0;

            if (!this.CanPerformMission(MissionProfileType.TRANSPORT))
            {
                return;
            }

            // Try to dump the requested amount of resources from the vessel:
            foreach (var item in requestedResources)
            {
                string requestedName   = item.Key;
                double requestedAmount = item.Value;

                PayloadResource payloadResource = null;
                if (!this.currentStats.payloadResources.TryGetValue(requestedName, out payloadResource))
                {
                    continue;
                }
                if (requestedAmount > payloadResource.amount)
                {
                    requestedAmount = payloadResource.amount;
                }
                if (requestedAmount < 0)
                {
                    requestedAmount = 0;
                }

                // Find parts to dump the resources from:
                double amountToDump = requestedAmount;
                foreach (Part part in vessel.parts)
                {
                    if (amountToDump <= 0)
                    {
                        break;
                    }
                    double dumpedAmount = part.RequestResource(requestedName, amountToDump);
                    if (dumpedAmount == 0)
                    {
                        continue;
                    }
                    Debug.Log("[KSTS] dumped " + dumpedAmount.ToString() + " of " + requestedName.ToString() + " from " + part.name.ToString());
                    amountToDump -= dumpedAmount;
                    dumpedMass   += dumpedAmount * payloadResource.mass;
                    if (KSTS.resourceDictionary.ContainsKey(payloadResource.name))
                    {
                        dumpedFunds += dumpedAmount * KSTS.resourceDictionary[payloadResource.name].unitCost;
                    }
                }
            }

            // If there was something dumped, we can move on to the next stage:
            if (dumpedMass > 0)
            {
                this.payloadMass      = dumpedMass;
                this.missionType      = MissionProfileType.TRANSPORT;
                this.deploymentTime   = Planetarium.GetUniversalTime();
                this.status           = FlightRecordingStatus.DESCENDING;
                this.dockingPortTypes = this.currentStats.dockingPortTypes;

                // The weight and value of the payload should not counted in the vessel's stats:
                this.launchMass -= dumpedMass;
                this.launchCost -= Math.Round(dumpedFunds);
            }
        }
Exemple #5
0
        // Shows a list of all available payload-resources the player can choose from:
        public bool DisplayList()
        {
            GUILayout.BeginHorizontal();
            GUILayout.Label("<size=14><b>Cargo:</b></size>");
            string[] transportTypeStrings = new string[] { "Resources", "Crew" };
            selectedTransportType = GUILayout.Toolbar(selectedTransportType, transportTypeStrings);
            GUILayout.EndHorizontal();

            scrollPos = GUILayout.BeginScrollView(scrollPos, GUI.scrollStyle);
            if (selectedTransportType == 0)
            {
                // Transport Resources:
                selectedCrewTransfers = null;
                if (resourceSelectors.Count == 0)
                {
                    GUILayout.Label("The selected target has no free capacity to receive resources.");
                }
                else
                {
                    // Show list with all possible payloads:
                    int    index        = 0;
                    double selectedMass = 0;
                    List <PayloadResource> currentlySelectedPayloads = new List <PayloadResource>();
                    foreach (GUIRichValueSelector selector in resourceSelectors)
                    {
                        selector.Display();
                        PayloadResource resource = availableResources[index];
                        PayloadResource selected = resource.Clone();
                        selected.amount = selector.Value;
                        currentlySelectedPayloads.Add(selected);
                        selectedMass += selected.amount * selected.mass;
                        index++;
                    }

                    // Show total selected amount:
                    string textColor = "#00FF00";
                    if (selectedMass > missionProfile.payloadMass)
                    {
                        textColor = "#FF0000";
                    }
                    GUILayout.BeginHorizontal();
                    GUILayout.Label("<b>Selected Payload:</b>");
                    GUILayout.Label("<color=" + textColor + ">" + selectedMass.ToString("#,##0.00 t") + " / " + missionProfile.payloadMass.ToString("#,##0.00 t") + "</color>  ", new GUIStyle(GUI.labelStyle)
                    {
                        alignment = TextAnchor.MiddleRight
                    });
                    GUILayout.EndHorizontal();

                    // If the selected mass falls in the range of the transport capacity, we can use the current selection for the mission:
                    if (selectedMass > 0 && selectedMass <= missionProfile.payloadMass)
                    {
                        selectedResources = currentlySelectedPayloads;
                    }
                    else
                    {
                        selectedResources = null;
                    }
                }
            }
            else
            {
                // Transport Crew:
                selectedResources = null;
                bool validCrewSelection = crewTransferSelector.DisplayList();

                // If there is a valid selection, copy the selection:
                if (validCrewSelection && (crewTransferSelector.crewToDeliver.Count > 0 || crewTransferSelector.crewToCollect.Count > 0))
                {
                    selectedCrewTransfers = new List <CrewTransferOrder>();
                    foreach (string name in crewTransferSelector.crewToDeliver)
                    {
                        selectedCrewTransfers.Add(new CrewTransferOrder()
                        {
                            kerbalName = name, direction = CrewTransferOrder.CrewTransferDirection.DELIVER
                        });
                    }
                    foreach (string name in crewTransferSelector.crewToCollect)
                    {
                        selectedCrewTransfers.Add(new CrewTransferOrder()
                        {
                            kerbalName = name, direction = CrewTransferOrder.CrewTransferDirection.COLLECT
                        });
                    }
                }
                else
                {
                    selectedCrewTransfers = null;
                }
            }

            GUILayout.EndScrollView();
            return(selectedResources != null || selectedCrewTransfers != null);
        }