private Crewable(Part part, PartCrewManifest manifest, int capacity) { this.part = part; this.manifest = manifest; Capacity = capacity; crewSlots = CrewSlot.GetSlots(part, manifest); }
/// <summary> /// Clears all crew out of the crewable. /// </summary> public void Clear() { for (int index = 0; index < Capacity; ++index) { manifest.RemoveCrewFromSeat(index); } crewSlots = CrewSlot.GetSlots(part, manifest); }
/// <summary> /// If the ship has no probe cores with SAS, try to make sure that there's at least one pilot. /// Returns the available SAS level (-1 if no SAS present). /// </summary> /// <param name="construct"></param> /// <param name="crewables"></param> private static int TryEnsureSAS(ShipConstruct construct, CrewableList crewables) { // Do we have SAS? int sasLevel = GetHighestSASLevel(construct); // get the highest-level pilot ProtoCrewMember highestPilot = GetHighestAssignedLevel(crewables.Command, PILOT_PROFESSION); int pilotLevel = (highestPilot == null) ? -1 : highestPilot.experienceLevel; int maxSas = (sasLevel > pilotLevel) ? sasLevel : pilotLevel; if (maxSas >= 0) { // we already have SAS on the ship, don't need to add a pilot if ((sasLevel < 0) && (pilotLevel > sasLevel)) { Logging.Log(Logging.ToString(highestPilot) + " is already assigned and will provide SAS"); } return(maxSas); } // There's no SAS control, we need to add a pilot somewhere. // Try to find a slot to put a pilot CrewSlot pilotSlot = Crewable.FindEmptySlot(crewables.Command); if (pilotSlot == null) { Logging.Warn("SAS will be unavailable (no probe cores, no open slots to add a pilot)"); return(maxSas); } // Try to find a pilot to assign. ProtoCrewMember lowestPilot; if (!FindHighestLowestAvailable(PILOT_PROFESSION, 0, crewables, out highestPilot, out lowestPilot)) { Logging.Warn("SAS will be unavailable (no probe cores, no available pilots)"); return(maxSas); } Logging.Log("Assigning " + Logging.ToString(highestPilot) + " to provide SAS"); pilotSlot.Occupant = highestPilot; return(highestPilot.experienceLevel); }
/// <summary> /// As needed, assign additional crew members to fulfill part requirements. /// </summary> /// <param name="crewables"></param> /// <param name="construct"></param> private static void FulfillPartRequirements(CrewableList crewables, ShipConstruct construct) { // Find any professions that are required on the ship Dictionary <string, ModuleCrewRequirement> requirements = FindRequiredProfessions(construct); if (requirements.Count == 0) { return; // there aren't any requirements } // We can ignore any that are already provided for List <string> ignoreList = new List <string>(); foreach (string requiredProfession in requirements.Keys) { int requiredLevel = requirements[requiredProfession].minimumLevel; if (HasProfession(crewables.All, requiredProfession, requiredLevel)) { ignoreList.Add(requiredProfession); } } foreach (string ignoreProfession in ignoreList) { requirements.Remove(ignoreProfession); } if (requirements.Count == 0) { return; // all requirements already taken care of } // We now have a set of required professions that we want to have on board, // but haven't yet satisfied. There might not be enough slots to hold them all, // so build a prioritized list with the most-desired profession first. List <String> prioritizedRequirements = new List <string>(requirements.Keys); if (prioritizedRequirements.Count > 1) { // Sort our remaining requirements in descending order of importance Comparison <string> byPriority = (profession1, profession2) => { // First, sort by *declared* importance from the parts. i.e. if the // Mystery Goo asks for a scientist and assigns importance 0, and the // ISRU asks for an engineer and assigns importance 1, then the ISRU wins. int importance1 = requirements[profession1].importance; int importance2 = requirements[profession2].importance; if (importance1 > importance2) { return(-1); } if (importance2 > importance1) { return(1); } // In case of a tie (e.g. one part asks for a scientist with importance 1 // and the other asks for an engineer with importance 1), then pick the // profession that's "better". importance1 = ProfessionImportance(profession1); importance2 = ProfessionImportance(profession2); if (importance1 > importance2) { return(-1); } if (importance2 > importance1) { return(1); } return(0); }; prioritizedRequirements.Sort(byPriority); } // Now go through our prioritized profession requirements and try to find // an empty slot (and available unassigned crew member) to satisfy each one. foreach (string requiredProfession in prioritizedRequirements) { ModuleCrewRequirement requirement = requirements[requiredProfession]; string part = Logging.ToString(requirement.part); ProtoCrewMember highest; ProtoCrewMember lowest; if (FindHighestLowestAvailable(requiredProfession, requirement.minimumLevel, crewables, out highest, out lowest)) { // Got a crew member to fulfill the requirement. In the case of pilots, // we want the lowest-level possible (to leave the highest freed up to // satisfy SAS requirements for other ships). But for anyone else, we // want the highest available. ProtoCrewMember crew = PILOT_PROFESSION.Equals(requiredProfession) ? lowest : highest; // Is there a command slot available? CrewSlot slot = Crewable.FindEmptySlot(crewables.Command); if (slot == null) { // okay then, how about a non-command slot? slot = Crewable.FindEmptySlot(crewables.All); } if (slot == null) { Logging.Warn("No open slot is available to assign a " + requirement.Description + " to operate " + part); } else { slot.Occupant = crew; Logging.Log("Assigning " + Logging.ToString(crew) + " to operate " + part); } } else { // there's nobody to fill the slot Logging.Warn("No " + requirement.Description + " is available to operate " + part + ", not assigning anyone"); } } // for each required profession }