private float GetActiveConverters() { //We don't just count converters - we count total efficiency of those //converters. This way high efficiency modules get a higher weight. var totEff = 0f; //Find any vessels that have an MKS Module tied to this same eTag. var vList = LogisticsTools.GetNearbyVessels(EFF_RANGE, true, vessel, true) .Where(v => v.FindPartModulesImplementing <MKSModule>().Any(m => m.eTag == eTag)); foreach (var vsl in vList) { var pList = vsl.FindPartModulesImplementing <BaseConverter>(); foreach (var p in pList) { var m = p.part.FindModuleImplementing <MKSModule>(); if (m != null && m.eTag == eTag) { if (p.IsActivated) // p has a GetEfficiencyMultiplier () { totEff += m.eMultiplier; } } } } return(totEff); }
public List <Vessel> GetResourceStockpiles() { List <Vessel> depots = LogisticsTools.GetNearbyVessels(LogisticsSetup.Instance.Config.ScavangeRange, false, vessel, true) .Where(dv => dv.FindPartModulesImplementing <USI_ModuleResourceWarehouse>().Any()).ToList(); var nearbyVesselList = LogisticsTools.GetNearbyVessels(LogisticsTools.PHYSICS_RANGE, false, vessel, true); foreach (var v in nearbyVesselList) { var range = LogisticsTools.GetRange(vessel, v); var parts = v.Parts.Where( p => p.FindModuleImplementing <ModuleResourceDistributor>() != null && LogisticsTools.HasCrew(p, "Pilot")); foreach (var p in parts) { var m = p.FindModuleImplementing <ModuleResourceDistributor>(); if (range <= m.ResourceDistributionRange) { //Now find ones adjacent to our depot. List <Vessel> stockpiles = LogisticsTools.GetNearbyVessels(m.ResourceDistributionRange, false, vessel, true).Where(sv => sv.FindPartModulesImplementing <USI_ModuleResourceWarehouse>().Any()).ToList(); foreach (var s in stockpiles) { if (!depots.Contains(s)) { depots.Add(s); } } } } } return(depots); }
private void GrabResources(string resourceName) { if (!part.Resources.Contains(resourceName)) { return; } var brokRes = part.Resources[resourceName]; var needed = brokRes.maxAmount - brokRes.amount; //Pull in from warehouses var whpList = LogisticsTools.GetRegionalWarehouses(vessel, "USI_ModuleResourceWarehouse"); foreach (var whp in whpList) { if (whp.Resources.Contains(resourceName)) { var res = whp.Resources[resourceName]; if (res.amount >= needed) { brokRes.amount += needed; res.amount -= needed; needed = 0; break; } else { brokRes.amount += res.amount; needed -= res.amount; res.amount = 0; } } } }
private void PushResources(string resourceName, double amount) { var vessels = LogisticsTools.GetNearbyVessels(2000, true, vessel, false); foreach (var v in vessels) { //Put recycled stuff into recycleable places foreach (var p in v.parts.Where(vp => vp != part && vp.Modules.Contains("USI_ModuleRecycleBin"))) { if (p.Resources.Contains(resourceName)) { var partRes = p.Resources[resourceName]; var partNeed = partRes.maxAmount - partRes.amount; if (partNeed > 0 && amount > 0) { if (partNeed > amount) { partNeed = amount; } partRes.amount += partNeed; amount -= partNeed; } } } } if (amount > 1f) { ScreenMessages.PostScreenMessage(String.Format("{0:0} units of {1} were lost due to lack of recycle space", amount, ResourceName), 5f, ScreenMessageStyle.UPPER_CENTER); } }
private float GetActiveConverters() { //We don't just count converters - we count total efficiency of those //converters. This way high efficiency modules get a higher weight. var totEff = 0f; //Find any vessels that have an MKS Module tied to this same eTag. var vList = LogisticsTools.GetNearbyVessels(EFF_RANGE, true, vessel, true) .Where(v => v.FindPartModulesImplementing <MKSModule>().Any(m => m.eTag == eTag)); var validMods = new List <String> { "ModuleResourceConverter", "ModuleResourceHarvester", "ModuleBulkHarvester" }; foreach (var vsl in vList) { var pList = vsl.FindPartModulesImplementing <BaseConverter>().Where(m => validMods.Contains(m.name)); foreach (var p in pList) { var m = p.part.FindModuleImplementing <MKSModule>(); if (m != null) { if (p.IsActivated) { totEff += (p.Efficiency * m.eMultiplier); } } } } return(totEff); }
private float GetCurrentConsumption(string tag) { // We don't just count consumers - we count total efficiency consumption. // This way high efficiency modules get a higher weight. var totalEfficiencyConsumption = 0f; // Find any nearby vessels that have consumers for this efficiency bonus tag. var mksVessels = LogisticsTools.GetNearbyVessels(EFFICIENCY_RANGE, true, vessel, true) .Where(v => v .FindConverterAddonsImplementing <USI_EfficiencyConsumerAddonForConverters>() .Any(a => a.Tag == tag)); foreach (var mksVessel in mksVessels) { var mksModule = mksVessel.FindPartModuleImplementing <MKSModule>(); if (mksModule == null) { Debug.LogError(string.Format("[MKS] {0}: Part is misconfigured. Parts with an EfficiencyConsumerAddon must also have an MKSModule.", GetType().Name)); continue; } var consumers = mksVessel.FindConverterAddonsImplementing <USI_EfficiencyConsumerAddonForConverters>(); foreach (var consumer in consumers) { if (consumer.IsActive && consumer.Tag == tag) { totalEfficiencyConsumption += mksModule.EfficiencyMultiplier; } } } return(totalEfficiencyConsumption); }
private void TransferSetup() { if (!HighLogic.LoadedSceneIsFlight) { return; } activeId = FlightGlobals.ActiveVessel.id; var PotentialVessels = LogisticsTools.GetNearbyVessels(150, true, FlightGlobals.ActiveVessel, true); NearVessels = new List <Vessel>(); foreach (var v in PotentialVessels) { if (HasResources(v)) { NearVessels.Add(v); } } if (NearVessels.Count == 0) { return; } _crewPresent = NearVessels.Any(v => v.GetCrewCount() > 0); _fromVessel = new TransferVessel(); _fromVessel.Setup(NearVessels[0], 0); var lastIdx = NearVessels.Count - 1; _toVessel = new TransferVessel(); _toVessel.Setup(NearVessels[lastIdx], lastIdx); _resList = RebuildResourceList(); }
private double FetchResources(double amount, PartResourceDefinition resource, double fillPercent) { double demand = amount; double fetched = 0d; try { var rangeFactor = LOG_RANGE; if (resource.name == "ElectricCharge") { rangeFactor = POWER_RANGE; } var nearVessels = LogisticsTools.GetNearbyVessels(rangeFactor, false, vessel, true); foreach (var v in nearVessels) { if (demand <= ResourceUtilities.FLOAT_TOLERANCE) { break; } //Is this a valid target? if (!HasResourcesToSpare(v, resource, fillPercent)) { continue; } //Can we find what we're looking for? var partList = v.Parts.Where( p => p.Resources.Contains(resource.name)); foreach (var p in partList) { //Special case - EC can only come from a PDU if (resource.name == "ElectricCharge" && !p.Modules.Contains("ModulePowerDistributor")) { continue; } var pr = p.Resources[resource.name]; if (pr.amount >= demand) { pr.amount -= demand; fetched += demand; demand = 0; break; } else { demand -= pr.amount; fetched += pr.amount; pr.amount = 0; } } } } catch (Exception ex) { print(String.Format("[MKS] - ERROR in FetchResources - {0}", ex.StackTrace)); } return(fetched); }
public List <Vessel> GetPowerDistributors(Vessel thisVessel) { bool hasRelay = false; var pList = new List <Vessel>(); var vList = LogisticsTools.GetNearbyVessels(20000, true, thisVessel, true); foreach (var v in vList) { var gParts = v.parts.Where(p => p.FindModuleImplementing <ModulePowerDistributor>() != null && HasCrew(p, "Engineer")); if (gParts != null) { foreach (var p in gParts) { var mod = p.FindModuleImplementing <ModulePowerDistributor>(); var posCur = vessel.GetWorldPos3D(); var posNext = v.GetWorldPos3D(); var distance = Vector3d.Distance(posCur, posNext); if (distance < mod.PowerDistributionRange) { pList.Add(v); } } } if (!hasRelay) { var dParts = v.parts.Where(p => p.FindModuleImplementing <ModulePowerCoupler>() != null); if (dParts != null) { foreach (var p in dParts) { var mod = p.FindModuleImplementing <ModulePowerCoupler>(); var posCur = vessel.GetWorldPos3D(); var posNext = v.GetWorldPos3D(); var distance = Vector3d.Distance(posCur, posNext); if (distance < mod.PowerCouplingRange) { hasRelay = true; } } } } } if (hasRelay) { return(pList); } else { return(new List <Vessel>()); } }
public bool LogisticsAvailable() { var vList = LogisticsTools.GetNearbyVessels(DEPOT_RANGE, true, vessel, true); foreach (var v in vList.Where(v => v.GetTotalMass() <= 3f)) { if (v.Parts.Any(p => p.FindModuleImplementing <ModuleResourceDistributor>() != null && HasCrew(p, "Pilot"))) { return(true); } } return(false); }
public bool PowerAvailable() { var vList = LogisticsTools.GetNearbyVessels(POWER_RANGE, true, vessel, true); foreach (var v in vList) { if (v.Parts.Any(p => p.FindModuleImplementing <ModulePowerDistributor>() != null && HasCrew(p, "Engineer"))) { return(true); } } return(false); }
private void LevelResources(string resource) { var nearbyShips = LogisticsTools.GetNearbyVessels(LogisticsRange, true, vessel, true); var depots = new List <Vessel>(); foreach (var d in nearbyShips) { if (d.FindPartModulesImplementing <ModuleDistributedWarehouse>().Any() && d.Parts.Any(p => p.Resources.Contains(resource))) { depots.Add(d); } } //Get relevant parts var resParts = new List <Part>(); foreach (var d in depots) { var pList = d.parts.Where(p => p.Resources.Contains(resource) && p.Modules.Contains("ModuleDistributedWarehouse")); foreach (var p in pList) { var wh = p.FindModuleImplementing <USI_ModuleResourceWarehouse>(); if (wh != null && wh.transferEnabled) { resParts.Add(p); } } } var amountSum = 0d; var maxSum = 0d; //Figure out our average fill percent foreach (var p in resParts) { var res = p.Resources[resource]; amountSum += res.amount; maxSum += res.maxAmount; } if (maxSum > 0 && amountSum > 0) { double fillPercent = amountSum / maxSum; //Level everything foreach (var p in resParts) { var res = p.Resources[resource]; res.amount = res.maxAmount * fillPercent; } } }
private float GetActiveBoosters(string tag) { var totalEfficiencyBoost = 0f; var boosters = LogisticsTools.GetNearbyVessels(EFFICIENCY_RANGE, true, vessel, true) .SelectMany(v => v .FindConverterAddonsImplementing <USI_EfficiencyBoosterAddon>() .Where(a => a.Tag == tag)); foreach (var booster in boosters) { if (booster.IsActive) { totalEfficiencyBoost += (float)(booster.EfficiencyMultiplier * booster.Multiplier); } } return(totalEfficiencyBoost); }
public List <Vessel> GetPowerDistributors() { var distributors = new List <Vessel>(); var nearbyVessels = LogisticsTools.GetNearbyVessels(LogisticsTools.PHYSICS_RANGE, false, vessel, true); foreach (var v in nearbyVessels) { var range = LogisticsTools.GetRange(vessel, v); if (v.parts .Select(p => p.FindModuleImplementing <ModulePowerDistributor>()) .Any(m => m != null && range <= m.ActiveDistributionRange)) { distributors.Add(v); } } return(distributors); }
private float GetActiveEParts() { var totEff = 0f; var vList = LogisticsTools.GetNearbyVessels(EFF_RANGE, true, vessel, true) .Where(v => v.FindPartModulesImplementing <ModuleEfficiencyPart>().Any(m => m.eTag == eTag)); foreach (var vsl in vList) { var pList = vsl.FindPartModulesImplementing <ModuleEfficiencyPart>(); foreach (var p in pList) { if (p.IsActivated && p.eTag == eTag) { totEff += (float)(p.EfficiencyMultiplier * p.eMultiplier); } } } return(totEff); }
private void SwapResources(string fetchName, string storeName) { print("Making sure part contains " + storeName); if (!part.Resources.Contains(storeName)) { return; } print("Resource exists..."); var brokRes = part.Resources[storeName]; var needed = brokRes.maxAmount - brokRes.amount; print("We need " + needed); //Pull in from warehouses var whpList = LogisticsTools.GetRegionalWarehouses(vessel, "USI_ModuleResourceWarehouse"); print("Found " + whpList.Count() + " warehouses..."); foreach (var whp in whpList) { if (whp.Resources.Contains(fetchName)) { print("Found " + fetchName); var res = whp.Resources[fetchName]; if (res.amount >= needed) { brokRes.amount += needed; res.amount -= needed; needed = 0; break; } else { brokRes.amount += res.amount; needed -= res.amount; res.amount = 0; } } } }
private void PushResources(string resourceName) { var brokRes = part.Resources[resourceName]; //Put remaining parts in warehouses foreach (var p in LogisticsTools.GetRegionalWarehouses(vessel, "USI_ModuleCleaningBin")) { if (p.Resources.Contains(resourceName)) { var partRes = p.Resources[resourceName]; var partNeed = partRes.maxAmount - partRes.amount; if (partNeed > 0 && brokRes.amount > 0) { if (partNeed > brokRes.amount) { partNeed = brokRes.amount; } partRes.amount += partNeed; brokRes.amount -= partNeed; } } } }
private float GetCrewHappiness() { //Crew Happiness is a function of the ratio of living space to Kerbals. //These are COLONY-WIDE. var kShips = LogisticsTools.GetNearbyVessels(COLONY_RANGE, true, vessel, true); float ls = GetKolonyLivingSpace(kShips); //We can add in a limited number for crew capacity - 10% ls += GetKolonyCrewCap(kShips) * .1f; var totKerbs = GetKolonyInhabitants(kShips); var hap = 0f; if (totKerbs > 0) { hap = ls / totKerbs; } //Range is 50% - 150% for crowding and extra space. //This is calculated before loneliness. if (hap < .5f) { hap = .5f; } if (hap > 1.5f) { hap = 1.5f; } //Kerbals hate being alone. Any fewer than five Kerbals incurs a pretty significant penalty. if (totKerbs < 5) { //20% - 80% hap *= (totKerbs * .2f); } return(hap); }
private void DrawLogistics() { var vessels = LogisticsTools.GetNearbyVessels(2000, true, _model, true); List <LogisticsResource> resources = new List <LogisticsResource>(); Dictionary <string, float> dr = new Dictionary <string, float>(); int kerbals = 0; foreach (Vessel v in vessels) { // Storage foreach (var r in v.GetStorage()) { getResourceFromList(resources, r.resourceName).maxAmount += r.amount; } // Amount foreach (var r in v.GetResourceAmounts()) { getResourceFromList(resources, r.resourceName).amount += r.amount; } // Production of converters foreach (var r in v.GetProduction()) { getResourceFromList(resources, r.resourceName).change += r.amount; } // Consumption of Converters foreach (var r in v.GetProduction(false)) { getResourceFromList(resources, r.resourceName).change -= r.amount; } // Drills foreach (Part drill in v.Parts.Where(p => p.Modules.Contains("ModuleResourceHarvester"))) { foreach (ModuleResourceHarvester m in drill.FindModulesImplementing <ModuleResourceHarvester>().Where(mod => mod.IsActivated)) { bool hasResource = false; foreach (var p in v.Parts) { var res = p.Resources.Get(m.ResourceName); if (res == null) { continue; } if (res.amount <= res.maxAmount) { hasResource = true; } } if (hasResource) // test if storage for this resource on this vessel is not full { AbundanceRequest ar = new AbundanceRequest { Altitude = v.altitude, BodyId = FlightGlobals.currentMainBody.flightGlobalsIndex, CheckForLock = false, Latitude = v.latitude, Longitude = v.longitude, ResourceType = HarvestTypes.Planetary, ResourceName = m.ResourceName }; getResourceFromList(resources, m.ResourceName).change += (double)ResourceMap.Instance.GetAbundance(ar); getResourceFromList(resources, "ElectricCharge").change -= 6; } } } // Life Support kerbals += v.GetCrewCount(); } if (_usils) { getResourceFromList(resources, "Supplies").change -= kerbals * 0.00005; getResourceFromList(resources, "Mulch").change += kerbals * 0.00005; getResourceFromList(resources, "ElectricCharge").change -= kerbals * 0.01; } if (_tacls) { // TAC-LS consumption rates are a bit complex to calculate, so here is an approximated calculation where // - Kerbals on EVA are not handled // - BaseElectricityConsumptionRate is not taken into account getResourceFromList(resources, "Oxygen").change -= kerbals * 0.001713537562385; getResourceFromList(resources, "Food").change -= kerbals * 0.000016927083333; getResourceFromList(resources, "Water").change -= kerbals * 0.000011188078704; getResourceFromList(resources, "CarbonDioxide").change += kerbals * 0.00148012889876; getResourceFromList(resources, "Waste").change += kerbals * 0.000001539351852; getResourceFromList(resources, "WasteWater").change += kerbals * 0.000014247685185; getResourceFromList(resources, "ElectricCharge").change -= kerbals * 0.014166666666667; // Values are based on TAC-LS Version 0.11.1.20 } // Consumption rates for Snacks are not calculated resources.Sort(new LogisticsResourceComparer()); foreach (LogisticsResource r in resources) { GUILayout.Label(r.resourceName + ": " + numberToOut(r.amount, -1, false) + "/" + Math.Round(r.maxAmount, 5) + " (" + numberToOut(r.change, r.change > 0 ? r.maxAmount - r.amount : r.amount) + ")"); } }
public override void OnFixedUpdate() { if (part.Resources.Contains(BrokeredResource) && part.protoModuleCrew.Count == part.CrewCapacity) { var brokRes = part.Resources[BrokeredResource]; var needed = brokRes.maxAmount - brokRes.amount; //Pull in from warehouses var whpList = LogisticsTools.GetRegionalWarehouses(vessel, "USI_ModuleResourceWarehouse"); foreach (var whp in whpList) { if (whp.Resources.Contains(BrokeredResource)) { var res = whp.Resources[BrokeredResource]; if (res.amount >= needed) { brokRes.amount += needed; res.amount -= needed; needed = 0; break; } else { brokRes.amount += res.amount; needed -= res.amount; res.amount = 0; } } } //Push to all parts needing this resource foreach (var p in vessel.parts.Where(vp => vp != part && !vp.Modules.Contains("USI_ModuleResourceWarehouse"))) { if (p.Resources.Contains(BrokeredResource)) { var partRes = p.Resources[BrokeredResource]; var partNeed = partRes.maxAmount - partRes.amount; if (partNeed > 0 && brokRes.amount > 0) { if (partNeed > brokRes.amount) { partNeed = brokRes.amount; } partRes.amount += partNeed; brokRes.amount -= partNeed; } } } //Put remaining parts in warehouses foreach (var p in vessel.parts.Where(vp => vp != part && vp.Modules.Contains("USI_ModuleResourceWarehouse"))) { if (p.Resources.Contains(BrokeredResource)) { var partRes = p.Resources[BrokeredResource]; var partNeed = partRes.maxAmount - partRes.amount; if (partNeed > 0 && brokRes.amount > 0) { if (partNeed > brokRes.amount) { partNeed = brokRes.amount; } partRes.amount += partNeed; brokRes.amount -= partNeed; } } } } }
public List <Vessel> GetPowerDistributors(Vessel thisVessel) { bool hasRelay = false; var pList = new List <Vessel>(); var vList = LogisticsTools.GetNearbyVessels(20000, true, thisVessel, true); print("Checking " + vList.Count + " vessels..."); foreach (var v in vList) { var gParts = v.parts.Where(p => p.FindModuleImplementing <ModulePowerDistributor>() != null && HasCrew(p, "Engineer")); if (gParts != null) { print("Found " + gParts.Count() + " parts that are distributors!"); foreach (var p in gParts) { var mod = p.FindModuleImplementing <ModulePowerDistributor>(); var posCur = vessel.GetWorldPos3D(); var posNext = v.GetWorldPos3D(); var distance = Vector3d.Distance(posCur, posNext); if (distance < mod.PowerDistributionRange) { print("Adding PDU in range"); pList.Add(v); } else { print("PDU was not in range..."); } } } if (!hasRelay) { var dParts = v.parts.Where(p => p.FindModuleImplementing <ModulePowerCoupler>() != null); if (dParts != null) { print("Found " + gParts.Count() + " parts that are couplers!"); foreach (var p in dParts) { var mod = p.FindModuleImplementing <ModulePowerCoupler>(); var posCur = vessel.GetWorldPos3D(); var posNext = v.GetWorldPos3D(); var distance = Vector3d.Distance(posCur, posNext); if (distance < mod.PowerCouplingRange) { print("Relay was in range!!!!"); hasRelay = true; } else { print("Relay was not in range"); } } } } } if (hasRelay) { return(pList); } else { return(new List <Vessel>()); } }
private void RefreshResourceList() { if (vesselId != FlightGlobals.ActiveVessel.id.ToString()) { vesselId = FlightGlobals.ActiveVessel.id.ToString(); _resourceList.Clear(); } var vList = LogisticsTools.GetNearbyVessels(LOCAL_LOGISTICS_RANGE, false, FlightGlobals.ActiveVessel, true); vList.Add(FlightGlobals.ActiveVessel); var _workList = new List <ResourceSummary>(); var vCount = vList.Count; for (int i = 0; i < vCount; ++i) { var thisVessel = vList[i]; var pCount = thisVessel.Parts.Count; for (int p = 0; p < pCount; ++p) { var thisPart = thisVessel.Parts[p]; var rCount = thisPart.Resources.Count; for (int r = 0; r < rCount; ++r) { var res = thisPart.Resources[r]; if (!res.isVisible) { continue; } var found = false; wlCount = _workList.Count(); for (int c = 0; c < wlCount; ++c) { var thisRes = _workList[c]; if (thisRes.ResourceName == res.resourceName) { found = true; thisRes.CurrentAmount = +res.amount; thisRes.CurrentMax = +res.maxAmount; break; } } if (!found) { _workList.Add(new ResourceSummary { CurrentMax = res.maxAmount, CurrentAmount = res.amount, ResourceName = res.resourceName }); } } } } //At this point we have a populated working list. We now update the master list. rlCount = _resourceList.Count; wlCount = _workList.Count; for (int w = 0; w < wlCount; w++) { var found = false; var wRes = _workList[w]; for (int r = 0; r < _resourceList.Count; r++) { var res = _resourceList[r]; if (wRes.ResourceName == res.ResourceName) { res.LastAmount = res.CurrentAmount; res.LastTime = res.CurrentTime; res.LastMax = res.CurrentMax; res.CurrentAmount = wRes.CurrentAmount; res.CurrentMax = wRes.CurrentMax; res.CurrentTime = Planetarium.GetUniversalTime(); found = true; break; } } if (!found) { _resourceList.Add(new ResourceSummary { LastTime = Planetarium.GetUniversalTime() - UpdateFrequency, LastAmount = wRes.CurrentAmount, LastMax = wRes.CurrentMax, CurrentAmount = wRes.CurrentAmount, CurrentMax = wRes.CurrentMax, CurrentTime = Planetarium.GetUniversalTime(), ResourceName = wRes.ResourceName }); } } //Cull missing resources for (int r = rlCount; r-- > 0;) { var res = _resourceList[r]; var found = false; for (int w = 0; r < _workList.Count; w++) { var wRes = _workList[w]; if (wRes.ResourceName == res.ResourceName) { found = true; break; } } if (!found) { _resourceList.Remove(res); } } }
private float GetEfficiency() { try { //Efficiency is based on various factors. These come in three //categories: // * Part // * Vessel // * Colony // - Vessel Workspaces [numWorkspaces] // - 25% Vessel Crew Capacity [numWorkSpaces] // - Vessel MKS Module count [numModules] // - Part Crew [modKerbalFactor] (0.05 - 3.75 per Kerbal) // - Vessel crew [numWeightedKerbals] // - Colony efficiency parts [added to eff] // Bonus equal to 100 * number of units - 1 // - Colony Living Space/Kerbal Happiness float numWorkspaces = GetKolonyWorkspaces(vessel); //Plus 25% of Crew Cap as low efficiency workspaces numWorkspaces += vessel.GetCrewCapacity() * .25f; //Number of active modules var numModules = GetActiveKolonyModules(vessel); //Kerbals in the module float modKerbalFactor = part.protoModuleCrew.Sum(k => GetKerbalFactor(k)); modKerbalFactor *= GetCrewHappiness(); //Kerbals in the ship float numWeightedKerbals = vessel.GetVesselCrew().Sum(k => GetKerbalFactor(k)); numWeightedKerbals *= GetCrewHappiness(); //Worst case, 25% (if crewed). Uncrewed vessels will be at 0% //You need crew for these things, no robo ships. float eff = .0f; if (vessel.GetCrewCount() > 0) { float WorkSpaceKerbalRatio = numWorkspaces / vessel.GetCrewCount(); if (WorkSpaceKerbalRatio > 3) { WorkSpaceKerbalRatio = 3; } //A module gets 100% bonus from Kerbals inside of it, //in addition to a 10% bonus for Kerbals in the entire station. float WorkUnits = WorkSpaceKerbalRatio * modKerbalFactor; WorkUnits += WorkSpaceKerbalRatio * numWeightedKerbals * CrewBonus; eff = WorkUnits / numModules; if (eff > MaxEfficiency) { eff = MaxEfficiency; } if (eff < .25) { eff = .25f; } } //Add in efficiencyParts if (efficiencyPart != "") { var validEffParts = new List <EffPart>(); var effPartBits = efficiencyPart.Split(',') .Select(effPartName => effPartName.Trim().Replace('_', '.')).ToArray(); for (int i = 0; i < effPartBits.Count(); i += 2) { validEffParts.Add(new EffPart { Name = effPartBits[i], Multiplier = float.Parse(effPartBits[i + 1]) }); } var effParts = 0f; foreach (var vep in validEffParts) { var vList = LogisticsTools.GetNearbyVessels(EFF_RANGE, true, vessel, true); var effPartList = new List <Part>(); foreach (var v in vList) { var nameWhenRootPart = vep.Name + " (" + v.GetName() + ")"; var pList = v.Parts.Where(p => p.name == vep.Name || p.name == nameWhenRootPart); effPartList.AddRange(pList); } foreach (var ep in effPartList) { var mod = ep.FindModuleImplementing <USIAnimation>(); if (mod == null) { effParts += vep.Multiplier; } else { if (mod.isDeployed) { effParts += vep.Multiplier; } } } } eff += effParts; if (eff < 0.25) { eff = 0.25f; //We can go as low as 25% as these are almost mandatory. } } if (!calculateEfficiency) { eff = 1f; efficiency = String.Format("100% [Fixed]"); } efficiency = String.Format("{0}%", Math.Round((eff * 100), 1)); //DEBUG DATA //DEBUG return(eff); } catch (Exception ex) { print(String.Format("[MKS] - ERROR in GetEfficiency - {0}", ex.Message)); return(1f); } }
private void TransferResources(PartResourceDefinition resource, double amount, TransferType transferType) { try { var transferAmount = amount; var nearVessels = LogisticsTools.GetNearbyVessels(LogisticsRange, false, vessel); foreach (var v in nearVessels) { if (transferAmount == 0) { break; } //Can we find what we're looking for? var partList = v.Parts.Where( p => p.Resources.Contains(resource.name) && p != part && p.Modules.Contains("ProxyLogistics")); foreach (var p in partList) { var pr = p.Resources[resource.name]; if (transferType == TransferType.TakeResources) { // RemotePartAmount: 200 -> 150 // LocalPartAmount: 10 -> 60 // TransferAmount: 50 -> 0 // if (pr.amount >= transferAmount) { pr.amount -= transferAmount; part.Resources[resource.name].amount += transferAmount; transferAmount = 0; break; } else { // RemotePartAmount: 10 -> 0 // LocalPartAmount: 10 -> 20 // TransferAmount: 50 -> 40 // transferAmount -= pr.amount; part.Resources[resource.name].amount += pr.amount; pr.amount = 0; } } else { var plMods = p.Modules.OfType <ProxyLogistics>().Where(m => m.IsLogisticsDistributor); if (plMods.Any()) { var storageSpace = pr.maxAmount - pr.amount; if (storageSpace >= transferAmount) { // SS: 100 // RemotePartAmount: 400/500 -> 450/500 // LocalPartAmount: 100 -> 50 // TransferAmount: 50 -> 0 pr.amount += transferAmount; part.Resources[resource.name].amount -= transferAmount; transferAmount = 0; break; } else { // SS:10 // RemotePartAmount: 490/500 -> 500/500 // LocalPartAmount: 100 -> 90 // TransferAmount: 50 -> 40 transferAmount -= storageSpace; part.Resources[resource.name].amount -= storageSpace; pr.amount = pr.maxAmount; } } } } } } catch (Exception ex) { print(String.Format("[MKS] - ERROR in TransferResources - {0}", ex.StackTrace)); } }
private static List <Vessel> FetchNewParticipatingVessels() { var nearbyVessels = LogisticsTools.GetNearbyVessels(LOCAL_LOGISTICS_RANGE, true, FlightGlobals.ActiveVessel, true); return(nearbyVessels.Where(HasResources).ToList()); }
private void DrawLogistics() { var vessels = LogisticsTools.GetNearbyVessels(2000, true, _model, true); List <LogisticsResource> resources = new List <LogisticsResource>(); Dictionary <string, float> dr = new Dictionary <string, float>(); int kerbals = 0; foreach (Vessel v in vessels) { // Storage foreach (var r in v.GetStorage()) { getResourceFromList(resources, r.resourceName).maxAmount += r.amount; } // Amount foreach (var r in v.GetResourceAmounts()) { getResourceFromList(resources, r.resourceName).amount += r.amount; } // Production of converters foreach (var r in v.GetProduction()) { getResourceFromList(resources, r.resourceName).change += r.amount; } // Consumption of Converters foreach (var r in v.GetProduction(false)) { getResourceFromList(resources, r.resourceName).change -= r.amount; } // Drills foreach (Part drill in v.Parts.Where(p => p.Modules.Contains("ModuleResourceHarvester"))) { foreach (ModuleResourceHarvester m in drill.FindModulesImplementing <ModuleResourceHarvester>().Where(mod => mod.IsActivated)) { if (v.Parts.Exists(p => p.Resources.list.Exists(r => r.resourceName == m.ResourceName && r.amount < r.maxAmount))) // test if storage for this resource on this vessel is not full { AbundanceRequest ar = new AbundanceRequest { Altitude = v.altitude, BodyId = FlightGlobals.currentMainBody.flightGlobalsIndex, CheckForLock = false, Latitude = v.latitude, Longitude = v.longitude, ResourceType = HarvestTypes.Planetary, ResourceName = m.ResourceName }; getResourceFromList(resources, m.ResourceName).change += (double)ResourceMap.Instance.GetAbundance(ar); getResourceFromList(resources, "ElectricCharge").change -= 6; } } } // Life Support kerbals += v.GetCrewCount(); } if (_usils) { getResourceFromList(resources, "Supplies").change -= kerbals * 0.00005; getResourceFromList(resources, "Mulch").change += kerbals * 0.00005; getResourceFromList(resources, "ElectricCharge").change -= kerbals * 0.01; } resources.Sort(new LogisticsResourceComparer()); foreach (LogisticsResource r in resources) { GUILayout.Label(r.resourceName + ": " + numberToOut(r.amount, -1, false) + "/" + Math.Round(r.maxAmount, 5) + " (" + numberToOut(r.change, r.change > 0 ? r.maxAmount - r.amount : r.amount) + ")"); } }