void VesselRecovered(ProtoVessel pv, bool b) { // note: this is called multiple times when a vessel is recovered // for each crew member foreach (ProtoCrewMember c in pv.GetVesselCrew()) { // avoid creating kerbal data in db again, // as this function may be called multiple times if (!DB.ContainsKerbal(c.name)) { continue; } // set roster status of eva dead kerbals if (DB.Kerbal(c.name).eva_dead) { c.rosterStatus = ProtoCrewMember.RosterStatus.Dead; } // reset kerbal data of recovered kerbals DB.RecoverKerbal(c.name); } DB.vessels.Remove(Lib.VesselID(pv)); // purge the caches ResourceCache.Purge(pv); Drive.Purge(pv); Cache.PurgeObjects(pv); }
void PartDestroyed(Part p) { // do nothing in the editor if (Lib.IsEditor()) { return; } var vi = Cache.VesselInfo(p.vessel); if (!vi.is_valid) { return; } Cache.PurgeObjects(p.vessel); if (DB.drives.ContainsKey(p.flightID)) { foreach (var pair in DB.drives[p.flightID].files) { if (pair.Value.buff > double.Epsilon) { Science.Credit(pair.Key, pair.Value.buff, true, p.vessel.protoVessel); } } } DB.drives.Remove(p.flightID); }
void FromEVA(GameEvents.FromToAction <Part, Part> data) { String prop_name = Lib.EvaPropellantName(); // for each resource in the eva kerbal for (int i = 0; i < data.from.Resources.Count; ++i) { // get the resource PartResource res = data.from.Resources[i]; // add leftovers to the vessel data.to.RequestResource(res.resourceName, -res.amount); } // merge drives data Drive.Transfer(data.from.vessel, data.to.vessel, true); // forget vessel data DB.vessels.Remove(Lib.VesselID(data.from.vessel)); Drive.Purge(data.from.vessel); Cache.PurgeObjects(data.from.vessel); Cache.PurgeObjects(data.to.vessel); // execute script DB.Vessel(data.to.vessel).computer.Execute(data.to.vessel, ScriptType.eva_in); }
void VesselTerminated(ProtoVessel pv) { // forget all kerbals data foreach (ProtoCrewMember c in pv.GetVesselCrew()) { DB.KillKerbal(c.name, true); } DB.vessels.Remove(Lib.VesselID(pv)); // purge the caches ResourceCache.Purge(pv); Drive.Purge(pv); Cache.PurgeObjects(pv); }
public Callbacks() { GameEvents.onCrewOnEva.Add(this.ToEVA); GameEvents.onCrewBoardVessel.Add(this.FromEVA); GameEvents.onVesselRecoveryProcessing.Add(this.VesselRecoveryProcessing); GameEvents.onVesselRecovered.Add(this.VesselRecovered); GameEvents.onVesselTerminated.Add(this.VesselTerminated); GameEvents.onVesselWillDestroy.Add(this.VesselDestroyed); GameEvents.onNewVesselCreated.Add(this.VesselCreated); GameEvents.onPartCouple.Add(this.VesselDock); GameEvents.onVesselChange.Add((v) => { Cache.PurgeObjects(v); }); GameEvents.onVesselStandardModification.Add((v) => { Cache.PurgeObjects(v); }); GameEvents.onPartDie.Add(this.PartDestroyed); GameEvents.OnTechnologyResearched.Add(this.TechResearched); GameEvents.onGUIEditorToolbarReady.Add(this.AddEditorCategory); GameEvents.onGUIAdministrationFacilitySpawn.Add(() => visible = false); GameEvents.onGUIAdministrationFacilityDespawn.Add(() => visible = true); GameEvents.onGUIAstronautComplexSpawn.Add(() => visible = false); GameEvents.onGUIAstronautComplexDespawn.Add(() => visible = true); GameEvents.onGUIMissionControlSpawn.Add(() => visible = false); GameEvents.onGUIMissionControlDespawn.Add(() => visible = true); GameEvents.onGUIRnDComplexSpawn.Add(() => visible = false); GameEvents.onGUIRnDComplexDespawn.Add(() => visible = true); GameEvents.onHideUI.Add(() => visible = false); GameEvents.onShowUI.Add(() => visible = true); GameEvents.onGUILaunchScreenSpawn.Add((_) => visible = false); GameEvents.onGUILaunchScreenDespawn.Add(() => visible = true); GameEvents.onGameSceneSwitchRequested.Add((_) => { visible = false; Cache.PurgeObjects(); Science.CreditAllDeferred(); }); GameEvents.onGUIApplicationLauncherReady.Add(() => visible = true); GameEvents.CommNet.OnNetworkInitialized.Add(() => Kerbalism.Fetch.StartCoroutine(NetworkInitialized())); // add editor events GameEvents.onEditorShipModified.Add((sc) => Planner.Planner.EditorShipModifiedEvent(sc)); }
void VesselDock(GameEvents.FromToAction <Part, Part> e) { var fromVessel = e.from.vessel; DB.vessels.Remove(Lib.VesselID(fromVessel)); // note: // we do not forget vessel data here, it just became inactive // and ready to be implicitly activated again on undocking // we do however tweak the data of the vessel being docked a bit, // to avoid states getting out of sync, leading to unintuitive behaviours VesselData vd = DB.Vessel(fromVessel); vd.msg_belt = false; vd.msg_signal = false; vd.storm_age = 0.0; vd.storm_time = 0.0; vd.storm_state = 0; vd.supplies.Clear(); vd.scansat_id.Clear(); Cache.PurgeObjects(); }
void VesselDestroyed(Vessel v) { DB.vessels.Remove(Lib.VesselID(v)); // rescan the damn kerbals // - vessel crew is empty at destruction time // - we can't even use the flightglobal roster, because sometimes it isn't updated yet at this point HashSet <string> kerbals_alive = new HashSet <string>(); HashSet <string> kerbals_dead = new HashSet <string>(); foreach (Vessel ov in FlightGlobals.Vessels) { foreach (ProtoCrewMember c in Lib.CrewList(ov)) { kerbals_alive.Add(c.name); } } foreach (KeyValuePair <string, KerbalData> p in DB.Kerbals()) { if (!kerbals_alive.Contains(p.Key)) { kerbals_dead.Add(p.Key); } } foreach (string n in kerbals_dead) { // we don't know if the kerbal really is dead, or if it is just not currently assigned to a mission DB.KillKerbal(n, false); } // purge the caches ResourceCache.Purge(v); Drive.Purge(v); Cache.PurgeObjects(v); }
void ToEVA(GameEvents.FromToAction <Part, Part> data) { Cache.PurgeObjects(data.from.vessel); Cache.PurgeObjects(data.to.vessel); // get total crew in the origin vessel double tot_crew = Lib.CrewCount(data.from.vessel) + 1.0; // get vessel resources handler Vessel_resources resources = ResourceCache.Get(data.from.vessel); // setup supply resources capacity in the eva kerbal Profile.SetupEva(data.to); String prop_name = Lib.EvaPropellantName(); // for each resource in the kerbal for (int i = 0; i < data.to.Resources.Count; ++i) { // get the resource PartResource res = data.to.Resources[i]; // eva prop is handled differently if (res.resourceName == prop_name) { continue; } double quantity = Math.Min(resources.Info(data.from.vessel, res.resourceName).amount / tot_crew, res.maxAmount); // remove resource from vessel quantity = data.from.RequestResource(res.resourceName, quantity); // add resource to eva kerbal data.to.RequestResource(res.resourceName, -quantity); } // take as much of the propellant as possible. just imagine: there are 1.3 units left, and 12 occupants // in the ship. you want to send out an engineer to fix the chemical plant that produces monoprop, // and have to get from one end of the station to the other with just 0.1 units in the tank... // nope. double evaPropQuantity = data.from.RequestResource(prop_name, Lib.EvaPropellantCapacity()); // We can't just add the monoprop here, because that doesn't always work. It might be related // to the fact that stock KSP wants to add 5 units of monoprop to new EVAs. Instead of fighting KSP here, // we just let it do it's thing and set our amount later in EVA.cs - which seems to work just fine. // don't put that into Cache.VesselInfo because that can be deleted before we get there Cache.SetVesselObjectsCache(data.to.vessel, "eva_prop", evaPropQuantity); // Airlock loss resources.Consume(data.from.vessel, "Nitrogen", PreferencesLifeSupport.Instance.evaAtmoLoss, "airlock"); // show warning if there is little or no EVA propellant in the suit if (evaPropQuantity <= 0.05 && !Lib.Landed(data.from.vessel)) { Message.Post(Severity.danger, Lib.BuildString("There isn't any <b>", prop_name, "</b> in the EVA suit"), "Don't let the ladder go!"); } // turn off headlamp light, to avoid stock bug that show them for a split second when going on eva KerbalEVA kerbal = data.to.FindModuleImplementing <KerbalEVA>(); EVA.HeadLamps(kerbal, false); // execute script DB.Vessel(data.from.vessel).computer.Execute(data.from.vessel, ScriptType.eva_out); }