Skip to content

Commit

Permalink
Showing 7 changed files with 502 additions and 8 deletions.
Binary file modified GameData/RP-0/Plugins/RP0.dll
Binary file not shown.
16 changes: 10 additions & 6 deletions Source/RP0.csproj
Original file line number Diff line number Diff line change
@@ -90,6 +90,10 @@
<Compile Include="ProceduralAvionics\ProceduralAvionicsUnlockedNodes.cs" />
<Compile Include="ProceduralAvionics\ProceduralAvionicsUtils.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Tooling\ModuleToolingy.cs" />
<Compile Include="Tooling\ToolingDatabase.cs" />
<Compile Include="Tooling\ToolingScenario.cs" />
<Compile Include="Tooling\ModuleToolingPTank.cs" />
<Compile Include="Utilities\KSPUtils.cs" />
<Compile Include="Utilities\MathUtils.cs" />
<Compile Include="Utilities\ObjectSerializer.cs" />
@@ -122,11 +126,11 @@
<PropertyGroup>
<PostBuildEvent>del "System.Core.dll"</PostBuildEvent>
</PropertyGroup>
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>
4 changes: 2 additions & 2 deletions Source/RP0.sln
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.26020.0
# Visual Studio 14
VisualStudioVersion = 14.0.25420.1
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RP0", "RP0.csproj", "{997854F8-4EFB-4A78-87BC-F7C8CEA64669}"
EndProject
107 changes: 107 additions & 0 deletions Source/Tooling/ModuleToolingPTank.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using KSP;
using UnityEngine;

namespace RP0
{
class ModuleToolingPTank : ModuleTooling
{
protected PartModule procTank, procShape;
protected string shapeName = string.Empty;
protected bool cone = false;

protected BaseField diam1, diam2, length;

public override void OnAwake()
{
base.OnAwake();

procTank = part.Modules["ProceduralPart"];
}
protected void GetDimensions(out float diam, out float len)
{
diam = 0f;
len = 0f;

if (procTank == null)
return;

string newName = procTank.Fields["shapeName"].GetValue<string>(procTank);
if (newName != shapeName || procShape == null)
{
shapeName = newName;
switch (shapeName)
{
case "Smooth Cone":
procShape = part.Modules["ProceduralShapeBezierCone"];
cone = true;
break;
case "Cone":
procShape = part.Modules["ProceduralShapeCone"];
cone = true;
break;
case "Fillet Cylinder":
procShape = part.Modules["ProceduralShapePill"];
break;

default: // "Cylinder"
procShape = part.Modules["ProceduralShapeCylinder"];
break;
}

if (procShape == null)
return;

if (cone)
{
diam1 = procShape.Fields["topDiameter"];
diam2 = procShape.Fields["bottomDiameter"];
}
else
{
diam1 = procShape.Fields["Diameter"];
diam2 = null;
}

length = procShape.Fields["length"];
}
else if (procShape == null)
return;

if (cone)
diam = Math.Max(diam1.GetValue<float>(procShape), diam2.GetValue<float>(procShape));
else
diam = diam1.GetValue<float>(procShape);

len = length.GetValue<float>(procShape);
}

public override float GetToolingCost()
{
float d, l;
GetDimensions(out d, out l);
float cost = lengthToolingCost.x * d * d + lengthToolingCost.y * d + lengthToolingCost.z * l + lengthToolingCost.w;
if (ToolingDatabase.HasTooling(toolingType, d, l) == ToolingDatabase.ToolingLevel.None)
cost += diameterToolingCost.x * d * d + diameterToolingCost.y * d + diameterToolingCost.z;

return cost;
}

public override void PurchaseTooling()
{
float d, l;
GetDimensions(out d, out l);
ToolingDatabase.UnlockTooling(toolingType, d, l);
}

public override bool IsUnlocked()
{
float d, l;
GetDimensions(out d, out l);
return ToolingDatabase.HasTooling(toolingType, d, l) == ToolingDatabase.ToolingLevel.Full;
}
}
}
117 changes: 117 additions & 0 deletions Source/Tooling/ModuleToolingy.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using KSP;
using UnityEngine;

