public bool RemoveExpiration(string pcmName, string entry) { for (int i = _expireTimes.Count; i-- > 0;) { TrainingExpiration e = _expireTimes[i]; if (e.PcmName != pcmName) { continue; } for (int j = e.Entries.Count; j-- > 0;) { if (e.Entries[j] == entry) { e.Entries.RemoveAt(j); if (e.Entries.Count == 0) { _expireTimes.RemoveAt(i); } return(true); } } } return(false); }
private void ProcessCourses(double time) { bool anyCourseEnded = false; for (int i = ActiveCourses.Count; i-- > 0;) { ActiveCourse course = ActiveCourses[i]; if (course.ProgressTime(time)) //returns true when the course completes { ActiveCourses.RemoveAt(i); anyCourseEnded = true; } } for (int i = _expireTimes.Count; i-- > 0;) { TrainingExpiration e = _expireTimes[i]; if (time > e.Expiration) { ProtoCrewMember pcm = HighLogic.CurrentGame.CrewRoster[e.PcmName]; if (pcm != null) { for (int j = pcm.careerLog.Entries.Count; j-- > 0;) { int eC = e.Entries.Count; if (eC == 0) { break; } FlightLog.Entry ent = pcm.careerLog[j]; for (int k = eC; k-- > 0;) { // Allow only mission trainings to expire. // This check is actually only needed for old savegames as only these can have expirations on proficiencies. if (ent.type == "TRAINING_mission" && e.Compare(k, ent)) { ScreenMessages.PostScreenMessage(pcm.name + ": Expired: " + GetPrettyCourseName(ent.type) + ent.target); ent.type = "expired_" + ent.type; e.Entries.RemoveAt(k); } } } } _expireTimes.RemoveAt(i); } } if (anyCourseEnded) { MaintenanceHandler.Instance?.ScheduleMaintenanceUpdate(); } }
private double GetExpiration(string pcmName, FlightLog.Entry ent) { for (int i = _expireTimes.Count; i-- > 0;) { TrainingExpiration e = _expireTimes[i]; if (e.PcmName == pcmName) { for (int j = e.Entries.Count; j-- > 0;) { if (e.Compare(j, ent)) { return(e.Expiration); } } } } return(0d); }
private bool SetExpiration(string pcmName, FlightLog.Entry ent, double expirationUT) { for (int i = _expireTimes.Count; i-- > 0;) { TrainingExpiration e = _expireTimes[i]; if (e.PcmName == pcmName) { for (int j = e.Entries.Count; j-- > 0;) { if (e.Compare(j, ent)) { e.Expiration = expirationUT; return(true); } } } } return(false); }
public void CompleteCourse() { //assign rewards to all kerbals and set them to free if (Completed) { foreach (ProtoCrewMember student in Students) { if (student == null) { continue; } if (ExpireLog != null) { foreach (ConfigNode.Value v in ExpireLog.values) { for (int i = student.careerLog.Count; i-- > 0;) { FlightLog.Entry e = student.careerLog.Entries[i]; if (TrainingExpiration.Compare(v.value, e)) { e.type = "expired_" + e.type; CrewHandler.Instance.RemoveExpiration(student.name, v.value); break; } } } } if (RewardLog != null) { if (student.flightLog.Count > 0) { student.ArchiveFlightLog(); } TrainingExpiration exp = null; if (expiration > 0d) { exp = new TrainingExpiration(); exp.PcmName = student.name; exp.Expiration = expiration; if (expirationUseStupid) { exp.Expiration *= UtilMath.Lerp(CrewHandler.Instance.Settings.trainingProficiencyStupidMin, CrewHandler.Instance.Settings.trainingProficiencyStupidMax, student.stupidity); } exp.Expiration += Planetarium.GetUniversalTime(); } bool prevMissionsAlreadyExpired = false; foreach (ConfigNode.Value v in RewardLog.values) { string[] s = v.value.Split(new char[] { ',', ' ' }, StringSplitOptions.RemoveEmptyEntries); string trainingType = s[0]; string trainingTarget = s.Length == 1 ? null : s[1]; if (!prevMissionsAlreadyExpired && trainingType == "TRAINING_mission") { // Expire any previous mission trainings because only 1 should be active at a time for (int i = student.careerLog.Count; i-- > 0;) { FlightLog.Entry e = student.careerLog.Entries[i]; if (e.type == "TRAINING_mission") { e.type = "expired_" + e.type; CrewHandler.Instance.RemoveExpiration(student.name, v.value); student.ArchiveFlightLog(); prevMissionsAlreadyExpired = true; } } } student.flightLog.AddEntry(trainingType, trainingTarget); student.ArchiveFlightLog(); if (expiration > 0d) { exp.Entries.Add(v.value); } } if (expiration > 0d) { CrewHandler.Instance.AddExpiration(exp); } } if (rewardXP != 0) { student.ExtraExperience += rewardXP; } } } foreach (ProtoCrewMember student in Students) { student.inactive = false; } //fire an event }
public void AddExpiration(TrainingExpiration e) { _expireTimes.Add(e); }
public void Update() { if (HighLogic.CurrentGame == null || HighLogic.CurrentGame.CrewRoster == null) { return; } // Catch earlies if (firstLoad) { firstLoad = false; List <string> newHires = new List <string>(); foreach (ProtoCrewMember pcm in HighLogic.CurrentGame.CrewRoster.Crew) { if ((pcm.rosterStatus == ProtoCrewMember.RosterStatus.Assigned || pcm.rosterStatus == ProtoCrewMember.RosterStatus.Available) && !kerbalRetireTimes.ContainsKey(pcm.name)) { newHires.Add(pcm.name); OnCrewHired(pcm, int.MinValue); } } if (newHires.Count > 0) { string msgStr = "Crew will retire as follows:"; foreach (string s in newHires) { msgStr += "\n" + s + ", no earlier than " + KSPUtil.PrintDate(kerbalRetireTimes[s], false); } PopupDialog.SpawnPopupDialog(new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), "InitialRetirementDateNotification", "Initial Retirement Date", msgStr + "\n(Retirement will be delayed the more interesting flights they fly.)", "OK", false, HighLogic.UISkin); } } // Retirements double time = Planetarium.GetUniversalTime(); if (nextUpdate < time) { // Ensure that CrewHandler updates happen at predictable times so that accurate KAC alarms can be set. do { nextUpdate += updateInterval; }while (nextUpdate < time); if (retirementEnabled) { foreach (KeyValuePair <string, double> kvp in kerbalRetireTimes) { ProtoCrewMember pcm = HighLogic.CurrentGame.CrewRoster[kvp.Key]; if (pcm == null) { toRemove.Add(kvp.Key); } else { if (pcm.rosterStatus != ProtoCrewMember.RosterStatus.Available) { if (pcm.rosterStatus != ProtoCrewMember.RosterStatus.Assigned) { toRemove.Add(kvp.Key); } continue; } if (pcm.inactive) { continue; } if (time > kvp.Value) { toRemove.Add(kvp.Key); retirees.Add(kvp.Key); pcm.rosterStatus = ProtoCrewMember.RosterStatus.Dead; } } } } bool anyCourseEnded = false; for (int i = ActiveCourses.Count; i-- > 0;) { ActiveCourse course = ActiveCourses[i]; if (course.ProgressTime(time)) //returns true when the course completes { ActiveCourses.RemoveAt(i); anyCourseEnded = true; } } for (int i = expireTimes.Count; i-- > 0;) { TrainingExpiration e = expireTimes[i]; if (time > e.expiration) { ProtoCrewMember pcm = HighLogic.CurrentGame.CrewRoster[e.pcmName]; if (pcm != null) { for (int j = pcm.careerLog.Entries.Count; j-- > 0;) { int eC = e.entries.Count; if (eC == 0) { break; } FlightLog.Entry ent = pcm.careerLog[j]; for (int k = eC; k-- > 0;) { // Allow only mission trainings to expire. // This check is actually only needed for old savegames as only these can have expirations on proficiencies. if (ent.type == "TRAINING_mission" && e.Compare(k, ent)) { ScreenMessages.PostScreenMessage(pcm.name + ": Expired: " + GetPrettyCourseName(ent.type) + ent.target); ent.type = "expired_" + ent.type; e.entries.RemoveAt(k); } } } } expireTimes.RemoveAt(i); } } // TODO remove from courses? Except I think they won't retire if inactive either so that's ok. if (toRemove.Count > 0) { string msgStr = string.Empty; foreach (string s in toRemove) { kerbalRetireTimes.Remove(s); if (HighLogic.CurrentGame.CrewRoster[s] != null) { msgStr += "\n" + s; } } if (!string.IsNullOrEmpty(msgStr)) { PopupDialog.SpawnPopupDialog(new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), "CrewRetirementNotification", "Crew Retirement", "The following retirements have occurred:\n" + msgStr, "OK", true, HighLogic.UISkin); } toRemove.Clear(); } if (anyCourseEnded || toRemove.Count > 0) { MaintenanceHandler.Instance.UpdateUpkeep(); } } // UI fixing if (inAC) { if (astronautComplex == null) { KSP.UI.Screens.AstronautComplex[] mbs = GameObject.FindObjectsOfType <KSP.UI.Screens.AstronautComplex>(); int maxCount = -1; foreach (KSP.UI.Screens.AstronautComplex c in mbs) { int count = c.ScrollListApplicants.Count + c.ScrollListAssigned.Count + c.ScrollListAvailable.Count + c.ScrollListKia.Count; if (count > maxCount) { maxCount = count; astronautComplex = c; } } if (astronautComplex == null) { return; } } int newAv = astronautComplex.ScrollListAvailable.Count; int newAsgn = astronautComplex.ScrollListAssigned.Count; int newKIA = astronautComplex.ScrollListKia.Count; if (newAv != countAvailable || newKIA != countKIA || newAsgn != countAssigned) { countAvailable = newAv; countAssigned = newAsgn; countKIA = newKIA; foreach (KSP.UI.UIListData <KSP.UI.UIListItem> u in astronautComplex.ScrollListAvailable) { KSP.UI.CrewListItem cli = u.listItem.GetComponent <KSP.UI.CrewListItem>(); if (cli != null) { FixTooltip(cli); if (cli.GetCrewRef().inactive) { cli.MouseoverEnabled = false; bool notTraining = true; for (int i = ActiveCourses.Count; i-- > 0 && notTraining;) { foreach (ProtoCrewMember pcm in ActiveCourses[i].Students) { if (pcm == cli.GetCrewRef()) { notTraining = false; cli.SetLabel("Training, done " + KSPUtil.PrintDate(ActiveCourses[i].startTime + ActiveCourses[i].GetTime(ActiveCourses[i].Students), false)); break; } } } if (notTraining) { cli.SetLabel("Recovering"); } } } } foreach (KSP.UI.UIListData <KSP.UI.UIListItem> u in astronautComplex.ScrollListAssigned) { KSP.UI.CrewListItem cli = u.listItem.GetComponent <KSP.UI.CrewListItem>(); if (cli != null) { FixTooltip(cli); } } foreach (KSP.UI.UIListData <KSP.UI.UIListItem> u in astronautComplex.ScrollListKia) { KSP.UI.CrewListItem cli = u.listItem.GetComponent <KSP.UI.CrewListItem>(); if (cli != null) { if (retirees.Contains(cli.GetName())) { cli.SetLabel("Retired"); cli.MouseoverEnabled = false; } } } } } }