void FixedUpdate() { // remove control locks in any case Misc.ClearLocks(); // do nothing if paused if (Lib.IsPaused()) { return; } // maintain elapsed_s, converting to double only once // and detect warp blending double fixedDeltaTime = TimeWarp.fixedDeltaTime; if (Math.Abs(fixedDeltaTime - elapsed_s) > double.Epsilon) { warp_blending = 0; } else { ++warp_blending; } elapsed_s = fixedDeltaTime; // evict oldest entry from vessel cache Cache.Update(); if (Features.KCommNet) { KCommNetScenario.CacheCommNetVessels(); } // store info for oldest unloaded vessel double last_time = 0.0; Vessel last_v = null; Vessel_Info last_vi = null; VesselData last_vd = null; Vessel_Resources last_resources = null; // for each vessel foreach (Vessel v in FlightGlobals.Vessels) { // get vessel info from the cache Vessel_Info vi = Cache.VesselInfo(v); // set locks for active vessel if (v.isActiveVessel) { Misc.SetLocks(v, vi); } // maintain eva dead animation and helmet state if (v.loaded && v.isEVA) { EVA.Update(v); } // keep track of rescue mission kerbals, and gift resources to their vessels on discovery if (v.loaded && vi.is_vessel) { // manage rescue mission mechanics Misc.ManageRescueMission(v); } // do nothing else for invalid vessels if (!vi.is_valid) { continue; } // get vessel data from db VesselData vd = DB.Vessel(v); // get resource cache Vessel_Resources resources = ResourceCache.Get(v); // call antenna update trigger Cache.AntennaUpdate(v); // if loaded if (v.loaded) { // show belt warnings Radiation.BeltWarnings(v, vi, vd); // update storm data Storm.Update(v, vi, vd, elapsed_s); // show signal warnings Signal.Update(v, vi, vd, elapsed_s); // consume ec for transmission, and transmit science data Science.Update(v, vi, vd, resources, elapsed_s); // apply rules Profile.Execute(v, vi, vd, resources, elapsed_s); // apply deferred requests resources.Sync(v, elapsed_s); // call automation scripts vd.computer.Automate(v, vi, resources); // remove from unloaded data container unloaded.Remove(vi.id); } // if unloaded else { // get unloaded data, or create an empty one if (!unloaded.TryGetValue(vi.id, out Unloaded_Data ud)) { ud = new Unloaded_Data(); unloaded.Add(vi.id, ud); } // accumulate time ud.time += elapsed_s; // maintain oldest entry if (ud.time > last_time) { last_time = ud.time; last_v = v; last_vi = vi; last_vd = vd; last_resources = resources; } } } // if the oldest unloaded vessel was selected if (last_v != null) { // show belt warnings Radiation.BeltWarnings(last_v, last_vi, last_vd); // update storm data Storm.Update(last_v, last_vi, last_vd, last_time); // show signal warnings Signal.Update(last_v, last_vi, last_vd, last_time); // consume ec for transmission, and transmit science Science.Update(last_v, last_vi, last_vd, last_resources, last_time); // apply rules Profile.Execute(last_v, last_vi, last_vd, last_resources, last_time); // simulate modules in background Background.Update(last_v, last_vi, last_vd, last_resources, last_time); // apply deferred requests last_resources.Sync(last_v, last_time); // call automation scripts last_vd.computer.Automate(last_v, last_vi, last_resources); // remove from unloaded data container unloaded.Remove(last_vi.id); } // update storm data for one body per-step if (storm_bodies.Count > 0) { storm_bodies.ForEach(k => k.time += elapsed_s); Storm_Data sd = storm_bodies[storm_index]; Storm.Update(sd.body, sd.time); sd.time = 0.0; storm_index = (storm_index + 1) % storm_bodies.Count; } }