namespace RP0
{
public abstract class ModuleTooling : PartModule, IPartCostModifier
{
[KSPField]
public string toolingType = "TankStarting";

[KSPField]
public string toolingName = "Tool Tank";

[KSPField]
public float untooledMultiplier = 10f;

[KSPField]
public float finalToolingCostMultiplier = 1f;

[KSPField]
// d^2, d^1, 1
public Vector3 diameterToolingCost = new Vector3(6000f, 12000f, 500f);

[KSPField]
// d^2, d^1, l^1, 1
public Vector4 lengthToolingCost = new Vector4(500f, 2000f, 200f, 100f);

[KSPEvent(guiActive = false, guiActiveEditor = true, guiName = "Tool Tank")]
public virtual void ToolingEvent()
{
if (IsUnlocked())
return;

float toolingCost = GetToolingCost();
bool canAfford = true;
if (!HighLogic.CurrentGame.Parameters.Difficulty.BypassEntryPurchaseAfterResearch)
{
if (Funding.Instance.Funds < toolingCost)
canAfford = false;
}
else
toolingCost = 0f;

PopupDialog.SpawnPopupDialog(new Vector2(0.5f, 0.5f),
new Vector2(0.5f, 0.5f),
new MultiOptionDialog(
"Tooling has not yet been set up for this part. It will cost " + toolingCost.ToString("N0") + " funds.",
"ModuleManager",
HighLogic.UISkin,
new Rect(0.5f, 0.5f, 150f, 60f),
new DialogGUIFlexibleSpace(),
new DialogGUIVerticalLayout(
new DialogGUIFlexibleSpace(),
new DialogGUIButton(canAfford ? "Purchase Tooling" : "Can't Afford",
() =>
{
if (canAfford)
{
Funding.Instance.AddFunds(-toolingCost, TransactionReasons.RnDPartPurchase);
PurchaseTooling();
Events["ToolingEvent"].guiActiveEditor = false;
}
}, 140.0f, 30.0f, true),
new DialogGUIButton("Close", () => { }, 140.0f, 30.0f, true)
)),
false,
HighLogic.UISkin);
}

public abstract float GetToolingCost();

public abstract void PurchaseTooling();

public abstract bool IsUnlocked();

public override void OnLoad(ConfigNode node)
{
base.OnLoad(node);

Events["ToolingEvent"].guiActiveEditor = IsUnlocked();
Events["ToolingEvent"].guiName = toolingName;
}

public virtual float GetModuleCost(float defaultCost, ModifierStagingSituation sit)
{
if (IsUnlocked())
return 0f;

float cost = part.partInfo.cost;
float baseCost = cost;

for (int i = part.Modules.Count; i-- > 0;)
{
PartModule m = part.Modules[i];
if (m is ModuleTooling)
continue;

IPartCostModifier c = m as IPartCostModifier;
if (c == null)
continue;

cost += c.GetModuleCost(baseCost, ModifierStagingSituation.CURRENT);
}

return cost;
}

public ModifierChangeWhen GetModuleCostChangeWhen()
{
return ModifierChangeWhen.FIXED;
}
}
}
205 changes: 205 additions & 0 deletions Source/Tooling/ToolingDatabase.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,205 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using KSP;
using UnityEngine;

