Advertisement
TheReadPanda

KSI-TestCode

Jun 13th, 2016
199
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 22.23 KB | None | 0 0
  1. using System;
  2. using System.Linq;
  3. using KSP.UI;
  4. using KSP.UI.Screens;
  5. using UnityEngine;
  6. using UnityEngine.UI;
  7.  
  8.  
  9.  
  10.  
  11. namespace Hire
  12. {
  13. [KSPAddon(KSPAddon.Startup.SpaceCentre, false)]
  14. class KSI_EditACPrefabs_SpaceCentre : MonoBehaviour
  15. {
  16. private void Awake() { gameObject.AddComponent<KSI_EditACPrefab>(); }
  17. }
  18.  
  19. [KSPAddon(KSPAddon.Startup.EditorAny, false)]
  20. class KSI_EditACPrefabs_Editor : KSI_EditACPrefabs_SpaceCentre { }
  21.  
  22.  
  23. class KSI_EditACPrefab : MonoBehaviour
  24. {
  25. private void Awake()
  26. {
  27. try
  28. {
  29. var prefab = GetAstronautComplexScreenPrefab();
  30.  
  31. // There isn't really any specific component we can look for to make it easier
  32. // without also making things less clear so a long transform path it is
  33. // var listAndScrollbar = prefab.transform.Find("RootCanvas/AstronautComplex anchor/GameObject/bg and aspectFitter/CrewAssignmentDialog/VL/ListAndScrollbar");
  34. var testVL = prefab.transform.Find("RootCanvas/AstronautComplex anchor/GameObject/bg and aspectFitter/CrewAssignmentDialog/VL");
  35.  
  36. if (testVL == null) throw new Exception("Couldn't find testVL Transform");
  37.  
  38. // temporarily detach Panel/scrolllist_applicants
  39. // we can't just delete it (or set it inactive apparently) or AstronautComplex will throw an exception
  40. //
  41. // we CAN, however, delete all the UI bits from it
  42. var panel = testVL.transform.Find("ListAndScrollbar");
  43. panel.SetParent(null);
  44.  
  45. panel.GetComponentsInChildren<ScrollRect>(true).ToList().ForEach(Destroy);
  46. panel.GetComponentsInChildren<Image>(true).ToList().ForEach(Destroy);
  47. panel.GetComponentsInChildren<CanvasRenderer>(true).ToList().ForEach(Destroy);
  48. panel.GetComponentsInChildren<Mask>(true).ToList().ForEach(Destroy);
  49. panel.GetComponentsInChildren<VerticalLayoutGroup>(true).ToList().ForEach(Destroy);
  50. panel.GetComponentsInChildren<ContentSizeFitter>(true).ToList().ForEach(Destroy);
  51.  
  52. // destroy all the other children
  53. foreach (Transform ch in testVL.transform)
  54. ch.gameObject.SetActive(false);
  55. // Destroy(ch.gameObject);
  56.  
  57. // reattach panel - AstronautComplex needs something inside here for something but now it won't be
  58. // rendering anything
  59. panel.SetParent(testVL);
  60.  
  61. // we won't know what the dimensions our replacement will take until the UI is actually spawned,
  62. // so we'll slip a little trojan right alongside the component (RectTransform) that will contain
  63. // that info. This helper will create the GUI
  64. testVL.gameObject.AddComponent<CustomAstronautComplexUISpawner>();
  65. }
  66. catch (Exception e)
  67. {
  68. Debug.LogError("Failed to edit Astronaut Complex: " + e);
  69. }
  70.  
  71. Destroy(gameObject); // once the spawner is attached to the prefab, this object no longer needed
  72. }
  73.  
  74.  
  75. private static UICanvasPrefab GetAstronautComplexScreenPrefab()
  76. {
  77. // the scene has just been entered and the AC shouldn't have spawned yet
  78. var spawner = FindObjectOfType<ACSceneSpawner>();
  79.  
  80. if (spawner == null)
  81. throw new Exception("Did not find AC spawner");
  82. if (spawner.ACScreenPrefab == null)
  83. throw new Exception("AC spawner prefab is null");
  84.  
  85. // this might look bizarre, but Unity seems to crash if you mess with this prefab like we're
  86. // about to do. Luckily ACScreenPrefab is public so we'll quickly make a copy and use that
  87. // as the "prefab" instead
  88. var prefab = Instantiate(spawner.ACScreenPrefab);
  89. prefab.gameObject.SetActive(false);
  90.  
  91. spawner.ACScreenPrefab = prefab;
  92.  
  93. return prefab;
  94. }
  95. }
  96.  
  97.  
  98.  
  99. // We'll have to wait until the AstronautComplex UI is actually spawned in
  100. // order to grab the dimensions of the area we'll be replacing. All the
  101. // visual bits should be handled by now so as soon as the panel is actually
  102. // visible, we can grab those dimensions and create the custom GUI using them
  103. class CustomAstronautComplexUISpawner : MonoBehaviour
  104. {
  105. private void Start()
  106. {
  107. #if DEBUG
  108. DebugDimensions();
  109. #endif
  110. var vectors = new Vector3[4];
  111. var uiCam = UIMasterController.Instance.GetComponentInChildren<UIMainCamera>();
  112.  
  113. if (uiCam == null)
  114. {
  115. Debug.LogError("UIMainCamera not found");
  116. return;
  117. }
  118.  
  119. var camera = uiCam.GetComponent<Camera>();
  120.  
  121. if (camera == null)
  122. {
  123. Debug.LogError("Camera attached to UIMainCamera not found");
  124. return;
  125. }
  126.  
  127. GetComponent<RectTransform>().GetWorldCorners(vectors);
  128.  
  129.  
  130. for (int i = 0; i < 4; ++i)
  131. vectors[i] = camera.WorldToScreenPoint(vectors[i]);
  132.  
  133.  
  134. // note: these are in screen space
  135. var rect = new Rect(vectors[1].x, Screen.height - vectors[1].y, vectors[2].x - vectors[1].x,
  136. vectors[2].y - vectors[3].y);
  137.  
  138. gameObject.AddComponent<CustomAstronautComplexUI>().Initialize(rect);
  139.  
  140. Destroy(this);
  141. }
  142.  
  143.  
  144. private void DebugDimensions()
  145. {
  146. print("Debugging dimensions");
  147.  
  148. var vectors = new Vector3[4];
  149. var camera = UIMasterController.Instance.GetComponentInChildren<UIMainCamera>().GetComponent<Camera>();
  150.  
  151. GetComponent<RectTransform>().GetWorldCorners(vectors);
  152.  
  153. foreach (var item in vectors)
  154. print("Corner: " + item);
  155.  
  156. for (int i = 0; i < 4; ++i)
  157. {
  158. vectors[i] = camera.GetComponent<Camera>().WorldToScreenPoint(vectors[i]);
  159. print("Transformed corner: " + vectors[i]);
  160. }
  161. }
  162. }
  163.  
  164.  
  165. /// <summary>
  166. /// This bit draws the GUI using the legacy GUI. You could easily use the new GUI instead if you prefer
  167. /// </summary>
  168. class CustomAstronautComplexUI : MonoBehaviour
  169. {
  170. private Rect _areaRect = new Rect(-500f, -500f, 200f, 200f);
  171. private Vector2 _guiScalar = Vector2.one;
  172. private Vector2 _guiPivot = Vector2.zero;
  173. private Vector2 _scrollbar = Vector2.zero;
  174. private readonly Texture2D _portraitMale = AssetBase.GetTexture("kerbalicon_recruit");
  175. private readonly Texture2D _portraitFemale = AssetBase.GetTexture("kerbalicon_recruit_female");
  176. private GUIStyle _backgroundStyle; // the background of the whole area our GUI will cover
  177. private GUIStyle _scrollviewStyle; // style of the whole scrollview
  178. private GUIStyle _nameStyle; // style used for kerbal names
  179. private GUIStyle _listItemEntryStyle; // style used for background of each kerbal entry
  180. private float KStupidity = 50;
  181. private float KCourage = 50;
  182. private bool KFearless = false;
  183. private int KCareer = 0;
  184. private string[] KCareerStrings = { "Pilot", "Scientist", "Engineer" };
  185. private int KLevel = 0;
  186. private string[] KLevelStringsZero = new string[1] { "Level 0" };
  187. private string[] KLevelStringsOne = new string[2] { "Level 0", "Level 1" };
  188. private string[] KLevelStringsTwo = new string[3] { "Level 0", "Level 1", "Level 2" };
  189. private string[] KLevelStringsAll = new string[6] { "Level 0", "Level 1", "Level 2", "Level 3", "Level 4", "Level 5" };
  190. private int KGender = 0;
  191. private GUIContent KMale = new GUIContent("Male", AssetBase.GetTexture("kerbalicon_recruit"));
  192. private GUIContent KFemale = new GUIContent("Female", AssetBase.GetTexture("kerbalicon_recruit_female"));
  193. Color basecolor = GUI.color;
  194. private float ACLevel = 0;
  195. private double KDead;
  196. private double DCost = 1;
  197. KerbalRoster roster = HighLogic.CurrentGame.CrewRoster;
  198. private bool hTest = true;
  199. private bool hasKredits = true;
  200.  
  201. private void Awake()
  202. {
  203. enabled = false;
  204. _backgroundStyle = new GUIStyle(HighLogic.Skin.window)
  205. {
  206. padding = new RectOffset(),
  207. border = new RectOffset()
  208. };
  209.  
  210. _scrollviewStyle = new GUIStyle(HighLogic.Skin.scrollView)
  211. {
  212. padding = new RectOffset(),
  213. border = new RectOffset()
  214. };
  215.  
  216. _nameStyle = new GUIStyle(HighLogic.Skin.label);
  217. _nameStyle.fontSize = (int)(_nameStyle.fontSize * 1.6);
  218. _nameStyle.fontStyle = FontStyle.Bold;
  219.  
  220. // set up a style that will cause the moused over entry to highlight itself. Makes the UI feel a little more
  221. // interactive
  222. _listItemEntryStyle = new GUIStyle(HighLogic.Skin.box);
  223.  
  224. var clone = Instantiate(_listItemEntryStyle.normal.background);
  225. var pixels = clone.GetPixels32();
  226.  
  227. // poor man's lighting algorithm
  228. for (int i = 0; i < pixels.Length; ++i)
  229. pixels[i] = new Color32(
  230. Math.Min((byte)255, (byte)(pixels[i].r + 25)),
  231. Math.Min((byte)255, (byte)(pixels[i].g + 25)),
  232. Math.Min((byte)255, (byte)(pixels[i].b + 25)),
  233. Math.Min((byte)255, (byte)(pixels[i].a + 25)));
  234.  
  235. clone.SetPixels32(pixels);
  236. clone.Apply();
  237.  
  238. _listItemEntryStyle.hover.background = clone;
  239. }
  240.  
  241.  
  242. public void Initialize(Rect guiRect)
  243. {
  244. var uiScaleMultiplier = GameSettings.UI_SCALE;
  245.  
  246. // the supplied rect will have the UI scalar already factored in
  247. //
  248. // to respect the player's UI scale wishes, work out what the unscaled rect
  249. // would be. Then we'll apply the scale again in OnGUI so all of our GUILayout elements
  250. // will respect the multiplier
  251. var correctedRect = new Rect(guiRect.x, guiRect.y, guiRect.width / uiScaleMultiplier,
  252. guiRect.height / uiScaleMultiplier);
  253.  
  254. _areaRect = correctedRect;
  255.  
  256. _guiPivot = new Vector2(_areaRect.x, _areaRect.y);
  257. _guiScalar = new Vector2(GameSettings.UI_SCALE, GameSettings.UI_SCALE);
  258.  
  259. enabled = true;
  260. }
  261.  
  262. private void kHire()
  263. {
  264.  
  265. ProtoCrewMember newKerb = HighLogic.CurrentGame.CrewRoster.GetNewKerbal(ProtoCrewMember.KerbalType.Crew);
  266. int loopcount = 0;
  267. ProtoCrewMember.Gender gender = (KGender == 0) ? ProtoCrewMember.Gender.Male : ProtoCrewMember.Gender.Female;
  268. string career = "";
  269. switch (KCareer)
  270. {
  271. case 0: career = "Pilot"; break;
  272. case 1: career = "Scientist"; break;
  273. case 2: career = "Engineer"; break;
  274. default: break;// throw an error?
  275. }
  276. while ((newKerb.experienceTrait.Title != career) || (newKerb.gender != gender)) // Just manually set career as selected now
  277. {
  278. HighLogic.CurrentGame.CrewRoster.Remove(newKerb);
  279. newKerb = HighLogic.CurrentGame.CrewRoster.GetNewKerbal(ProtoCrewMember.KerbalType.Crew);
  280. loopcount++;
  281. }
  282.  
  283. Debug.Log("KSI :: KIA MIA Stat is: " + KDead);
  284. Debug.Log("KSI :: " + newKerb.experienceTrait.TypeName + " " + newKerb.name + " has been created in: " + loopcount.ToString() + " loops.");
  285. newKerb.rosterStatus = ProtoCrewMember.RosterStatus.Available;
  286. newKerb.experience = 0;
  287. newKerb.experienceLevel = 0;
  288. newKerb.courage = KCourage / 100;
  289. newKerb.stupidity = KStupidity / 100;
  290. if (KFearless)
  291. {
  292. newKerb.isBadass = true;
  293. }
  294. Debug.Log("KSI :: Status set to Available, courage and stupidity set, fearless trait set.");
  295.  
  296. if (KLevel == 1)
  297. {
  298. newKerb.flightLog.AddEntry("Orbit,Kerbin");
  299. newKerb.flightLog.AddEntry("Suborbit,Kerbin");
  300. newKerb.flightLog.AddEntry("Flight,Kerbin");
  301. newKerb.flightLog.AddEntry("Land,Kerbin");
  302. newKerb.flightLog.AddEntry("Recover");
  303. newKerb.ArchiveFlightLog();
  304. newKerb.experience = 2;
  305. newKerb.experienceLevel = 1;
  306. Debug.Log("KSI :: Level set to 1.");
  307. }
  308. if (KLevel == 2)
  309. {
  310. newKerb.flightLog.AddEntry("Orbit,Kerbin");
  311. newKerb.flightLog.AddEntry("Suborbit,Kerbin");
  312. newKerb.flightLog.AddEntry("Flight,Kerbin");
  313. newKerb.flightLog.AddEntry("Land,Kerbin");
  314. newKerb.flightLog.AddEntry("Recover");
  315. newKerb.flightLog.AddEntry("Flyby,Mun");
  316. newKerb.flightLog.AddEntry("Orbit,Mun");
  317. newKerb.flightLog.AddEntry("Land,Mun");
  318. newKerb.flightLog.AddEntry("Flyby,Minmus");
  319. newKerb.flightLog.AddEntry("Orbit,Minmus");
  320. newKerb.flightLog.AddEntry("Land,Minmus");
  321. newKerb.ArchiveFlightLog();
  322. newKerb.experience = 8;
  323. newKerb.experienceLevel = 2;
  324. Debug.Log("KSI :: Level set to 2.");
  325. }
  326. if (ACLevel == 5)
  327. {
  328. newKerb.experience = 9999;
  329. newKerb.experienceLevel = 5;
  330. Debug.Log("KSI :: Level set to 5 - Non-Career Mode default.");
  331. }
  332.  
  333. Canvas.ForceUpdateCanvases();
  334. // GameEvents.onGUIAstronautComplexSpawn.Fire(); // This fails under the new UI --
  335. // Refreshes the AC so that new kerbal shows on the available roster.
  336.  
  337.  
  338. if (HighLogic.CurrentGame.Mode == Game.Modes.CAREER)
  339. {
  340. double myFunds = Funding.Instance.Funds;
  341. Funding.Instance.AddFunds(-costMath(), TransactionReasons.CrewRecruited);
  342. Debug.Log("KSI :: Total Funds removed " + costMath());
  343. }
  344. Debug.Log("KSI :: Hiring Function Completed.");
  345.  
  346. }
  347.  
  348.  
  349. private int costMath()
  350. {
  351. dCheck();
  352. float fearcost = 0;
  353. float basecost = 25000;
  354. float couragecost = (50 - KCourage) * 150;
  355. float stupidcost = (KStupidity - 50) * 150;
  356. float diffcost = HighLogic.CurrentGame.Parameters.Career.FundsLossMultiplier;
  357. if (KFearless == true)
  358. {
  359. fearcost += 10000;
  360. }
  361. DCost = 1 + (KDead * 0.1f);
  362.  
  363.  
  364. double currentcost = (basecost - couragecost - stupidcost + fearcost) * (KLevel + 1) * DCost * diffcost;
  365. // double finaldouble = (Math.Round(currentcost));
  366. int finalcost = Convert.ToInt32(currentcost); //Convert.ToInt32(finaldouble);
  367. return finalcost;
  368. }
  369.  
  370. // these slightly reduce garbage created by avoiding array allocations which is one reason OnGUI
  371. // is so terrible
  372. private static readonly GUILayoutOption[] DefaultLayoutOptions = new GUILayoutOption[0];
  373. private static readonly GUILayoutOption[] PortraitOptions = { GUILayout.ExpandWidth(false), GUILayout.ExpandHeight(false) };
  374. private static readonly GUILayoutOption[] FixedWidth = { GUILayout.Width(220f) };
  375. private static readonly GUILayoutOption[] HireButtonOptions = { GUILayout.ExpandHeight(true), GUILayout.MaxHeight(40f), GUILayout.MinWidth(40f) };
  376. private static readonly GUILayoutOption[] StatOptions = { GUILayout.MaxWidth(100f) };
  377. private static readonly GUILayoutOption[] FlavorTextOptions = { GUILayout.MaxWidth(200f) };
  378.  
  379. private string hireStatus()
  380. {
  381.  
  382. string bText = "Hire Applicant";
  383. if (HighLogic.CurrentGame.Mode == Game.Modes.CAREER)
  384. {
  385. double kredits = Funding.Instance.Funds;
  386. if (costMath() > kredits)
  387. {
  388. bText = "Not Enough Funds!";
  389. hTest = false;
  390. }
  391. if (HighLogic.CurrentGame.CrewRoster.GetActiveCrewCount() >= GameVariables.Instance.GetActiveCrewLimit(ScenarioUpgradeableFacilities.GetFacilityLevel(SpaceCenterFacility.AstronautComplex)))
  392. {
  393. bText = "Roster is Full!";
  394. hTest = false;
  395. }
  396. else
  397. {
  398. hTest = true;
  399. }
  400. }
  401. return bText;
  402. }
  403.  
  404. private void dCheck()
  405. {
  406. KDead = 0;
  407. // 10 percent for dead and 5 percent for missing, note can only have dead in some career modes.
  408. foreach (ProtoCrewMember kerbal in roster.Crew)
  409. {
  410. if (kerbal.rosterStatus.ToString() == "Dead")
  411. {
  412. if (kerbal.experienceTrait.Title == KCareerStrings[KCareer])
  413. {
  414. KDead += 1;
  415. }
  416. }
  417. if (kerbal.rosterStatus.ToString() == "Missing")
  418. {
  419. if (kerbal.experienceTrait.Title == KCareerStrings[KCareer])
  420. {
  421. KDead += 0.5;
  422. }
  423. }
  424. }
  425. }
  426.  
  427. private void OnGUI()
  428. {
  429. GUI.skin = HighLogic.Skin;
  430. var roster = HighLogic.CurrentGame.CrewRoster;
  431. GUIContent[] KGendArray = new GUIContent[2] { KMale, KFemale };
  432. if (HighLogic.CurrentGame.Mode == Game.Modes.SANDBOX)
  433. {
  434. hasKredits = false;
  435. ACLevel = 5;
  436. }
  437. if (HighLogic.CurrentGame.Mode == Game.Modes.SCIENCE_SANDBOX)
  438. {
  439. hasKredits = false;
  440. ACLevel = 1;
  441. }
  442. if (HighLogic.CurrentGame.Mode == Game.Modes.CAREER)
  443. {
  444. hasKredits = true;
  445. ACLevel = ScenarioUpgradeableFacilities.GetFacilityLevel(SpaceCenterFacility.AstronautComplex);
  446. }
  447.  
  448. GUILayout.BeginArea(_areaRect);
  449. {
  450. GUILayout.Label("Kerbal Science Institute: Placement Services"); // Testing Renaming Label Works
  451.  
  452. // Gender selection
  453. GUILayout.BeginHorizontal("box");
  454. KGender = GUILayout.Toolbar(KGender, KGendArray);
  455. GUILayout.EndHorizontal();
  456.  
  457. // Career selection
  458. GUILayout.BeginVertical("box");
  459. KCareer = GUILayout.Toolbar(KCareer, KCareerStrings);
  460. GUILayout.Label("Pilots can use SAS and ships at vector markers.");
  461. GUILayout.Label("Scientists can reset experiements and science gains.");
  462. GUILayout.Label("Engineers help drills, repack chutes and fix some items.");
  463. GUILayout.Label("Note: Some mods give additional effects to some careers.");
  464. GUI.contentColor = basecolor;
  465. GUILayout.EndVertical();
  466.  
  467. // Courage Brains and BadS flag selections
  468. GUILayout.BeginVertical("box");
  469. GUILayout.Label("Courage: " + Math.Truncate(KCourage));
  470. KCourage = GUILayout.HorizontalSlider(KCourage, 0, 100);
  471. GUILayout.Label("Stupidity: " + Math.Truncate(KStupidity));
  472. KStupidity = GUILayout.HorizontalSlider(KStupidity, 0, 100);
  473. GUILayout.BeginHorizontal();
  474. GUILayout.Label("Is this Kerbal Fearless?");
  475. KFearless = GUILayout.Toggle(KFearless, "Fearless");
  476. GUILayout.EndHorizontal();
  477. GUILayout.EndVertical();
  478.  
  479. // Level selection
  480. GUILayout.BeginVertical("box");
  481. GUILayout.Label("Select Your Level:");
  482.  
  483. // If statements for level options
  484. if (ACLevel == 0) { KLevel = GUILayout.Toolbar(KLevel, KLevelStringsZero); }
  485. if (ACLevel == 0.5) { KLevel = GUILayout.Toolbar(KLevel, KLevelStringsOne); }
  486. if (ACLevel == 1) { KLevel = GUILayout.Toolbar(KLevel, KLevelStringsTwo); }
  487. if (ACLevel == 5) { GUILayout.Label("Level 5 - Manditory for Sandbox or Science Mode."); }
  488. GUILayout.EndVertical();
  489.  
  490. if (hasKredits == true)
  491. {
  492. GUILayout.BeginHorizontal("window");
  493. GUILayout.BeginVertical();
  494. GUILayout.FlexibleSpace();
  495.  
  496. if (costMath() <= Funding.Instance.Funds)
  497. {
  498. GUILayout.Label("Cost: " + costMath(), HighLogic.Skin.textField);
  499. }
  500. else
  501. {
  502. GUI.color = Color.red;
  503. GUILayout.Label("Insufficient Funds - Cost: " + costMath(), HighLogic.Skin.textField);
  504. GUI.color = basecolor;
  505. }
  506. GUILayout.FlexibleSpace();
  507. GUILayout.EndVertical();
  508. GUILayout.EndHorizontal();
  509. }
  510.  
  511. GUILayout.BeginHorizontal();
  512. GUILayout.FlexibleSpace();
  513.  
  514. if (hTest)
  515. {
  516. if (GUILayout.Button(hireStatus(), GUILayout.Width(200f)))
  517. kHire();
  518. }
  519. if (!hTest)
  520. {
  521. GUILayout.Button(hireStatus(), GUILayout.Width(200f));
  522. }
  523.  
  524. GUILayout.FlexibleSpace();
  525. GUILayout.EndHorizontal();
  526.  
  527. GUILayout.EndArea();
  528. }
  529. }
  530.  
  531. }
  532.  
  533. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement