Skip to content

Commit

Permalink
Showing 5 changed files with 44 additions and 51 deletions.
2 changes: 1 addition & 1 deletion GameData/RP-0/CrewHandlerSettings.cfg
Original file line number Diff line number Diff line change
@@ -17,12 +17,12 @@ CREWHANDLERSETTINGS
retireCourageMax = 3
retireStupidMin = 1
retireStupidMax = 0
trainingProficiencyExpirationYears = 4
trainingProficiencyStupidMin = 1.5 // multiplier to how long proficiency lasts at 0 stupidity
trainingProficiencyStupidMax = 0.5 // multiplier to how long proficiency lasts at 1 stupidity
trainingProficiencyRefresherTimeMult = 0.25
trainingProficiencyXP = 1
trainingMissionExpirationDays = 120
trainingMissionStupidMin = 0.5 // multiplier to how long the training course takes at 0 stupidity
trainingMissionStupidMax = 1.5 // multiplier to how long the training course takes at 1 stupidity
minFlightDurationSecondsForTrainingExpire = 30
}
25 changes: 22 additions & 3 deletions Source/Crew/ActiveCourse.cs
Original file line number Diff line number Diff line change
@@ -188,15 +188,14 @@ public bool ProgressTime(double curT)

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)
@@ -232,10 +231,30 @@ public void CompleteCourse()
exp.expiration += Planetarium.GetUniversalTime();
}

bool prevMissionsAlreadyExpired = false;
foreach (ConfigNode.Value v in RewardLog.values)
{
string[] s = v.value.Split(new char[] { ',', ' ' }, StringSplitOptions.RemoveEmptyEntries);
student.flightLog.AddEntry(s[0], s.Length == 1 ? null : s[1]);
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);
48 changes: 11 additions & 37 deletions Source/Crew/CrewHandler.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
using System;
using System.Collections.Generic;
using System.Text;
using KSP;
using UnityEngine;
using System.Reflection;

@@ -525,6 +523,10 @@ protected void VesselRecoveryRequested(Vessel v)

double UT = Planetarium.GetUniversalTime();

// When flight duration was too short, mission training should not be set as expired.
// This can happen when an on-the-pad failure occurs and the vessel is recovered.
if (elapsedTime < settings.minFlightDurationSecondsForTrainingExpire) return;

foreach (ProtoCrewMember pcm in v.GetVesselCrew())
{
bool hasSpace = false;
@@ -704,7 +706,6 @@ protected void FixTooltip(KSP.UI.CrewListItem cli)

public string GetTrainingString(ProtoCrewMember pcm)
{
HashSet<string> expiredProfs = new HashSet<string>();
bool found = false;
string trainingStr = "\n\nTraining:";
int lastFlight = pcm.careerLog.Last() == null ? 0 : pcm.careerLog.Last().flight;
@@ -713,36 +714,29 @@ public string GetTrainingString(ProtoCrewMember pcm)
string pretty = GetPrettyCourseName(ent.type);
if (!string.IsNullOrEmpty(pretty))
{
if (ent.type == "expired_TRAINING_proficiency")
if (ent.type == "TRAINING_proficiency")
{
found = true;
expiredProfs.Add(ent.target);
trainingStr += "\n " + pretty + ent.target;
}
else
else if (ent.type == "TRAINING_mission")
{
if (ent.type == "TRAINING_mission" && ent.flight != lastFlight)
continue;

found = true;
trainingStr += "\n " + pretty + ent.target;
double exp = GetExpiration(pcm.name, ent);
if (exp > 0d)
trainingStr += ". Expires " + KSPUtil.PrintDate(exp, false);
{
trainingStr += "\n " + pretty + ent.target + ". Expires " + KSPUtil.PrintDate(exp, false);
}
}
}
}
if (expiredProfs.Count > 0)
trainingStr += "\n Expired proficiencies:";
foreach (string s in expiredProfs)
trainingStr += "\n " + s;

if (found)
return trainingStr;
else
return string.Empty;
}