namespace RP0
{
public struct ToolingDiameter
{
public double diameter;

public List<double> lengths;

public ToolingDiameter(double d)
{
diameter = d;
lengths = new List<double>();
}

public ToolingDiameter(double d, double l)
{
diameter = d;
lengths = new List<double>();
lengths.Add(l);
}
}
public class ToolingDatabase
{
protected static double comparisonEpsilonHigh = 1.04d;
protected static double comparisonEpsilonLow = 0.96d;

protected static int EpsilonCompare(double a, double b)
{
if (a > b * comparisonEpsilonLow && a < b * comparisonEpsilonHigh)
return 0;

return a.CompareTo(b);
}

protected static Dictionary<string, List<ToolingDiameter>> toolings = new Dictionary<string, List<ToolingDiameter>>();

protected static int DiamIndex(double diam, List<ToolingDiameter> lst, out int min)
{
min = 0;
int max = lst.Count - 1;
do
{
int mid = (min + max) / 2;
switch (EpsilonCompare(diam, lst[mid].diameter))
{
case 0:
return mid;

case 1:
min = mid + 1;
break;

default:
case -1:
max = mid - 1;
break;
}
}
while (min <= max);
return -1;
}

protected static int LengthIndex(double length, List<double> lst, out int min)
{
min = 0;
int max = lst.Count - 1;
do
{
int mid = (min + max) / 2;
switch (EpsilonCompare(length, lst[mid]))
{
case 0:
return mid;

case 1:
min = mid + 1;
break;

default:
case -1:
max = mid - 1;
break;
}
}
while (min <= max);
return -1;
}

public enum ToolingLevel
{
None = 0,
Diameter = 1,
Full = 2
};

public static ToolingLevel HasTooling(string type, double diam, double len)
{
List<ToolingDiameter> lst;
if (toolings.TryGetValue(type, out lst))
{
int tmp;
int dIndex = DiamIndex(diam, lst, out tmp);
if (dIndex == -1)
return ToolingLevel.None;

int lIndex = LengthIndex(len, lst[dIndex].lengths, out tmp);

return lIndex == -1 ? ToolingLevel.Diameter : ToolingLevel.Full;
}

return ToolingLevel.None;
}

public static bool UnlockTooling(string type, double diam, double len)
{
List<ToolingDiameter> lst;
if (toolings.TryGetValue(type, out lst))
{
int insertionIdx;
int dIndex = DiamIndex(diam, lst, out insertionIdx);
if (dIndex == -1)
{
ToolingDiameter d = new ToolingDiameter(diam, len);
lst.Insert(insertionIdx, d);
return true;
}

int lIndex = LengthIndex(len, lst[dIndex].lengths, out insertionIdx);

if (lIndex != -1)
{
return false;
}
else
{
ToolingDiameter d = lst[dIndex];
d.lengths.Insert(insertionIdx, len);
lst[dIndex] = d;
return true;
}
}
else
return false;
}


public static void Load(ConfigNode node)
{
toolings.Clear();
foreach (ConfigNode c in node.GetNodes("TYPE"))
{
string type = c.GetValue("type");
if (string.IsNullOrEmpty(type))
continue;

List<ToolingDiameter> lst = new List<ToolingDiameter>();

foreach (ConfigNode n in c.GetNodes("DIAMETER"))
{
double tmp = 0d;
if (!n.TryGetValue("diameter", ref tmp))
continue;

ToolingDiameter d = new ToolingDiameter(tmp);

ConfigNode len = n.GetNode("LENGTHS");
if (len != null)
foreach (ConfigNode.Value v in len.values)
if (double.TryParse(v.value, out tmp))
d.lengths.Add(tmp);

lst.Add(d);
}

toolings[type] = lst;
}
}

public static void Save(ConfigNode node)
{
foreach (KeyValuePair<string, List<ToolingDiameter>> kvp in toolings)
{
ConfigNode c = node.AddNode("TYPE");
c.AddValue("type", kvp.Key);

foreach (ToolingDiameter d in kvp.Value)
{
ConfigNode n = c.AddNode("DIAMETER");
n.AddValue("diameter", d.diameter.ToString("G17"));

ConfigNode len = n.AddNode("LENGTHS");
for (int i = 0, iC = d.lengths.Count; i < iC; ++i)
len.AddValue("length", d.lengths[i].ToString("G17"));
}
}
}
}
}
61 changes: 61 additions & 0 deletions Source/Tooling/ToolingScenario.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using KSP;
using UnityEngine;

namespace RP0
{
[KSPScenario(ScenarioCreationOptions.AddToAllGames, new GameScenes[] { GameScenes.EDITOR, GameScenes.SPACECENTER })]
public class ToolingManager : ScenarioModule
{
#region Fields

protected static ToolingDatabase database = new ToolingDatabase();

#region Instance

private static ToolingManager _instance = null;
public static ToolingManager Instance
{
get
{
return _instance;
}
}

#endregion

#endregion

#region Overrides and Monobehaviour methods

public override void OnAwake()
{
base.OnAwake();

if (_instance != null)
{
GameObject.Destroy(_instance);
}
_instance = this;
}

public override void OnLoad(ConfigNode node)
{
base.OnLoad(node);

ToolingDatabase.Load(node.GetNode("Tooling"));

}
public override void OnSave(ConfigNode node)
{
base.OnSave(node);

ToolingDatabase.Save(node.AddNode("Tooling"));
}

#endregion
}
}

0 comments on commit 6cfdc96

Please sign in to comment.