protected virtual List <ModuleDataTransmitter> GetTransmittersLoaded(Vessel v) { List <ModuleDataTransmitter> transmitters; if (!Cache.HasVesselObjectsCache(v, "commnet")) { // find transmitters transmitters = v.FindPartModulesImplementing <ModuleDataTransmitter>(); if (transmitters == null) { transmitters = new List <ModuleDataTransmitter>(); } // Disable all stock buttons // TODO : moved from the update method (AntennaInfo()) to here to save performance, but maybe that is called too early and doesn't work foreach (ModuleDataTransmitter mdt in transmitters) { mdt.Events["TransmitIncompleteToggle"].active = false; mdt.Events["StartTransmission"].active = false; mdt.Events["StopTransmission"].active = false; mdt.Actions["StartTransmissionAction"].active = false; } Cache.SetVesselObjectsCache(v, "commnet", transmitters); } else { transmitters = Cache.VesselObjectsCache <List <ModuleDataTransmitter> >(v, "commnet"); } return(transmitters); }
public static void BackgroundUpdate(Vessel v, ProtoPartModuleSnapshot m, KerbalismProcess process, Resource_info ec, Vessel_resources resources, double elapsed_s) { if (!process.unloaded) { return; } List <KeyValuePair <string, double> > resourcesProduced; List <KeyValuePair <string, double> > resourcesConsumed; if (!Cache.HasVesselObjectsCache(v, "kerbalism_process_produced_" + process.part.flightID)) { resourcesProduced = ParseResources(process.resources_produced, false); Cache.SetVesselObjectsCache <List <KeyValuePair <string, double> > >(v, "kerbalism_process_produced_" + process.part.flightID, resourcesProduced); } else { resourcesProduced = Cache.VesselObjectsCache <List <KeyValuePair <string, double> > >(v, "kerbalism_process_produced_" + process.part.flightID); } if (!Cache.HasVesselObjectsCache(v, "kerbalism_process_consumed_" + process.part.flightID)) { resourcesConsumed = ParseResources(process.resources_produced, false); Cache.SetVesselObjectsCache <List <KeyValuePair <string, double> > >(v, "kerbalism_process_consumed_" + process.part.flightID, resourcesConsumed); } else { resourcesConsumed = Cache.VesselObjectsCache <List <KeyValuePair <string, double> > >(v, "kerbalism_process_consumed_" + process.part.flightID); } RunProcessTick(v, elapsed_s, process.ec_produced, resourcesProduced, process.ec_consumed, resourcesConsumed, ec, resources); }
protected virtual List <KeyValuePair <ModuleDataTransmitter, ProtoPartSnapshot> > GetTransmittersUnloaded(Vessel v) { List <KeyValuePair <ModuleDataTransmitter, ProtoPartSnapshot> > transmitters; if (!Cache.HasVesselObjectsCache(v, "commnet_bg")) { transmitters = new List <KeyValuePair <ModuleDataTransmitter, ProtoPartSnapshot> >(); // find proto transmitters foreach (ProtoPartSnapshot p in v.protoVessel.protoPartSnapshots) { // get part prefab (required for module properties) Part part_prefab = PartLoader.getPartInfoByName(p.partName).partPrefab; foreach (ModuleDataTransmitter t in part_prefab.FindModulesImplementing <ModuleDataTransmitter>()) { transmitters.Add(new KeyValuePair <ModuleDataTransmitter, ProtoPartSnapshot>(t, p)); } } Cache.SetVesselObjectsCache(v, "commnet_bg", transmitters); } else { // cache transmitters transmitters = Cache.VesselObjectsCache <List <KeyValuePair <ModuleDataTransmitter, ProtoPartSnapshot> > >(v, "commnet_bg"); } return(transmitters); }
public static void Update(Vessel v) { // do nothing if not an eva kerbal if (!v.isEVA) return; // get KerbalEVA module KerbalEVA kerbal = Lib.FindModules<KerbalEVA>(v)[0]; Vessel_info vi = Cache.VesselInfo(v); // Stock KSP adds 5 units of monoprop to EVAs. We want to limit that amount // to whatever was available in the ship, so we don't magically create EVA prop out of nowhere if(Cache.HasVesselObjectsCache(v, "eva_prop")) { Lib.Log("### have eva_prop for " + v); var quantity = Cache.VesselObjectsCache<double>(v, "eva_prop"); Cache.RemoveVesselObjectsCache(v, "eva_prop"); Lib.Log("### adding " + quantity + " eva prop"); Lib.SetResource(kerbal.part, Lib.EvaPropellantName(), quantity, Lib.EvaPropellantCapacity()); } // get resource handler Resource_info ec = ResourceCache.Info(v, "ElectricCharge"); // determine if headlamps need ec // - not required if there is no EC capacity in eva kerbal (no ec supply in profile) // - not required if no EC cost for headlamps is specified (set by the user) bool need_ec = ec.capacity > double.Epsilon && Settings.HeadLampsCost > double.Epsilon; // consume EC for the headlamps if (need_ec && kerbal.lampOn) { ec.Consume(Settings.HeadLampsCost * Kerbalism.elapsed_s, "headlamp"); } // force the headlamps on/off HeadLamps(kerbal, kerbal.lampOn && (!need_ec || ec.amount > double.Epsilon)); // if dead if (IsDead(v)) { // enforce freezed state Freeze(kerbal); // disable modules DisableModules(kerbal); // remove plant flag action kerbal.flagItems = 0; } }
protected virtual List <KeyValuePair <ModuleDataTransmitter, ProtoPartModuleSnapshot> > GetTransmittersUnloaded(Vessel v) { List <KeyValuePair <ModuleDataTransmitter, ProtoPartModuleSnapshot> > transmitters; if (!Cache.HasVesselObjectsCache(v, "commnet_bg")) { transmitters = new List <KeyValuePair <ModuleDataTransmitter, ProtoPartModuleSnapshot> >(); // find proto transmitters foreach (ProtoPartSnapshot pps in v.protoVessel.protoPartSnapshots) { // get part prefab (required for module properties) Part part_prefab = pps.partInfo.partPrefab; for (int i = 0; i < part_prefab.Modules.Count; i++) { if (part_prefab.Modules[i] is ModuleDataTransmitter mdt) { ProtoPartModuleSnapshot ppms; // We want to also get a possible ModuleDataTransmitter derivative but type checking isn't available // so we check a specific value present on the base class (See ModuleDataTransmitter.OnSave()) if (pps.modules[i].moduleValues.HasValue("canComm")) { ppms = pps.modules[i]; } // fallback in case the module indexes are messed up else { ppms = pps.FindModule("ModuleDataTransmitter"); Lib.LogDebug($"Could not find a ModuleDataTransmitter or derivative at index {i} on part {pps.partName} on vessel {v.protoVessel.vesselName}", Lib.LogLevel.Warning); } if (ppms != null) { transmitters.Add(new KeyValuePair <ModuleDataTransmitter, ProtoPartModuleSnapshot>(mdt, ppms)); } } } } Cache.SetVesselObjectsCache(v, "commnet_bg", transmitters); } else { // cache transmitters transmitters = Cache.VesselObjectsCache <List <KeyValuePair <ModuleDataTransmitter, ProtoPartModuleSnapshot> > >(v, "commnet_bg"); } return(transmitters); }
protected virtual List <ModuleDataTransmitter> GetTransmittersLoaded(Vessel v) { List <ModuleDataTransmitter> transmitters; if (!Cache.HasVesselObjectsCache(v, "commnet")) { // find transmitters transmitters = v.FindPartModulesImplementing <ModuleDataTransmitter>(); if (transmitters == null) { transmitters = new List <ModuleDataTransmitter>(); } Cache.SetVesselObjectsCache(v, "commnet", transmitters); } else { transmitters = Cache.VesselObjectsCache <List <ModuleDataTransmitter> >(v, "commnet"); } return(transmitters); }
public AntennaInfoCommNet(Vessel v, bool powered, bool storm, bool transmitting) { int transmitterCount = 0; rate = 1; double ec_transmitter = 0; // if vessel is loaded if (v.loaded) { List <ModuleDataTransmitter> transmitters; if (!Cache.HasVesselObjectsCache(v, "commnet")) { // find transmitters transmitters = v.FindPartModulesImplementing <ModuleDataTransmitter>(); if (transmitters == null) { transmitters = new List <ModuleDataTransmitter>(); } Cache.SetVesselObjectsCache(v, "commnet", transmitters); } else { transmitters = Cache.VesselObjectsCache <List <ModuleDataTransmitter> >(v, "commnet"); } foreach (ModuleDataTransmitter t in transmitters) { // Disable all stock buttons t.Events["TransmitIncompleteToggle"].active = false; t.Events["StartTransmission"].active = false; t.Events["StopTransmission"].active = false; t.Actions["StartTransmissionAction"].active = false; if (t.antennaType == AntennaType.INTERNAL) // do not include internal data rate, ec cost only { ec += t.DataResourceCost * t.DataRate; } else { // do we have an animation ModuleDeployableAntenna animation = t.part.FindModuleImplementing <ModuleDeployableAntenna>(); ModuleAnimateGeneric animationGeneric = t.part.FindModuleImplementing <ModuleAnimateGeneric>(); if (animation != null) { // only include data rate and ec cost if transmitter is extended if (animation.deployState == ModuleDeployablePart.DeployState.EXTENDED) { rate *= t.DataRate; transmitterCount++; var e = t.DataResourceCost * t.DataRate; ec_transmitter += e; } } else if (animationGeneric != null) { // only include data rate and ec cost if transmitter is extended if (animationGeneric.animSpeed > 0) { rate *= t.DataRate; transmitterCount++; var e = t.DataResourceCost * t.DataRate; ec_transmitter += e; } } // no animation else { rate *= t.DataRate; transmitterCount++; var e = t.DataResourceCost * t.DataRate; ec_transmitter += e; } } } } // if vessel is not loaded else { List <KeyValuePair <ModuleDataTransmitter, ProtoPartSnapshot> > transmitters; if (!Cache.HasVesselObjectsCache(v, "commnet_bg")) { transmitters = new List <KeyValuePair <ModuleDataTransmitter, ProtoPartSnapshot> >(); // find proto transmitters foreach (ProtoPartSnapshot p in v.protoVessel.protoPartSnapshots) { // get part prefab (required for module properties) Part part_prefab = PartLoader.getPartInfoByName(p.partName).partPrefab; foreach (ModuleDataTransmitter t in part_prefab.FindModulesImplementing <ModuleDataTransmitter>()) { transmitters.Add(new KeyValuePair <ModuleDataTransmitter, ProtoPartSnapshot>(t, p)); } } Cache.SetVesselObjectsCache(v, "commnet_bg", transmitters); } else { // cache transmitters transmitters = Cache.VesselObjectsCache <List <KeyValuePair <ModuleDataTransmitter, ProtoPartSnapshot> > >(v, "commnet_bg"); } foreach (var pair in transmitters) { ModuleDataTransmitter t = pair.Key; ProtoPartSnapshot p = pair.Value; if (t.antennaType == AntennaType.INTERNAL) // do not include internal data rate, ec cost only { ec += t.DataResourceCost * t.DataRate; } else { // do we have an animation ProtoPartModuleSnapshot m = p.FindModule("ModuleDeployableAntenna") ?? p.FindModule("ModuleAnimateGeneric"); if (m != null) { // only include data rate and ec cost if transmitter is extended string deployState = Lib.Proto.GetString(m, "deployState"); float animSpeed = Lib.Proto.GetFloat(m, "animSpeed"); if (deployState == "EXTENDED" || animSpeed > 0) { rate *= t.DataRate; transmitterCount++; ec_transmitter += t.DataResourceCost * t.DataRate; } } // no animation else { rate *= t.DataRate; transmitterCount++; ec_transmitter += t.DataResourceCost * t.DataRate; } } } } if (transmitterCount > 1) { rate = Math.Pow(rate, 1.0 / transmitterCount); } else if (transmitterCount == 0) { rate = 0; } // when transmitting, transmitters need more EC for the signal amplifiers. // while not transmitting, transmitters only use 10-20% of that ec_transmitter *= transmitting ? Settings.TransmitterActiveEcFactor : Settings.TransmitterPassiveEcFactor; ec += ec_transmitter; Init(v, powered, storm); }
public Vessel_info(Vessel v, Guid vessel_id, UInt64 inc) { // NOTE: anything used here can't in turn use cache, unless you know what you are doing // NOTE: you can't cache vessel position // at any point in time all vessel/body positions are relative to a different frame of reference // so comparing the current position of a vessel, with the cached one of another make no sense // associate with an unique incremental id this.inc = inc; // determine if this is a valid vessel is_vessel = Lib.IsVessel(v); if (!is_vessel) { return; } // determine if this is a rescue mission vessel is_rescue = Misc.IsRescueMission(v); if (is_rescue) { return; } // dead EVA are not valid vessels if (EVA.IsDead(v)) { return; } // shortcut for common tests is_valid = true; // generate id once id = vessel_id; // calculate crew info for the vessel crew_count = Lib.CrewCount(v); crew_capacity = Lib.CrewCapacity(v); // get vessel position Vector3d position = Lib.VesselPosition(v); // this should never happen again if (Vector3d.Distance(position, v.mainBody.position) < 1.0) { throw new Exception("Shit hit the fan for vessel " + v.vesselName); } // determine if there is enough EC for a powered state powered = Lib.IsPowered(v); // determine if in sunlight, calculate sun direction and distance sunlight = Sim.RaytraceBody(v, position, FlightGlobals.Bodies[0], out sun_dir, out sun_dist) ? 1.0 : 0.0; // environment stuff atmo_factor = Sim.AtmosphereFactor(v.mainBody, position, sun_dir); gamma_transparency = Sim.GammaTransparency(v.mainBody, v.altitude); underwater = Sim.Underwater(v); breathable = Sim.Breathable(v, underwater); landed = Lib.Landed(v); zerog = !landed && (!v.mainBody.atmosphere || v.mainBody.atmosphereDepth < v.altitude); if (v.mainBody.flightGlobalsIndex != 0 && TimeWarp.CurrentRate > 1000.0f) { highspeedWarp(v); } // temperature at vessel position temperature = Sim.Temperature(v, position, sunlight, atmo_factor, out solar_flux, out albedo_flux, out body_flux, out total_flux); temp_diff = Sim.TempDiff(temperature, v.mainBody, landed); // radiation radiation = Radiation.Compute(v, position, gamma_transparency, sunlight, out blackout, out magnetosphere, out inner_belt, out outer_belt, out interstellar); // extended atmosphere thermosphere = Sim.InsideThermosphere(v); exosphere = Sim.InsideExosphere(v); // malfunction stuff malfunction = Reliability.HasMalfunction(v); critical = Reliability.HasCriticalFailure(v); // communications info connection = ConnectionInfo.Update(v, powered, blackout); transmitting = Science.Transmitting(v, connection.linked && connection.rate > double.Epsilon); // habitat data volume = Habitat.Tot_volume(v); surface = Habitat.Tot_surface(v); if (Cache.HasVesselObjectsCache(v, "max_pressure")) { max_pressure = Cache.VesselObjectsCache <double>(v, "max_pressure"); } pressure = Math.Min(max_pressure, Habitat.Pressure(v)); evas = (uint)(Math.Max(0, ResourceCache.Info(v, "Nitrogen").amount - 330) / PreferencesLifeSupport.Instance.evaAtmoLoss); poisoning = Habitat.Poisoning(v); humidity = Habitat.Humidity(v); shielding = Habitat.Shielding(v); living_space = Habitat.Living_space(v); volume_per_crew = Habitat.Volume_per_crew(v); comforts = new Comforts(v, landed, crew_count > 1, connection.linked && connection.rate > double.Epsilon); // data about greenhouses greenhouses = Greenhouse.Greenhouses(v); // other stuff gravioli = Sim.Graviolis(v); Drive.GetCapacity(v, out free_capacity, out total_capacity); }