protected double GetExpiration(string pcmName, FlightLog.Entry ent)
public double GetExpiration(string pcmName, FlightLog.Entry ent)
{
for (int i = expireTimes.Count; i-- > 0;)
{
@@ -838,8 +832,6 @@ protected void GenerateCourseProf(AvailablePart ap)
n.AddValue("id", "prof_" + name);
n.AddValue("name", "Proficiency: " + name);
n.AddValue("time", 1d + (TrainingDatabase.GetTime(name) * 86400d));
n.AddValue("expiration", settings.trainingProficiencyExpirationYears * 86400d * 365d);
n.AddValue("expirationUseStupid", true);

n.AddValue("conflicts", "TRAINING_proficiency:" + name);

@@ -851,22 +843,6 @@ protected void GenerateCourseProf(AvailablePart ap)
CourseTemplate c = new CourseTemplate(n);
c.PopulateFromSourceNode();
OfferedCourses.Add(c);

ConfigNode n2 = n.CreateCopy();
n2.SetValue("id", "profR_" + name);
n2.SetValue("name", "Refresher: " + name);
n2.SetValue("time", 1d + TrainingDatabase.GetTime(name) * 86400d * settings.trainingProficiencyRefresherTimeMult);
n2.AddValue("preReqsAny", "expired_TRAINING_proficiency:" + name + ",TRAINING_proficiency:" + name);
n2.RemoveValue("conflicts");

r = n2.GetNode("REWARD");
r.SetValue("XPAmt", "0");
ConfigNode exp = r.AddNode("EXPIRELOG");
exp.AddValue("0", "TRAINING_proficiency," + name);

c = new CourseTemplate(n2);
c.PopulateFromSourceNode();
OfferedCourses.Add(c);
}

protected void GenerateCourseMission(AvailablePart ap)
@@ -904,8 +880,6 @@ protected string GetPrettyCourseName(string str)
{
case "TRAINING_proficiency":
return "Proficiency with ";
case "expired_TRAINING_proficiency":
return "(Expired) Proficiency with ";
case "TRAINING_mission":
return "Mission training for ";
/*case "expired_TRAINING_mission":
5 changes: 4 additions & 1 deletion Source/Crew/CrewHandlerSettings.cs
Original file line number Diff line number Diff line change
@@ -20,14 +20,17 @@ public class CrewHandlerSettings : IConfigNode
public double retireBaseYears = 5d, retireCourageMin = 0d, retireCourageMax = 3d, retireStupidMin = 1d, retireStupidMax = 0d;

[Persistent]
public double trainingProficiencyExpirationYears = 4d, trainingProficiencyStupidMin = 1.5d, trainingProficiencyStupidMax = 0.5d, trainingProficiencyRefresherTimeMult = 0.25d;
public double trainingProficiencyStupidMin = 1.5d, trainingProficiencyStupidMax = 0.5d, trainingProficiencyRefresherTimeMult = 0.25d;

[Persistent]
public int trainingProficiencyXP = 1;

[Persistent]
public double trainingMissionExpirationDays = 120d, trainingMissionStupidMin = 0.5d, trainingMissionStupidMax = 1.5d;

[Persistent]
public double minFlightDurationSecondsForTrainingExpire = 30d;


public void Load(ConfigNode node)
{
15 changes: 6 additions & 9 deletions Source/KCTBinderModule.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
using System;
using System.Collections.Generic;
using System.Text;
using UnityEngine;
using KerbalConstructionTime;
using RP0.Crew;

namespace RP0
{
@@ -39,27 +37,26 @@ public static bool CheckCrewForPart(ProtoCrewMember pcm, string partName)
if (!requireTraining || EntryCostStorage.GetCost(partName) == 1)
return true;

partName = Crew.TrainingDatabase.SynonymReplace(partName);
partName = TrainingDatabase.SynonymReplace(partName);

FlightLog.Entry ent = pcm.careerLog.Last();
if (ent == null)
return false;

int lastFlight = ent.flight;
bool lacksMission = true;
for (int i = pcm.careerLog.Entries.Count; i-- > 0;)
{
FlightLog.Entry e = pcm.careerLog.Entries[i];
if (lacksMission)
{
if (e.flight < lastFlight)
return false;

if (string.IsNullOrEmpty(e.type) || string.IsNullOrEmpty(e.target))
continue;

if (e.type == "TRAINING_mission" && e.target == partName)
lacksMission = false;
{
double exp = CrewHandler.Instance.GetExpiration(pcm.name, e);
lacksMission = exp == 0d || exp < Planetarium.GetUniversalTime();
}
}
else
{

0 comments on commit a1a4e31

Please sign in to comment.