Guest User

KSP ICE Source Dump

a guest
Feb 8th, 2015
562
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 165.97 KB | None | 0 0
  1. //ID-ICE InfiniteDice Internal Combustion Engine - Module for KSP Updated for KSP v 0.90.
  2. //Mod, code, models, textures are shared under
  3. //Attribution-NonCommercial-NoDerivatives 4.0 International (CC BY-NC-ND 4.0) - You are free to:Share — copy and redistribute the material in any medium or format - You can modify files for your personal use.
  4. //If you remix, transform, or build upon the material, you may not distribute the modified material. You may not use the material for commercial purposes.
  5.  
  6. //A note on the license - I have dozens of hours in this and other mods, which I share out to the community for no fees. Id you like the mod please share your thoughts/images/videos on the KSP forum thread!
  7. //Thanks for using this mod.
  8.  
  9. //ID ICE is not perfect! I don't claim this is a totally realistic simulation of how a real engine works. My overall goal was to experiment with making an alternative engine module for KSP.
  10. //Secondly to support and inspire the community to take more advantage of EVA activities. Have fun!
  11.  
  12.  
  13. class IDwheel : PartModule
  14. {
  15. #region variables
  16. [KSPField]
  17. public string wheelColliderName = "wheelCollider";
  18. [KSPField]
  19. public string boundsCollider = "Bounds";
  20. [KSPField]
  21. public string wheelMeshName = "Wheel";
  22. [KSPField]
  23. public string suspensionParentName = "suspensionParent";
  24. [KSPField]
  25. public int numberOfWheels = 1;
  26.  
  27. [KSPField]
  28. public string sfxBurnoutLoop = "IDiCEr1/Sounds/burnout";
  29.  
  30. public FXGroup soundLoop = null;
  31.  
  32. public GameObject fxBoInstance;
  33.  
  34. [KSPField]
  35. public string altWheelLocP = "adjSusParLoc";
  36.  
  37. public Transform alterWheelCPos = null;
  38.  
  39. public bool useAltWLoc = false;
  40.  
  41. [KSPField]
  42. public bool disableColliderWhenRetracted = false;
  43.  
  44. [KSPField]
  45. public bool usesIDdDrive = false;
  46.  
  47. [KSPField]
  48. public float wheelRadius = 0.25f;
  49.  
  50. [KSPField]
  51. public float wheelWidth = 0.125f;
  52.  
  53. public IDice getICEOutput;
  54. public IDdDrive getICEdDrive;
  55. public bool firstRun = true;
  56.  
  57.  
  58.  
  59. [KSPField]
  60. public float origDrag = 2.2f;
  61.  
  62. [KSPField(isPersistant = true)]
  63. public bool tireFlat = false;
  64.  
  65. [KSPField(isPersistant = true)]
  66. public bool isDestroyed = false;
  67.  
  68. [KSPField(isPersistant = true, guiActiveEditor = true, guiActive = false, guiName = "GearDrag Multi"), UI_FloatRange(minValue = 100f, maxValue = 300f, stepIncrement = 50f)]
  69. public float gearDragMulti = 150f;
  70.  
  71. [KSPField]
  72. public string animationName = "Retract";
  73. [KSPField]
  74. public int animationLayer = 1;
  75. [KSPField]
  76. public float deploymentCooldown = 0.5f;
  77.  
  78. [KSPField(isPersistant = true)]
  79. public string deploymentState = "Deployed";
  80.  
  81. [KSPField(isPersistant = true, guiActiveEditor = true, guiActive = false, guiName = "Brake Torque"), UI_FloatRange(minValue = 0f, maxValue = 40f, stepIncrement = 2.5f)]
  82. public float brakeTorque = 5f;
  83.  
  84. [KSPField(isPersistant = true, guiActiveEditor = true, guiActive = true, guiName = "Spring Rate"), UI_FloatRange(minValue = 0.1f, maxValue = 1.8f, stepIncrement = 0.1f)]
  85. public float suspSpring = 0.2f;
  86.  
  87. [KSPField(isPersistant = true, guiActiveEditor = true, guiActive = true, guiName = "Damp Rate"), UI_FloatRange(minValue = 0.1f, maxValue = 1.8f, stepIncrement = 0.1f)]
  88. public float suspDamp = 0.1f;
  89.  
  90. [KSPField(isPersistant = true, guiActiveEditor = true, guiActive = true, guiName = "Rest Height"), UI_FloatRange(minValue = 0.05f, maxValue = 0.5f, stepIncrement = 0.05f)]
  91. public float suspRHeight = 0.25f;
  92.  
  93. [KSPField]
  94. public float brakeSpeed = 0.75f;
  95. [KSPField(isPersistant = true)]
  96. public bool brakesEngaged = false;
  97.  
  98. public float velocitySlipMod = 1f;
  99. public float alterSlipMod = 2.5f;
  100.  
  101. [KSPField]
  102. public float hubDrag = 1.5f;
  103.  
  104. [KSPField(isPersistant = true)]
  105. public bool hubDamage = false;
  106.  
  107. public float sideSlipMod, forwardSlipMod;
  108. public KSPParticleEmitter[] findKspEmitter;
  109.  
  110. [KSPField(isPersistant = true)]
  111. public float origSFriction;
  112.  
  113. [KSPField(isPersistant = true)]
  114. public float origFFriction;
  115.  
  116. public AnimationCurve vSlipCurve;
  117.  
  118. public AnimationCurve aMSlipCurve;
  119.  
  120.  
  121. public float cornerLoad = 0f;
  122. public float origCLoad = 0f;
  123. public bool setOnce = true;
  124. public float lastSlipMod = 0f;
  125. public float percentGripMod = 1f;
  126.  
  127. [KSPField]
  128. public bool hasMotor = true;
  129. [KSPField(isPersistant = true, guiActiveEditor = true, guiActive = true, guiName = "Motor Enabled"), UI_Toggle(controlEnabled = false, disabledText = "No", enabledText = "Yes")]
  130. public bool motorEnabled = false;
  131. [KSPField]
  132. public float motorTorque = 80f;
  133. [KSPField]
  134. public float maxSpeed = 30f;
  135. [KSPField]
  136. public string resourceName = "ElectricCharge";
  137. [KSPField]
  138. public float resourceConsumptionRate = 0.2f;
  139. [KSPField(isPersistant = true, guiActiveEditor = false, guiActive = true, guiName = "Motor Reversed"), UI_Toggle(controlEnabled = false, disabledText = "No", enabledText = "Yes")]
  140. public bool reverseMotor = false;
  141. [KSPField(isPersistant = true)]
  142. public bool reverseMotorSet = false;
  143. [KSPField(isPersistant = true)]
  144. public bool motorStartsReversed = false;
  145.  
  146. #region wheel collider settings
  147. [KSPField]
  148. public bool overrideModelFrictionValues = false;
  149. [KSPField]
  150. public float forwardsStiffness = 10.0f;
  151. [KSPField]
  152. public float forwardsExtremumSlip = 1.0f;
  153. [KSPField]
  154. public float forwardsExtremumValue = 20000.0f;
  155. [KSPField]
  156. public float forwardsAsymptoteSlip = 2.0f;
  157. [KSPField]
  158. public float forwardsAsymptoteValue = 10000.0f;
  159. [KSPField]
  160. public float sidewaysStiffness = 1.0f;
  161. [KSPField]
  162. public float sidewaysExtremumSlip = 1.0f;
  163. [KSPField]
  164. public float sidewaysExtremumValue = 20000.0f;
  165. [KSPField]
  166. public float sidewaysAsymptoteSlip = 2.0f;
  167. [KSPField]
  168. public float sidewaysAsymptoteValue = 10000.0f;
  169. [KSPField]
  170. public float wheelColliderMass = -1f;
  171. [KSPField]
  172. public float wheelColliderRadius = -1f;
  173. [KSPField]
  174. public float wheelColliderSuspensionDistance = -1f;
  175. [KSPField]
  176. public float suspensionSpring = -1f;
  177. [KSPField]
  178. public float suspensionDamper = -1f;
  179. [KSPField]
  180. public float suspensionTargetPosition = -1f;
  181. #endregion
  182.  
  183. [KSPField]
  184. public float rotationAdjustment = 1f;
  185.  
  186. [KSPField]
  187. public float deployedDrag = 0f;
  188. [KSPField]
  189. public float retractedDrag = 0f;
  190.  
  191. [KSPField]
  192. public bool guiActiveUnfocused = true;
  193. [KSPField]
  194. public float unfocusedRange = 5f;
  195.  
  196. public bool bWasDown = false;
  197.  
  198. public float animTime = 0f;
  199. public float animSpeed = 0f;
  200. public float rotation = 0f;
  201.  
  202. public bool fixOngoing = false;
  203. public float doneTime = 0f;
  204. public bool canFixFlat = true;
  205.  
  206. private Animation anim;
  207. private WheelList wheelList = new WheelList();
  208. public int gWheelNum;
  209. private bool boundsColliderRemoved = false;
  210.  
  211. [KSPField]
  212. public bool debugMode = false;
  213. #endregion
  214.  
  215. #region Actions and Events
  216.  
  217. [KSPAction("Raise Lower Gear", KSPActionGroup.Gear)]
  218. public void ToggleGearAction(KSPActionParam param)
  219. {
  220. if (param.type == KSPActionType.Activate)
  221. {
  222. LowerGear();
  223. }
  224. else
  225. {
  226. RaiseGear();
  227. }
  228. param.Cooldown = deploymentCooldown;
  229. }
  230.  
  231. [KSPEvent(guiName = "Raise Gear", guiActive = true, guiActiveUnfocused = true, unfocusedRange = 5f)]
  232. public void RaiseGear()
  233. {
  234. animate("Retract");
  235. }
  236.  
  237. [KSPEvent(guiName = "Lower Gear", guiActive = true, guiActiveUnfocused = true, unfocusedRange = 5f)]
  238. public void LowerGear()
  239. {
  240. animate("Deploy");
  241. }
  242.  
  243. [KSPAction("Reverse Motor")]
  244. public void ReverseMotorAction(KSPActionParam param)
  245. {
  246. ReverseMotorEvent();
  247. }
  248.  
  249. [KSPEvent(guiName = "Toggle Reverse Motor", guiActive = true)]
  250. public void ReverseMotorEvent()
  251. {
  252. bool changeOnce = true;
  253.  
  254. if (reverseMotor == true && changeOnce == true)
  255. {
  256. reverseMotor = false;
  257. changeOnce = false;
  258. }
  259. else if (reverseMotor == false && changeOnce == true)
  260. {
  261. reverseMotor = true;
  262. changeOnce = false;
  263. }
  264. }
  265.  
  266. [KSPAction("Toggle Motor")]
  267. public void ToggleMotorAction(KSPActionParam param)
  268. {
  269. if (param.type == KSPActionType.Activate)
  270. {
  271. EnableMotorEvent();
  272. }
  273. else
  274. {
  275. DisableMotorEvent();
  276. }
  277. }
  278.  
  279. [KSPEvent(active = true, guiName = "Fix Flat", guiActiveUnfocused = true, externalToEVAOnly = true, guiActive = false, unfocusedRange = 5f)]
  280. public void fixTire()
  281. {
  282. if (fixOngoing == false && tireFlat == true && canFixFlat == true)
  283. {
  284. float fixTime = 10f;
  285. float startTime = Time.time;
  286.  
  287. ScreenMessages.PostScreenMessage(new ScreenMessage("Fixing the flat tire...", fixTime, ScreenMessageStyle.UPPER_CENTER));
  288. fixOngoing = true;
  289. doneTime = fixTime + startTime;
  290. Events["fixTire"].active = false;
  291. }
  292. if (canFixFlat == false)
  293. {
  294. ScreenMessages.PostScreenMessage(new ScreenMessage("Wheel too badly damaged to fix flat, repair vessel first!", 3f, ScreenMessageStyle.UPPER_CENTER));
  295. }
  296.  
  297. }
  298.  
  299. [KSPEvent(guiName = "Enable Motor", guiActive = false)]
  300. public void EnableMotorEvent()
  301. {
  302. motorEnabled = true;
  303. Events["EnableMotorEvent"].guiActive = false;
  304. Events["DisableMotorEvent"].guiActive = false;
  305. }
  306.  
  307. [KSPEvent(guiName = "Disable Motor", guiActive = false)]
  308. public void DisableMotorEvent()
  309. {
  310. motorEnabled = false;
  311. Events["EnableMotorEvent"].guiActive = false;
  312. Events["DisableMotorEvent"].guiActive = false;
  313. }
  314.  
  315. private void animate(string mode)
  316. {
  317. if (anim != null)
  318. {
  319. animTime = anim[animationName].normalizedTime;
  320.  
  321. if (deploymentState == "Retracted")
  322. animTime = 1f;
  323.  
  324. if (mode == "Deploy")
  325. {
  326. if (deploymentState == "Retracted")
  327. animTime = 1f;
  328. animSpeed = -1f;
  329. deploymentState = "Deploying";
  330. }
  331. else if (mode == "Retract")
  332. {
  333. if (deploymentState == "Deployed")
  334. animTime = 0f;
  335. animSpeed = 1f;
  336. deploymentState = "Retracting";
  337. }
  338. else if (mode == "Stop")
  339. {
  340. animSpeed = 0f;
  341. deploymentState = "Stopped";
  342. }
  343.  
  344. anim[animationName].normalizedTime = animTime;
  345. anim[animationName].speed = animSpeed;
  346. if (animSpeed != 0f)
  347. {
  348.  
  349. anim.Play(animationName);
  350. }
  351. else
  352. {
  353. anim.Stop();
  354. }
  355. }
  356. }
  357.  
  358. [KSPAction("Brakes", KSPActionGroup.Brakes)]
  359. public void BrakesAction(KSPActionParam param)
  360. {
  361. if (param.type == KSPActionType.Activate)
  362. {
  363. brakesEngaged = true;
  364. }
  365. else
  366. {
  367. brakesEngaged = false;
  368. }
  369. }
  370.  
  371. [KSPEvent(name = "brakesOn", guiActive = true, active = true, guiName = "Brakes On", externalToEVAOnly = true, unfocusedRange = 6f, guiActiveUnfocused = true)]
  372. public void brakesOnEvent()
  373. {
  374. brakesEngaged = true;
  375. Events["brakesOnEvent"].guiActive = false;
  376. Events["brakesOffEvent"].guiActive = true;
  377. }
  378.  
  379. [KSPEvent(name = "brakesOff", guiActive = true, active = true, guiName = "Brakes Off", externalToEVAOnly = true, unfocusedRange = 6f, guiActiveUnfocused = true)]
  380. public void brakesOffEvent()
  381. {
  382. brakesEngaged = false;
  383. Events["brakesOnEvent"].guiActive = true;
  384. Events["brakesOffEvent"].guiActive = false;
  385. }
  386.  
  387.  
  388. #endregion
  389.  
  390.  
  391.  
  392. public override void OnStart(PartModule.StartState state)
  393. {
  394. base.OnStart(state);
  395. #region In flight
  396. if (HighLogic.LoadedSceneIsFlight)
  397. {
  398.  
  399. #region SoundFX
  400.  
  401. soundLoop.audio = gameObject.AddComponent<AudioSource>();
  402.  
  403. if (soundLoop.audio != null)
  404. {
  405.  
  406. soundLoop.audio.volume = GameSettings.SHIP_VOLUME;
  407. soundLoop.audio.rolloffMode = AudioRolloffMode.Linear;
  408. soundLoop.audio.dopplerLevel = 0f;
  409. soundLoop.audio.panLevel = 1f;
  410.  
  411. soundLoop.audio.clip = GameDatabase.Instance.GetAudioClip(sfxBurnoutLoop);
  412. soundLoop.audio.loop = true;
  413. soundLoop.audio.playOnAwake = false;
  414. soundLoop.audio.priority = 1;
  415. }
  416.  
  417. #endregion
  418.  
  419. #region FX
  420.  
  421. try
  422. {
  423.  
  424. fxBoInstance = GameDatabase.Instance.GetModel("IDiCEr1/Effects/BurnoutFX/model");
  425. }
  426. catch
  427. {
  428. print("Problem locating BurnoutFX");
  429. }
  430.  
  431. if (fxBoInstance != null)
  432. {
  433. fxBoInstance.SetActive(false);
  434. fxBoInstance.transform.parent = this.part.transform;
  435. fxBoInstance.transform.position = this.part.transform.position;
  436.  
  437. }
  438.  
  439. #endregion
  440.  
  441. #region create wheel setup
  442. List<WheelCollider> colliderList = new List<WheelCollider>();
  443. List<Transform> wheelMeshList = new List<Transform>();
  444. List<Transform> suspensionList = new List<Transform>();
  445.  
  446. for (int i = 0; i < numberOfWheels; i++)
  447. {
  448. string suffix = (i + 1).ToString();
  449. if (i == 0)
  450. suffix = "";
  451. Transform colliderTransform = part.FindModelTransform(wheelColliderName + suffix);
  452. if (colliderTransform != null)
  453. {
  454. WheelCollider collider = colliderTransform.GetComponent<WheelCollider>();
  455. if (collider != null)
  456. {
  457. colliderList.Add(collider);
  458.  
  459. Transform wheelMeshTransform = part.FindModelTransform(wheelMeshName + suffix);
  460. if (wheelMeshTransform != null)
  461. {
  462. wheelMeshList.Add(wheelMeshTransform);
  463. }
  464. else
  465. {
  466. Debug.Log("FSwheel: missing wheel mesh " + wheelMeshName + suffix);
  467. }
  468. Transform suspensionTransform = part.FindModelTransform(suspensionParentName + suffix);
  469. if (suspensionTransform != null)
  470. {
  471. suspensionList.Add(suspensionTransform);
  472. }
  473. else
  474. {
  475. Debug.Log("FSwheel: missing suspensionParent " + suspensionParentName + suffix);
  476. }
  477.  
  478.  
  479. }
  480. }
  481. else
  482. {
  483. Debug.Log("FSwheel: missing wheel collider " + wheelColliderName + suffix);
  484. }
  485. }
  486.  
  487. wheelList.Create(colliderList, wheelMeshList, suspensionList);
  488. if (wheelList != null)
  489. {
  490. if (!wheelList.enabled)
  491. {
  492. wheelList.enabled = true;
  493. }
  494. }
  495.  
  496.  
  497. if (wheelList.wheels.Count > 0)
  498. {
  499.  
  500. if (!reverseMotorSet)
  501. {
  502. float dot = Vector3.Dot(wheelList.wheels[0].wheelCollider.transform.forward, vessel.ReferenceTransform.up);
  503. if (dot < 0)
  504. {
  505. reverseMotor = true;
  506.  
  507. }
  508. else
  509. {
  510. reverseMotor = false;
  511.  
  512. }
  513. if (motorStartsReversed)
  514. reverseMotor = !reverseMotor;
  515. reverseMotorSet = true;
  516. }
  517. }
  518.  
  519.  
  520. if (disableColliderWhenRetracted)
  521. {
  522. if (deploymentState == "Retracted")
  523. {
  524. wheelList.enabled = false;
  525. }
  526. }
  527.  
  528.  
  529. if (overrideModelFrictionValues)
  530. {
  531. wheelList.forwardStiffness = forwardsStiffness;
  532. wheelList.forwardsAsymptoteSlip = forwardsAsymptoteSlip;
  533. wheelList.forwardsAsymptoteValue = forwardsAsymptoteValue;
  534. wheelList.forwardsExtremumSlip = forwardsExtremumSlip;
  535. wheelList.forwardsExtremumValue = forwardsExtremumValue;
  536. wheelList.sidewaysStiffness = sidewaysStiffness;
  537. wheelList.forwardsAsymptoteSlip = sidewaysAsymptoteSlip;
  538. wheelList.sidewaysAsymptoteValue = sidewaysAsymptoteValue;
  539. wheelList.sidewaysExtremumSlip = sidewaysExtremumSlip;
  540. wheelList.sidewaysExtremumValue = sidewaysExtremumValue;
  541. wheelList.updateWheelFriction();
  542. }
  543.  
  544.  
  545. if (suspensionSpring >= 0f && suspensionDamper >= 0f && suspensionTargetPosition >= 0f)
  546. {
  547. wheelList.updateSpring(suspensionSpring, suspensionDamper, suspensionTargetPosition);
  548. }
  549. if (wheelColliderRadius >= 0f) wheelList.radius = wheelColliderRadius;
  550. if (wheelColliderMass >= 0f) wheelList.mass = wheelColliderMass;
  551. if (wheelColliderSuspensionDistance >= 0f) wheelList.suspensionDistance = wheelColliderSuspensionDistance;
  552.  
  553. #endregion
  554.  
  555. #region animation
  556.  
  557. anim = part.FindModelAnimators(animationName).FirstOrDefault();
  558. if (anim != null)
  559. {
  560. anim[animationName].layer = animationLayer;
  561. float startAnimTime = 0f;
  562. if (deploymentState == "Retracted")
  563. {
  564. startAnimTime = 1f;
  565. animSpeed = 1f;
  566. }
  567. else
  568. {
  569. animSpeed = -1f;
  570. }
  571. anim[animationName].normalizedTime = startAnimTime;
  572. anim[animationName].speed = animSpeed;
  573. anim.Play(animationName);
  574. }
  575. #endregion
  576.  
  577.  
  578.  
  579.  
  580. #region GUI element changes
  581. Events["RaiseGear"].guiActiveUnfocused = guiActiveUnfocused;
  582. Events["RaiseGear"].unfocusedRange = unfocusedRange;
  583. Events["LowerGear"].guiActiveUnfocused = guiActiveUnfocused;
  584. Events["LowerGear"].unfocusedRange = unfocusedRange;
  585. Events["EnableMotorEvent"].guiActive = !motorEnabled;
  586. Events["DisableMotorEvent"].guiActive = motorEnabled;
  587. Events["brakesOnEvent"].guiActive = !brakesEngaged;
  588. Events["brakesOffEvent"].guiActive = brakesEngaged;
  589. Events["brakesOnEvent"].guiActiveUnfocused = guiActiveUnfocused;
  590. Events["brakesOffEvent"].guiActiveUnfocused = guiActiveUnfocused;
  591.  
  592. if (debugMode)
  593. {
  594. Events["increaseFrictionEvent"].guiActive = true;
  595. Events["decreaseFrictionEvent"].guiActive = true;
  596. Events["suspensionGUIEvent"].guiActive = true;
  597. }
  598. #endregion
  599. }
  600. #endregion
  601.  
  602. if (!usesIDdDrive)
  603. {
  604. Fields["gearDragMulti"].guiActiveEditor = false;
  605. Fields["gearDragMulti"].guiActive = false;
  606. }
  607.  
  608.  
  609. }
  610.  
  611. public void Update()
  612. {
  613.  
  614. if (!HighLogic.LoadedSceneIsFlight) return;
  615.  
  616. if (this.vessel == FlightGlobals.ActiveVessel && usesIDdDrive)
  617. {
  618. if (Input.GetKey(KeyCode.S) && brakesEngaged == false)
  619. {
  620. brakesEngaged = true;
  621. bWasDown = true;
  622. }
  623. if (!Input.GetKey(KeyCode.S) && brakesEngaged == true && bWasDown == true)
  624. {
  625. brakesEngaged = false;
  626. bWasDown = false;
  627. }
  628.  
  629. }
  630.  
  631. }
  632.  
  633. public void FixedUpdate()
  634. {
  635. if (!HighLogic.LoadedSceneIsFlight)
  636. return;
  637.  
  638. if (firstRun == true)
  639. {
  640. getICEdDrive = this.vessel.FindPartModulesImplementing<IDdDrive>().FirstOrDefault();
  641. getICEOutput = this.vessel.FindPartModulesImplementing<IDice>().FirstOrDefault();
  642.  
  643. Transform[] affectDmgState = this.part.FindModelTransforms("runFlat");
  644.  
  645.  
  646.  
  647. findKspEmitter = fxBoInstance.GetComponentsInChildren<KSPParticleEmitter>();
  648.  
  649. if (affectDmgState != null && tireFlat == false)
  650. {
  651. foreach (Transform tD in affectDmgState)
  652. {
  653. tD.GetComponent<MeshRenderer>().enabled = false;
  654. }
  655. }
  656. else
  657. {
  658. foreach (Transform tD in affectDmgState)
  659. {
  660. tD.GetComponent<MeshRenderer>().enabled = true;
  661. }
  662. }
  663.  
  664. origDrag = this.part.rigidbody.drag;
  665.  
  666. firstRun = false;
  667. for (int i = 0; i < wheelList.wheels.Count; i++)
  668. {
  669. origSFriction = wheelList.wheels[i].wheelCollider.sidewaysFriction.stiffness;
  670. origFFriction = wheelList.wheels[i].wheelCollider.forwardFriction.stiffness;
  671. }
  672.  
  673. }
  674.  
  675. if (fixOngoing == true && Time.time >= doneTime && tireFlat == true)
  676. {
  677. doneTime = 0f;
  678. fixOngoing = false;
  679. tireFlat = false;
  680.  
  681. Transform[] affectDmgState = this.part.FindModelTransforms("runFlat");
  682.  
  683. for (int i = 0; i < wheelList.wheels.Count; i++)
  684. {
  685.  
  686. if (affectDmgState != null)
  687. {
  688. foreach (Transform tD in affectDmgState)
  689. {
  690. tD.GetComponent<MeshRenderer>().enabled = false;
  691. }
  692.  
  693. }
  694.  
  695. wheelList.wheels[i].wheelCollider.radius = wheelRadius;
  696.  
  697.  
  698. }
  699.  
  700. }
  701.  
  702. #region destroy bounds collider
  703. if (!boundsColliderRemoved)
  704. {
  705. if (boundsCollider != string.Empty)
  706. {
  707. Transform boundsTransform = part.FindModelTransform(boundsCollider);
  708. if (boundsTransform != null)
  709. {
  710. GameObject.Destroy(boundsTransform.gameObject);
  711. }
  712. }
  713. boundsColliderRemoved = true;
  714. }
  715. #endregion
  716.  
  717. #region update deployment state
  718. if (anim != null)
  719. {
  720. if (!anim.isPlaying)
  721. {
  722. if (deploymentState == "Deploying")
  723. deploymentState = "Deployed";
  724. else if (deploymentState == "Retracting")
  725. deploymentState = "Retracted";
  726. }
  727. }
  728. #endregion
  729.  
  730. #region update brake torque
  731. if (brakesEngaged)
  732. {
  733. if (hubDamage == true)
  734. {
  735. wheelList.brakeTorque = Mathf.Lerp(wheelList.brakeTorque, (brakeTorque * hubDrag), TimeWarp.deltaTime * brakeSpeed);
  736. }
  737. else
  738. {
  739. wheelList.brakeTorque = Mathf.Lerp(wheelList.brakeTorque, brakeTorque, TimeWarp.deltaTime * brakeSpeed);
  740. }
  741. }
  742. else
  743. {
  744. if (hubDamage == true)
  745. {
  746. wheelList.brakeTorque = wheelList.mass * hubDrag;
  747. }
  748. else
  749. {
  750. wheelList.brakeTorque = 0f;
  751. }
  752. }
  753. #endregion
  754.  
  755. #region update spring power
  756.  
  757. wheelList.updateSpring(suspSpring, suspDamp, suspRHeight);
  758.  
  759. #endregion
  760.  
  761. #region rotate wheel meshes
  762. for (int i = 0; i < wheelList.wheels.Count; i++)
  763. {
  764.  
  765. if (wheelList.wheels[i].useRotation)
  766. {
  767. if (this.usesIDdDrive && this.motorEnabled && !getICEdDrive.inNeutral && wheelList.motorTorque != 0f)
  768. {
  769. rotation = getICEdDrive.rpmOutput * rotationAdjustment * Time.deltaTime;
  770.  
  771. }
  772. else if (!this.usesIDdDrive || !this.motorEnabled || getICEdDrive.inNeutral || wheelList.motorTorque == 0f)
  773. {
  774. if (wheelList.wheels[i].wheelCollider.isGrounded)
  775. {
  776. rotation = wheelList.wheels[i].wheelCollider.rpm * rotationAdjustment * Time.deltaTime;
  777. if (reverseMotor)
  778. {
  779. rotation *= -1f;
  780. }
  781. }
  782. else
  783. {
  784. rotation = Mathf.SmoothStep(500f, 0.0f, 180f);
  785. }
  786. }
  787.  
  788. if (!this.reverseMotor)
  789. {
  790. wheelList.wheels[i].wheelMesh.Rotate(new Vector3(0f, 0f, rotation));
  791. }
  792. else
  793. {
  794. wheelList.wheels[i].wheelMesh.Rotate(new Vector3(0f, 0f, -rotation));
  795. }
  796.  
  797.  
  798.  
  799. }
  800. }
  801. #endregion
  802.  
  803.  
  804.  
  805. #region update suspension
  806.  
  807. for (int i = 0; i < wheelList.wheels.Count; i++)
  808. {
  809.  
  810. if (wheelList.wheels[i].useSuspension)
  811. {
  812.  
  813. RaycastHit raycastHit;
  814. WheelCollider wheelCollider = wheelList.wheels[i].wheelCollider;
  815. Transform suspensionParent = wheelList.wheels[i].suspensionParent;
  816.  
  817. alterWheelCPos = part.FindModelTransform(altWheelLocP);
  818. if (alterWheelCPos != null)
  819. {
  820. useAltWLoc = true;
  821. }
  822.  
  823. if (useAltWLoc == false || alterWheelCPos == null)
  824. {
  825. if (Physics.Raycast(wheelCollider.transform.position, -wheelCollider.transform.up, out raycastHit, wheelCollider.suspensionDistance + wheelCollider.radius))
  826. {
  827. suspensionParent.position = raycastHit.point + wheelCollider.transform.up * wheelCollider.radius;
  828. cornerLoad = raycastHit.distance;
  829.  
  830. }
  831. else
  832. {
  833. suspensionParent.position = wheelCollider.transform.position - wheelCollider.transform.up * wheelCollider.suspensionDistance;
  834. cornerLoad = wheelCollider.suspensionDistance;
  835. }
  836. }
  837. if(useAltWLoc == true)
  838. {
  839.  
  840. if (Physics.Raycast(alterWheelCPos.position, -alterWheelCPos.up, out raycastHit, wheelCollider.suspensionDistance + wheelCollider.radius))
  841. {
  842. suspensionParent.position = raycastHit.point + alterWheelCPos.up * wheelCollider.radius;
  843. cornerLoad = raycastHit.distance;
  844.  
  845. }
  846. else
  847. {
  848. suspensionParent.position = alterWheelCPos.position - alterWheelCPos.up * wheelCollider.suspensionDistance;
  849. cornerLoad = wheelCollider.suspensionDistance;
  850. }
  851. }
  852.  
  853. }
  854.  
  855. }
  856. #endregion
  857.  
  858. #region Active vessel code
  859.  
  860. if (vessel.isActiveVessel && base.vessel.IsControllable)
  861. {
  862. #region collider disabling
  863. if (disableColliderWhenRetracted)
  864. {
  865. if (deploymentState == "Retracted")
  866. {
  867. wheelList.enabled = false;
  868. }
  869. else
  870. {
  871. wheelList.enabled = true;
  872. }
  873. }
  874. #endregion
  875.  
  876. #region update motors
  877.  
  878. if (hasMotor && motorEnabled && deploymentState == "Deployed" && !usesIDdDrive)
  879. {
  880. float speedModifier = Mathf.Max(0f, -(((float)vessel.horizontalSrfSpeed - maxSpeed) / maxSpeed));
  881. float throttleInput = vessel.ctrlState.wheelThrottle * speedModifier;
  882. if (reverseMotor == true)
  883. throttleInput *= -1;
  884. double resourceConsumed = (double)Mathf.Abs(resourceConsumptionRate * throttleInput) * (double)TimeWarp.deltaTime;
  885. if (!CheatOptions.InfiniteFuel)
  886. {
  887. double receivedResource = base.part.RequestResource(resourceName, resourceConsumed);
  888. if (resourceConsumed > 0f)
  889. {
  890. double resouceReceivedNormalized = receivedResource / resourceConsumed;
  891.  
  892. throttleInput *= Mathf.Clamp((float)resouceReceivedNormalized, 0f, 1f);
  893. }
  894. }
  895. if (throttleInput < 0f) throttleInput *= 0.3f;
  896. wheelList.motorTorque = throttleInput * motorTorque;
  897.  
  898.  
  899.  
  900. }
  901. else if (usesIDdDrive == true && deploymentState == "Deployed" && motorEnabled)
  902. {
  903.  
  904. if (getICEOutput != null && getICEdDrive != null)
  905. {
  906. float driveDirection = 1f;
  907.  
  908. float motorSetDirection = 1f;
  909. if (reverseMotor == true) motorSetDirection *= -1;
  910.  
  911. if (getICEdDrive.inReverse) driveDirection *= -1;
  912.  
  913. float finalPower = motorSetDirection * (driveDirection * ((getICEOutput.lastCylForce * FlightInputHandler.state.mainThrottle) * getICEdDrive.gearedForceMulti));
  914.  
  915. if (getICEdDrive.coupledICEOutput > 0f)
  916. {
  917. finalPower = motorSetDirection * (driveDirection * ((getICEdDrive.coupledICEOutput * FlightInputHandler.state.mainThrottle) * getICEdDrive.gearedForceMulti));
  918. }
  919.  
  920. gWheelNum = 0;
  921.  
  922. for (int i = 0; i < wheelList.wheels.Count; i++)
  923. {
  924.  
  925. if (wheelList.wheels[i].wheelCollider.isGrounded)
  926. {
  927. gWheelNum += 1;
  928.  
  929. }
  930.  
  931. }
  932.  
  933.  
  934. if (this.vessel.rb_velocity.magnitude < ((this.wheelRadius * 2f) * 3.14f) * (getICEdDrive.rpmOutput / 60f) && getICEdDrive.currentGear != 0 && getICEOutput.currentRPM > 0f)
  935. {
  936.  
  937.  
  938. for (int i = 0; i < wheelList.wheels.Count; i++)
  939. {
  940.  
  941. if (wheelList.wheels[i].wheelCollider.isGrounded && gWheelNum > 0)
  942. {
  943. float flatTMulti = 1f;
  944.  
  945. if (tireFlat == true)
  946. {
  947. flatTMulti = 0.65f;
  948. }
  949. if (isDestroyed == true)
  950. {
  951. flatTMulti = 0.01f;
  952. }
  953.  
  954. float newTorque = Mathf.Lerp(wheelList.motorTorque, ((finalPower / gWheelNum) * flatTMulti), 0.125f);
  955.  
  956. wheelList.motorTorque = newTorque;
  957.  
  958.  
  959. this.rigidbody.drag = origDrag;
  960.  
  961. }
  962. else wheelList.motorTorque = 0f;
  963. }
  964.  
  965. }
  966. else
  967. {
  968. wheelList.motorTorque = 0f;
  969. this.rigidbody.drag = origDrag * (getICEdDrive.gearedForceMulti * gearDragMulti);
  970. }
  971. }
  972. else wheelList.motorTorque = 0f;
  973.  
  974. }
  975. else
  976. {
  977. wheelList.motorTorque = 0f;
  978. }
  979. #endregion
  980.  
  981. #region update drag
  982.  
  983. if (deploymentState == "Deployed")
  984. {
  985. part.minimum_drag = deployedDrag;
  986. part.maximum_drag = deployedDrag;
  987. }
  988. else
  989. {
  990. part.minimum_drag = 0f;
  991. part.maximum_drag = 0f;
  992. }
  993.  
  994. #endregion
  995.  
  996. #endregion
  997.  
  998.  
  999.  
  1000.  
  1001. if (usesIDdDrive == true)
  1002. {
  1003.  
  1004. #region drifting TEST
  1005. for (int i = 0; i < wheelList.wheels.Count; i++)
  1006. {
  1007.  
  1008. if (percentGripMod < 1f)
  1009. {
  1010. percentGripMod += 0.0035f;
  1011. if (percentGripMod < 0.64f)
  1012. {
  1013. setOnce = false;
  1014. }
  1015. else setOnce = true;
  1016. }
  1017.  
  1018. if (percentGripMod > 1f) percentGripMod = 1f;
  1019.  
  1020. if (this.vessel.rb_velocity.magnitude > (((wheelRadius * 0.5f) * wheelWidth) * 150f) && cornerLoad < origCLoad && setOnce == true)//compressing - lose grip... contrary to logic!
  1021. {
  1022.  
  1023. percentGripMod = (cornerLoad / origCLoad) * 0.225f;
  1024. setOnce = false;
  1025.  
  1026. }
  1027.  
  1028. origCLoad = cornerLoad;
  1029.  
  1030.  
  1031. if (wheelList.wheels[i].wheelCollider.isGrounded)
  1032. {
  1033. sideSlipMod = ((wheelRadius * 0.5f) * wheelWidth) * percentGripMod;
  1034. forwardSlipMod = (wheelRadius * 0.5f) * wheelWidth;
  1035.  
  1036. if (tireFlat == true)
  1037. {
  1038. sideSlipMod = ((wheelRadius * 0.5f) * wheelWidth) * 0.5f;
  1039. soundLoop.audio.Stop();
  1040. }
  1041.  
  1042. if (getICEdDrive.coupledICEOutput > 0f && motorEnabled && !getICEdDrive.inNeutral && getICEOutput.runState == "Running" || getICEdDrive.coupledICEOutput > 0f && motorEnabled && !getICEdDrive.inNeutral && getICEOutput.runState == "Overheated")
  1043. {
  1044. float useVelocity = this.part.vessel.rb_velocity.magnitude + 1f;
  1045.  
  1046. if (reverseMotor == false)
  1047. {
  1048.  
  1049. if (getICEdDrive.rpmOutput > wheelList.wheels[i].wheelCollider.rpm)
  1050. {
  1051.  
  1052. if (getICEdDrive.rpmOutput > wheelList.wheels[i].wheelCollider.rpm * 5f && FlightInputHandler.state.mainThrottle > 0.25f)
  1053. {
  1054. if (soundLoop.audio.isPlaying == false)
  1055. {
  1056. soundLoop.audio.Play();
  1057. }
  1058. }
  1059. else if (getICEdDrive.rpmOutput < wheelList.wheels[i].wheelCollider.rpm * 4f || FlightInputHandler.state.mainThrottle <= 0.25f && this.part.vessel.angularMomentum.magnitude < 5f)
  1060. {
  1061. fxBoInstance.SetActive(false);
  1062. if (soundLoop.audio.isPlaying == true)
  1063. {
  1064. soundLoop.audio.Stop();
  1065. }
  1066. }
  1067.  
  1068. if (getICEdDrive.rpmOutput > wheelList.wheels[i].wheelCollider.rpm * 10f)
  1069. {
  1070. fxBoInstance.SetActive(true);
  1071. }
  1072.  
  1073. alterSlipMod = (useVelocity / getICEdDrive.gearedForceMulti) * (1.6f - FlightInputHandler.state.mainThrottle);
  1074.  
  1075. }
  1076. else if (getICEdDrive.rpmOutput <= wheelList.wheels[i].wheelCollider.rpm * 3f)
  1077. {
  1078.  
  1079. soundLoop.audio.Stop();
  1080. fxBoInstance.SetActive(false);
  1081. alterSlipMod = 1.6f;
  1082. }
  1083. }
  1084. else
  1085. {
  1086.  
  1087. if (getICEdDrive.rpmOutput > wheelList.wheels[i].wheelCollider.rpm * -1f)
  1088. {
  1089. if (getICEdDrive.rpmOutput > wheelList.wheels[i].wheelCollider.rpm * -5f && FlightInputHandler.state.mainThrottle > 0.25F)
  1090. {
  1091. if (soundLoop.audio.isPlaying == false)
  1092. {
  1093. soundLoop.audio.Play();
  1094. }
  1095. }
  1096. else if (getICEdDrive.rpmOutput < wheelList.wheels[i].wheelCollider.rpm * -4f || FlightInputHandler.state.mainThrottle <= 0.25F && this.part.vessel.angularMomentum.magnitude < 5f)
  1097. {
  1098. fxBoInstance.SetActive(false);
  1099. if (soundLoop.audio.isPlaying == true)
  1100. {
  1101. soundLoop.audio.Stop();
  1102. }
  1103. }
  1104.  
  1105. if (getICEdDrive.rpmOutput > wheelList.wheels[i].wheelCollider.rpm * -10f)
  1106. {
  1107. fxBoInstance.SetActive(true);
  1108. }
  1109.  
  1110. alterSlipMod = (useVelocity / getICEdDrive.gearedForceMulti) * (1.6f - FlightInputHandler.state.mainThrottle);
  1111.  
  1112.  
  1113. }
  1114. else if (getICEdDrive.rpmOutput <= wheelList.wheels[i].wheelCollider.rpm * -3f)
  1115. {
  1116.  
  1117. soundLoop.audio.Stop();
  1118. fxBoInstance.SetActive(false);
  1119. alterSlipMod = 1.6f;
  1120. }
  1121. }
  1122.  
  1123.  
  1124.  
  1125. }
  1126. else
  1127. {
  1128. soundLoop.audio.Stop();
  1129. fxBoInstance.SetActive(false);
  1130. alterSlipMod = 1.6f;
  1131. }
  1132.  
  1133.  
  1134. vSlipCurve = AnimationCurve.Linear(0.001f, 5f, 140f, 0.0000001f);
  1135. vSlipCurve.AddKey(1f, 3.25f);
  1136. vSlipCurve.AddKey(3f, 1.9f);
  1137. vSlipCurve.AddKey(9f, 1.5f);
  1138. vSlipCurve.AddKey(18f, 0.9f);
  1139. vSlipCurve.AddKey(36f, 0.4f);
  1140. vSlipCurve.AddKey(80f, 0.09f);
  1141. vSlipCurve.AddKey(120f, 0.0185f);
  1142.  
  1143. float vSlipCResult = vSlipCurve.Evaluate(this.part.vessel.rb_velocity.magnitude);
  1144.  
  1145. aMSlipCurve = AnimationCurve.Linear(0.1f, 4f, 12f, 0.0000001f);
  1146. aMSlipCurve.AddKey(1f, 2.48f);
  1147. aMSlipCurve.AddKey(2f, 1.115f);
  1148. aMSlipCurve.AddKey(3f, 0.34f);
  1149. aMSlipCurve.AddKey(5f, 0.172f);
  1150. aMSlipCurve.AddKey(7f, 0.0855f);
  1151. aMSlipCurve.AddKey(9f, 0.0425f);
  1152. aMSlipCurve.AddKey(10f, 0.00785f);
  1153. aMSlipCurve.AddKey(11f, 0.001185f);
  1154.  
  1155. float correctAM = this.part.vessel.angularMomentum.magnitude;
  1156. if (correctAM <= 0.1f) correctAM = 0.1f;
  1157. if (correctAM > 12f) correctAM = 12f;
  1158.  
  1159. float aMSlipCResult = aMSlipCurve.Evaluate(correctAM);
  1160.  
  1161. if (getICEdDrive != null)
  1162. {
  1163. if (getICEdDrive.lsdEnabled == true)
  1164. {
  1165. alterSlipMod *= (1f + getICEdDrive.limitedSlip);
  1166. }
  1167. }
  1168.  
  1169. velocitySlipMod = Mathf.SmoothStep(velocitySlipMod, vSlipCResult * aMSlipCResult, 0.1f);
  1170.  
  1171. WheelFrictionCurve newSFriction = new WheelFrictionCurve();
  1172. newSFriction.extremumSlip = sidewaysExtremumSlip;
  1173. newSFriction.extremumValue = sidewaysExtremumValue;
  1174. newSFriction.asymptoteSlip = sidewaysAsymptoteSlip;
  1175. newSFriction.asymptoteValue = sidewaysAsymptoteValue;
  1176. newSFriction.stiffness = (origSFriction * (velocitySlipMod * alterSlipMod) * (sideSlipMod / (((float)this.part.vessel.geeForce + 0.1f) * 9f)));
  1177.  
  1178. wheelList.wheels[i].wheelCollider.sidewaysFriction = newSFriction;
  1179.  
  1180. WheelFrictionCurve newFFriction = new WheelFrictionCurve();
  1181. newFFriction.extremumSlip = forwardsExtremumSlip;
  1182. newFFriction.extremumValue = forwardsExtremumValue;
  1183. newFFriction.asymptoteSlip = forwardsAsymptoteSlip;
  1184. newFFriction.asymptoteValue = forwardsAsymptoteValue;
  1185. newFFriction.stiffness = (origFFriction * (velocitySlipMod * alterSlipMod) * (forwardSlipMod / (((float)this.part.vessel.geeForce + 0.001f) * 0.85f)));
  1186.  
  1187. wheelList.wheels[i].wheelCollider.forwardFriction = newFFriction;
  1188.  
  1189.  
  1190. }
  1191. else
  1192. {
  1193. sideSlipMod = 0.0001f;
  1194. soundLoop.audio.Stop();
  1195. fxBoInstance.SetActive(false);
  1196.  
  1197. WheelFrictionCurve newSFriction = new WheelFrictionCurve();
  1198. newSFriction.extremumSlip = sidewaysExtremumSlip;
  1199. newSFriction.extremumValue = sidewaysExtremumValue;
  1200. newSFriction.asymptoteSlip = sidewaysAsymptoteSlip;
  1201. newSFriction.asymptoteValue = sidewaysAsymptoteValue;
  1202. newSFriction.stiffness = Mathf.SmoothStep(origSFriction, sideSlipMod, 0.05f);
  1203.  
  1204. wheelList.wheels[i].wheelCollider.sidewaysFriction = newSFriction;
  1205.  
  1206. WheelFrictionCurve newFFriction = new WheelFrictionCurve();
  1207. newFFriction.extremumSlip = sidewaysExtremumSlip;
  1208. newFFriction.extremumValue = sidewaysExtremumValue;
  1209. newFFriction.asymptoteSlip = sidewaysAsymptoteSlip;
  1210. newFFriction.asymptoteValue = sidewaysAsymptoteValue;
  1211. newFFriction.stiffness = Mathf.SmoothStep(origFFriction, sideSlipMod, 0.05f);
  1212.  
  1213. wheelList.wheels[i].wheelCollider.forwardFriction = newFFriction;
  1214. }
  1215.  
  1216.  
  1217. }
  1218. #endregion
  1219.  
  1220. }
  1221.  
  1222.  
  1223. if (tireFlat == true)
  1224. {
  1225. Transform[] affectDmgState = this.part.FindModelTransforms("runFlat");
  1226.  
  1227. for (int i = 0; i < wheelList.wheels.Count; i++)
  1228. {
  1229.  
  1230. if (wheelList.wheels[i].wheelCollider.isGrounded)
  1231. {
  1232. if (affectDmgState != null)
  1233. {
  1234. foreach (Transform tD in affectDmgState)
  1235. {
  1236. tD.GetComponent<MeshRenderer>().enabled = true;
  1237. }
  1238. }
  1239. }
  1240. else
  1241. {
  1242. if (affectDmgState != null)
  1243. {
  1244. foreach (Transform tD in affectDmgState)
  1245. {
  1246. tD.GetComponent<MeshRenderer>().enabled = false;
  1247. }
  1248. }
  1249. }
  1250. }
  1251. }
  1252.  
  1253. }
  1254. }
  1255.  
  1256. public void ApplyDamage(float damageState)
  1257. {
  1258. print("Inside ApplyDamage for ICE Wheel!");
  1259. if (damageState < 0.5f)
  1260. {
  1261. float specialDamage = (float)rndNumber.rndRoll(0, 100);
  1262. if (specialDamage < 50f)
  1263. {
  1264. float doDamage = (float)rndNumber.rndRoll(0, 100);
  1265. if (doDamage < 75f && tireFlat != true)
  1266. {
  1267. Transform[] affectDmgState = this.part.FindModelTransforms("runFlat");
  1268.  
  1269. if (affectDmgState != null)
  1270. {
  1271. tireFlat = true;
  1272. Events["fixTire"].active = true;
  1273.  
  1274. foreach (Transform tD in affectDmgState)
  1275. {
  1276. tD.GetComponent<MeshRenderer>().enabled = true;
  1277. }
  1278. }
  1279. for (int i = 0; i < wheelList.wheels.Count; i++)
  1280. {
  1281.  
  1282. if (wheelList.wheels[i].wheelCollider.isGrounded)
  1283. {
  1284. wheelList.wheels[i].wheelCollider.radius = wheelRadius * 0.85f;
  1285.  
  1286. }
  1287.  
  1288. }
  1289.  
  1290. ScreenMessages.PostScreenMessage(new ScreenMessage("A flat tire!", 3f, ScreenMessageStyle.UPPER_CENTER));
  1291. }
  1292. if (doDamage <= 100f && doDamage >= 75f && hubDamage == false)
  1293. {
  1294. ScreenMessages.PostScreenMessage(new ScreenMessage("What is that horrible sound?", 3f, ScreenMessageStyle.UPPER_CENTER));
  1295. for (int i = 0; i < wheelList.wheels.Count; i++)
  1296. {
  1297.  
  1298. hubDamage = true;
  1299.  
  1300. }
  1301. }
  1302.  
  1303. }
  1304. if (damageState == 0.01f) //0.01 is the lowest sendmessage will use, consider this 0.
  1305. {
  1306. Transform[] affectDmgState = this.part.FindModelTransforms("runFlat");
  1307.  
  1308. if (affectDmgState != null)
  1309. {
  1310. tireFlat = false;
  1311. canFixFlat = false;
  1312. isDestroyed = true;
  1313. hubDamage = true;
  1314. foreach (Transform tD in affectDmgState)
  1315. {
  1316. tD.GetComponent<MeshRenderer>().enabled = false;
  1317. }
  1318. }
  1319. for (int i = 0; i < wheelList.wheels.Count; i++)
  1320. {
  1321.  
  1322. if (wheelList.wheels[i].wheelCollider.isGrounded)
  1323. {
  1324. wheelList.wheels[i].wheelCollider.radius = wheelRadius * 0.7f;
  1325.  
  1326. }
  1327.  
  1328. }
  1329. }
  1330.  
  1331. }
  1332. if (damageState == 1f)
  1333. {
  1334.  
  1335. Transform[] affectDmgState = this.part.FindModelTransforms("runFlat");
  1336.  
  1337. if (affectDmgState != null)
  1338. {
  1339. foreach (Transform tD in affectDmgState)
  1340. {
  1341. tD.GetComponent<MeshRenderer>().enabled = false;
  1342. }
  1343.  
  1344. tireFlat = false;
  1345. }
  1346. for (int i = 0; i < wheelList.wheels.Count; i++)
  1347. {
  1348.  
  1349.  
  1350. hubDamage = false;
  1351. isDestroyed = false;
  1352. canFixFlat = true;
  1353.  
  1354.  
  1355. }
  1356.  
  1357. }
  1358.  
  1359. }
  1360.  
  1361. }
  1362.  
  1363. class WheelClass
  1364. {
  1365. public WheelCollider wheelCollider;
  1366. public Transform wheelMesh;
  1367. public Transform suspensionParent;
  1368. public bool useRotation = false;
  1369. public bool useSuspension = false;
  1370. public WheelClass(WheelCollider _wheelCollider, Transform _wheelMesh, Transform _suspensionParent)
  1371. {
  1372. wheelCollider = _wheelCollider;
  1373. wheelMesh = _wheelMesh;
  1374. suspensionParent = _suspensionParent;
  1375. }
  1376.  
  1377. public WheelClass(WheelCollider _wheelCollider)
  1378. {
  1379. wheelCollider = _wheelCollider;
  1380. useRotation = false;
  1381. useSuspension = false;
  1382. }
  1383. }
  1384.  
  1385. class WheelList
  1386. {
  1387. public List<WheelClass> wheels;
  1388.  
  1389. private bool _enabled = false;
  1390. private float _brakeTorque = 0f;
  1391. private float _motorTorque = 0f;
  1392. private float _radius = 0.25f;
  1393. private float _suspensionDistance = 0.025f;
  1394.  
  1395. private float _mass = 0.1f;
  1396. public float forwardStiffness = 10f;
  1397. public float forwardsExtremumSlip = 1.0f;
  1398. public float forwardsExtremumValue = 20000.0f;
  1399. public float forwardsAsymptoteSlip = 2.0f;
  1400. public float forwardsAsymptoteValue = 10000.0f;
  1401. public float sidewaysStiffness = 1.0f;
  1402. public float sidewaysExtremumSlip = 1.0f;
  1403. public float sidewaysExtremumValue = 20000.0f;
  1404. public float sidewaysAsymptoteSlip = 2.0f;
  1405. public float sidewaysAsymptoteValue = 10000.0f;
  1406. public void Create(List<WheelCollider> colliders, List<Transform> wheelMeshes, List<Transform> suspensionParents)
  1407. {
  1408. wheels = new List<WheelClass>();
  1409. for (int i = 0; i < colliders.Count; i++)
  1410. {
  1411. wheels.Add(new WheelClass(colliders[i]));
  1412. if (i < wheelMeshes.Count)
  1413. {
  1414. wheels[i].wheelMesh = wheelMeshes[i];
  1415. wheels[i].useRotation = true;
  1416. }
  1417. if (i < suspensionParents.Count)
  1418. {
  1419. wheels[i].suspensionParent = suspensionParents[i];
  1420. wheels[i].useSuspension = true;
  1421. }
  1422. }
  1423. }
  1424.  
  1425. public void Create(WheelCollider collider, Transform wheelMesh, Transform suspensionParent)
  1426. {
  1427. wheels = new List<WheelClass>();
  1428. wheels.Add(new WheelClass(collider, wheelMesh, suspensionParent));
  1429. }
  1430.  
  1431. public bool enabled
  1432. {
  1433. get
  1434. {
  1435. return _enabled;
  1436. }
  1437.  
  1438. set
  1439. {
  1440. _enabled = value;
  1441. for (int i = 0; i < wheels.Count; i++)
  1442. {
  1443. wheels[i].wheelCollider.enabled = value;
  1444. }
  1445. }
  1446. }
  1447.  
  1448. public float brakeTorque
  1449. {
  1450. get
  1451. {
  1452. return _brakeTorque;
  1453. }
  1454. set
  1455. {
  1456. _brakeTorque = value;
  1457. for (int i = 0; i < wheels.Count; i++)
  1458. {
  1459. wheels[i].wheelCollider.brakeTorque = value;
  1460. }
  1461. }
  1462. }
  1463.  
  1464. public float motorTorque
  1465. {
  1466. get
  1467. {
  1468. return _motorTorque;
  1469. }
  1470. set
  1471. {
  1472. _motorTorque = value;
  1473. for (int i = 0; i < wheels.Count; i++)
  1474. {
  1475. wheels[i].wheelCollider.motorTorque = value;
  1476.  
  1477. }
  1478. }
  1479. }
  1480.  
  1481.  
  1482.  
  1483. public void updateSpring(float spring, float damper, float targetPosition)
  1484. {
  1485. JointSpring jointSpring = new JointSpring();
  1486. jointSpring.spring = spring;
  1487. jointSpring.damper = damper;
  1488. jointSpring.targetPosition = targetPosition;
  1489. for (int i = 0; i < wheels.Count; i++)
  1490. {
  1491. wheels[i].wheelCollider.suspensionSpring = jointSpring;
  1492. }
  1493. }
  1494.  
  1495. public float suspensionDistance
  1496. {
  1497. get
  1498. {
  1499. return _suspensionDistance;
  1500. }
  1501. set
  1502. {
  1503. _suspensionDistance = value;
  1504. for (int i = 0; i < wheels.Count; i++)
  1505. {
  1506. wheels[i].wheelCollider.suspensionDistance = value;
  1507. }
  1508. }
  1509. }
  1510.  
  1511. public float mass
  1512. {
  1513. get
  1514. {
  1515. return _mass;
  1516. }
  1517. set
  1518. {
  1519. _mass = value;
  1520. for (int i = 0; i < wheels.Count; i++)
  1521. {
  1522. wheels[i].wheelCollider.mass = value;
  1523. }
  1524. }
  1525. }
  1526.  
  1527. public float radius
  1528. {
  1529. get
  1530. {
  1531. return _radius;
  1532. }
  1533. set
  1534. {
  1535. _radius = value;
  1536. for (int i = 0; i < wheels.Count; i++)
  1537. {
  1538. wheels[i].wheelCollider.radius = value;
  1539. }
  1540. }
  1541. }
  1542.  
  1543. public void updateWheelFriction()
  1544. {
  1545.  
  1546. WheelFrictionCurve forwardFriction = new WheelFrictionCurve();
  1547. forwardFriction.extremumSlip = forwardsExtremumSlip;
  1548. forwardFriction.extremumValue = forwardsExtremumValue;
  1549. forwardFriction.asymptoteSlip = forwardsAsymptoteSlip;
  1550. forwardFriction.asymptoteValue = forwardsAsymptoteValue;
  1551. forwardFriction.stiffness = forwardStiffness;
  1552.  
  1553. WheelFrictionCurve sidewaysFriction = new WheelFrictionCurve();
  1554. sidewaysFriction.extremumSlip = sidewaysExtremumSlip;
  1555. sidewaysFriction.extremumValue = sidewaysExtremumValue;
  1556. sidewaysFriction.asymptoteSlip = sidewaysAsymptoteSlip;
  1557. sidewaysFriction.asymptoteValue = sidewaysAsymptoteValue;
  1558. sidewaysFriction.stiffness = sidewaysStiffness;
  1559.  
  1560. for (int i = 0; i < wheels.Count; i++)
  1561. {
  1562. wheels[i].wheelCollider.forwardFriction = forwardFriction;
  1563. wheels[i].wheelCollider.sidewaysFriction = sidewaysFriction;
  1564. }
  1565. }
  1566. }
  1567.  
  1568. //******************************************
  1569.  
  1570. public class aircraftParkDist : PartModule
  1571. {
  1572. [KSPField(isPersistant = true, guiActiveEditor = true, guiActive = true, guiName = "Park Dist: "), UI_FloatRange(minValue = 0f, maxValue = 1.2f, stepIncrement = 0.1f)]
  1573. public float dockDistance = 0.9f;
  1574.  
  1575. private bool doItOnce = true;
  1576. public Transform affectClawNode;
  1577.  
  1578. public void FixedUpdate()
  1579. {
  1580. if (doItOnce == true)
  1581. {
  1582. try
  1583. {
  1584. affectClawNode = this.part.FindModelTransform("clawLoc");
  1585. doItOnce = false;
  1586. }
  1587. catch
  1588. {
  1589. print("Problem locating clawLoc!");
  1590. }
  1591. }
  1592.  
  1593.  
  1594. if (affectClawNode != null)
  1595. {
  1596.  
  1597. affectClawNode.localPosition = new Vector3(-dockDistance, 0f, 0f);
  1598. }
  1599.  
  1600.  
  1601.  
  1602.  
  1603.  
  1604. }
  1605.  
  1606. }
  1607.  
  1608. //*************************************
  1609.  
  1610. public class IDpartTurner : PartModule
  1611. {
  1612. [KSPField]
  1613. public string targetPartObject = "turnEmpty";
  1614. [KSPField]
  1615. public float rotationDirectionX = 0f;
  1616. [KSPField]
  1617. public float rotationDirectionY = 0f;
  1618. [KSPField]
  1619. public float rotationDirectionZ = 1f;
  1620. [KSPField]
  1621. public float defaultRotationX = 0f;
  1622. [KSPField]
  1623. public float defaultRotationY = 0f;
  1624. [KSPField]
  1625. public float defaultRotationZ = 0f;
  1626. [KSPField(guiActive = false, guiActiveEditor = true, guiName = "Steering Multiplier", isPersistant = true)]
  1627. public float steerMultiplier = 10f;
  1628. [KSPField]
  1629. public float steerMaxSpeed = 18f;
  1630. [KSPField]
  1631. public bool speedAdjustedSteering = true;
  1632. [KSPField]
  1633. public float speedAdjustedSteeringMinimumMultiplier = 0.1f;
  1634.  
  1635. [KSPField(guiActive = true, guiActiveEditor = true, guiName = "Steering", isPersistant = true)]
  1636. public bool steeringEnabled = false;
  1637. [KSPField(guiActive=false, guiName="use QE, not AD", isPersistant=true)]
  1638. public bool altInputModeEnabled = false;
  1639. [KSPField(guiActive = true, guiActiveEditor = true, guiName = "Reverse Steering", isPersistant = true)]
  1640. public bool reversedInput = false;
  1641. [KSPField(guiActive = false, guiName = "Ignore Trim", isPersistant = true)]
  1642. public bool ignoreTrim = true;
  1643. [KSPField]
  1644. public bool useWheelSteeringAxis = true;
  1645.  
  1646.  
  1647. private Vector3 currentTrim = new Vector3(0,0,0);
  1648. private Vector3 currentRotation = new Vector3(0, 0, 0);
  1649. private Vector3 steeringInput;
  1650. private Transform partTransform;
  1651.  
  1652. [KSPAction("Toggle Steering")]
  1653. public void toggleSteeringAction(KSPActionParam param)
  1654. {
  1655. toggleSteering();
  1656. }
  1657.  
  1658. [KSPAction("Invert Steering")]
  1659. public void toggleInvertAction(KSPActionParam param)
  1660. {
  1661. reversedInput = !reversedInput;
  1662. }
  1663.  
  1664. [KSPEvent(name = "toggleSteering", active = true, guiActive = false, guiActiveEditor = true, guiName = "Toggle Steering")]
  1665. public void toggleSteering()
  1666. {
  1667. steeringEnabled = !steeringEnabled;
  1668. }
  1669.  
  1670. [KSPEvent(name = "toggleAltInputMode", active = false, guiActive = false, guiName = "QE or AD to steer")]
  1671. public void toggleAltInputMode()
  1672. {
  1673. altInputModeEnabled = !altInputModeEnabled;
  1674. }
  1675.  
  1676. [KSPEvent(name = "toggleIgnoreTrim", active = false, guiActive = false, guiName = "Toggle Ignore trim")]
  1677. public void toggleIgnoreTrim()
  1678. {
  1679. ignoreTrim = !ignoreTrim;
  1680. }
  1681.  
  1682. [KSPEvent(name = "toggleReverseInput", active = true, guiActive = false, guiActiveEditor = true, guiName = "Toggle Reverse Steering")]
  1683. public void toggleReverseInput()
  1684. {
  1685. reversedInput = !reversedInput;
  1686. }
  1687.  
  1688. [KSPEvent(name = "increaseSteering", active = true, guiActive = false, guiActiveEditor = true, guiName = "Increase Steering")]
  1689. public void increaseSteering()
  1690. {
  1691. steerMultiplier += 1f;
  1692. if (steerMultiplier > 90f) steerMultiplier = 90f;
  1693. }
  1694.  
  1695. [KSPEvent(name = "decreaseSteering", active = true, guiActive = false, guiActiveEditor = true, guiName = "Decrease Steering")]
  1696. public void decreaseSteering()
  1697. {
  1698. steerMultiplier -= 1;
  1699. if (steerMultiplier < 1f) steerMultiplier = 1f;
  1700. }
  1701.  
  1702. [KSPEvent(name = "ToggleSpeedAdjustedSteering", active = true, guiActive = false, guiActiveEditor = true, guiName = "Dynamic Steering")]
  1703. public void toggleSpeedAdjustedSteeringEvent()
  1704. {
  1705. speedAdjustedSteering = !speedAdjustedSteering;
  1706. }
  1707.  
  1708. public void steerPart(float direction)
  1709. {
  1710. float steerModifier = 1f;
  1711. if (speedAdjustedSteering)
  1712. {
  1713. steerModifier = Mathf.Max(speedAdjustedSteeringMinimumMultiplier, -(((float)vessel.horizontalSrfSpeed - steerMaxSpeed) / steerMaxSpeed));
  1714. }
  1715.  
  1716. currentRotation.x = steerMultiplier * rotationDirectionX * direction * steerModifier;
  1717. currentRotation.y = steerMultiplier * rotationDirectionY * direction * steerModifier;
  1718. currentRotation.z = steerMultiplier * rotationDirectionZ * direction * steerModifier;
  1719. }
  1720.  
  1721. private void setPartRotation()
  1722. {
  1723.  
  1724. if (partTransform != null)
  1725. partTransform.localRotation = Quaternion.Euler(currentRotation);
  1726. }
  1727.  
  1728. public override void OnStart(PartModule.StartState state)
  1729. {
  1730. base.OnStart(state);
  1731. partTransform = part.FindModelTransform(targetPartObject);
  1732. if (useWheelSteeringAxis)
  1733. {
  1734. Events["toggleIgnoreTrim"].guiActive = false;
  1735. Events["toggleAltInputMode"].guiActive = false;
  1736. Fields["altInputModeEnabled"].guiActive = false;
  1737. Fields["ignoreTrim"].guiActive = false;
  1738. }
  1739.  
  1740. }
  1741.  
  1742. public override void OnUpdate()
  1743. {
  1744. if (!HighLogic.LoadedSceneIsFlight || !vessel.isActiveVessel) return;
  1745. FlightCtrlState ctrl = vessel.ctrlState;
  1746.  
  1747. int reverseModifier = 1;
  1748.  
  1749. if (useWheelSteeringAxis)
  1750. {
  1751. steeringInput.x = vessel.ctrlState.wheelSteer + vessel.ctrlState.wheelSteerTrim;
  1752. }
  1753. else
  1754. {
  1755. if (altInputModeEnabled)
  1756. {
  1757. steeringInput.x = ctrl.roll;
  1758. if (ignoreTrim) steeringInput.x -= ctrl.rollTrim;
  1759. }
  1760. else
  1761. {
  1762. steeringInput.x = ctrl.yaw;
  1763. if (ignoreTrim) steeringInput.x -= ctrl.yawTrim;
  1764. }
  1765. }
  1766.  
  1767. if (reversedInput)
  1768. {
  1769. reverseModifier = -1;
  1770. }
  1771.  
  1772. if (steeringEnabled)
  1773. {
  1774. steerPart(steeringInput.x * reverseModifier);
  1775. }
  1776. else steerPart(0);
  1777.  
  1778.  
  1779. setPartRotation();
  1780. }
  1781. }
  1782.  
  1783. //***************************************
  1784.  
  1785. public class IDice : PartModule
  1786. {
  1787. //ID-ICE InfiniteDice Internal Combustion Engine - Module for KSP. Mod, code, models, textures are shared under
  1788. //Attribution-NonCommercial-NoDerivatives 4.0 International (CC BY-NC-ND 4.0) - You are free to:Share — copy and redistribute the material in any medium or format - Ypu can modify files for your personal use.
  1789. //If you remix, transform, or build upon the material, you may not distribute the modified material. You may not use the material for commercial purposes.
  1790.  
  1791. //A note on the license - I have dozens of hours in this and other mods, which I share out to the community for no fees. Id you like the mod please share your thoughts/images/videos on the KSP forum thread!
  1792. //Thanks for using this mod.
  1793.  
  1794. //ID ICE is not perfect! I don't claim this is a totally realistic simulation of how a real engine works. My overall goal was to experiment with making an alternative engine module for KSP.
  1795. //Secondly to support and inspire the community to take more advantage of EVA activities. Have fun!
  1796.  
  1797.  
  1798. [KSPField]
  1799. public int numOfCyls = 1; // how many cylinders does the engine have, each cylinder produces a fraction of the enginePower.
  1800.  
  1801. [KSPField]
  1802. public float engineDisplacement = 17.3f; // in litres - not in use yet. to convert to cubic inches * 61.0237
  1803.  
  1804. [KSPField(isPersistant = true, guiActiveEditor = true, guiActive = false, guiName = "Performance Multi"), UI_FloatRange(minValue = 5f, maxValue = 20f, stepIncrement = 0.5f)]
  1805. public float enginePerformanceMulti = 10f; // total engine power rating - the power it generates will NOT be equal to this but is only based on this.
  1806.  
  1807. [KSPField(isPersistant = true)]
  1808. public float origEngPerformance = 0f;
  1809.  
  1810. [KSPField]
  1811. public int camTime = 10; // the degrees of one rotation that the cylinder produces power numOfCyls * camTime should NOT EXCEED 360!!!
  1812.  
  1813. [KSPField]
  1814. public float engineRedline = 4500f; // the max permitted speed without incurring heat and wear losses
  1815.  
  1816. [KSPField]
  1817. public float engineIdleSpeed = 600f; // the speed the engine must be turning in order to maintain a run state, running below this speed will increase the chance of stall.
  1818.  
  1819. [KSPField]
  1820. public float engineHeatup = 1f; //1 is normal... some smaller engines need a much higher multiplier
  1821.  
  1822. [KSPField]
  1823. public string resourceType = "LiquidFuel"; // the fuel the engine runs on
  1824.  
  1825. [KSPField(guiActive = true, guiName = "RPM: ")]
  1826. public float currentRPM = 0f;
  1827.  
  1828. [KSPField(guiActive = true, isPersistant = true)]
  1829. public bool ctrlEngine = true;
  1830.  
  1831. [KSPField]
  1832. public bool coupleOutput = false;
  1833.  
  1834. // Snjo can get/set to this for the throttle gui********************************************************************************************MULTI THROTTLE STUFF********
  1835. public float throttleActual;// this is either the KSP throttle or the multi-gui throttle see checkThrottle()
  1836.  
  1837. [KSPField(isPersistant = true, guiActiveEditor = false, guiActive = true, guiName = "Engine Throttle: "), UI_FloatRange(minValue = 0f, maxValue = 1f, stepIncrement = 0.1f)]
  1838. public float guiThrottle = 0f;
  1839.  
  1840. public float lastGoodThrottle = 0f; // to hold the last throttle setting when pilot leaves plane... why? just because!
  1841.  
  1842. [KSPField(isPersistant = true, guiActiveEditor = true, guiActive = true, guiName = "Gui Throttle"), UI_Toggle(controlEnabled = false, disabledText = "No", enabledText = "Yes")]
  1843. public bool useMultiThrottle = false; // change to true in cfg to enable snjos multi-throttle gui controls.
  1844.  
  1845. [KSPField(isPersistant = true, guiActiveEditor = true, guiActive = true, guiName = "W Throttle"), UI_Toggle(controlEnabled = false, disabledText = "No", enabledText = "Yes")]
  1846. public bool useWThrottle = false; // change to true in cfg to enable W tap throttle.
  1847. //********************************************************************************************************************************************END MULTI THROTTLE********
  1848. public float ignitionTimer = 0.01f;
  1849. public float ignCooldown = 0.01f;
  1850.  
  1851. public float failureTimer = 30f;
  1852. public float failureCooldown = 30f;
  1853.  
  1854. public float animateTimer = 1f;
  1855. public float animateCooldown = 1f;
  1856.  
  1857. public bool fixOngoing = false;
  1858. public float doneTime = 0f;
  1859. public float startTime = 0f;
  1860. public float fixTime = 0f;
  1861. public string jobName = "nil";
  1862. public bool takeOilOnce = false;
  1863.  
  1864. public IDdDrive getICEdDrive;
  1865.  
  1866. public float idleForceLoss = 0.1f;
  1867. public int atRotation = 0; // what is the current rotation of the engine crank? determines where power and idle force happens
  1868. public int chokeSet = 0; //0 none, 1 half, 2 full... //implement for r2.
  1869.  
  1870. public bool starterOn = false;
  1871. public float starterCond = 100f;
  1872. public bool fuelOn = false;
  1873. public bool elecOn = false;
  1874. public bool carbHeat = false; //implement for r2
  1875. public float carbIce = 1f; // 0 to 1 : 1 being clear of ice and no power loss. The floor for this is 0.5f
  1876.  
  1877. public bool dmgOilLeak = false;
  1878. public bool dmgMissFire = false;
  1879. public bool dmgFuelCutout = false;
  1880. public bool dmgOutOfWhack = false;
  1881.  
  1882. [KSPField(isPersistant = true, guiActiveEditor = true, guiActive = true, guiName = "Prop Pitch: "), UI_FloatRange(minValue = -1f, maxValue = 1f, stepIncrement = 1f)]
  1883. public float propPitch = 1f; // 1 is 100% and is normal, 0 is neutral, -1 is reverse.
  1884.  
  1885. public float pitchModifier = 1f;
  1886. public bool togglePitch = false;
  1887.  
  1888. [KSPField]
  1889. public bool remoteCharger = false; // does it charge batteries within a set distance?
  1890.  
  1891. public float remChargeDist = 0f;
  1892. public bool madeCharge = false;
  1893.  
  1894. [KSPField]
  1895. public bool variPitch = false;
  1896.  
  1897. [KSPField]
  1898. public string animatedPart = "none";
  1899.  
  1900. [KSPField]
  1901. public string sfxEngineDrone = "IDiCEr1/Sounds/IDiceE4"; //constant sound loop
  1902.  
  1903. [KSPField]
  1904. public string sfxEngineBackF = "IDiCEr1/Sounds/IDiceBf1"; //constant sound loop
  1905.  
  1906. [KSPField]
  1907. public string sfxEngineGroup = "IDiCEr1/Sounds/IDiceE2"; //idle sound loop
  1908.  
  1909. [KSPField]
  1910. public string sfxEngineStart = "IDiCEr1/Sounds/IDiceStart"; //start sound one time
  1911.  
  1912. [KSPField]
  1913. public string sfxSupercharger = "IDiCEr1/Sounds/IDSuperC"; //start sound one time
  1914.  
  1915. [KSPField]
  1916. public string sfxFail = "IDiCEr1/Sounds/IDiceFail"; //spun bearing sound
  1917.  
  1918. public float propScalePower = 0f;
  1919. public float coldLoss = 0f;
  1920.  
  1921. [KSPField(isPersistant = true, guiActive = true, guiName = "State: ")]
  1922. public string runState = "Off"; // Off, Starting, Stalled, Running, Overheated, Seized, Dead
  1923.  
  1924. public float lastCylForce;
  1925. public int lastCylToFire;
  1926.  
  1927. [KSPField(isPersistant = true, guiActive = false, guiName = "Ignition: ")]
  1928. public float sparkEff = 1f; // 1 is new, as it gets used this will diminish till finally the engine will run like crap
  1929.  
  1930. [KSPField(isPersistant = true, guiActive = false, guiName = "Air Filter: ")]
  1931. public float airEff = 1f; // 1 is new, as it gets used this will diminish till finally the engine will run like crap
  1932.  
  1933. public float wearRate = 0.0001f; // this is the overall wear multiplier.
  1934.  
  1935. [KSPField]
  1936. public float fuelAirMix = 0.066666f; // rate at which the engine will consume fuel enter Ratio....
  1937.  
  1938. public float actualAirDensity;
  1939. public float airNeeded; // formula will be CubicInches * current rpm * Efficiency (airfilter + atmospheric density/2) / 3456 == cubic feet per minute so * by 0.000471947443 for cubicM/sec...
  1940.  
  1941. [KSPField(isPersistant = true, guiActive = true, guiName = "Oil Level: ")]
  1942. public float oilLevel = 100f; //%
  1943.  
  1944. [KSPField(isPersistant = true, guiActive = false, guiName = "Oil Condition: ")]
  1945. public float oilCond = 100f; //%
  1946.  
  1947. [KSPField]
  1948. public float oilCapacity = 50f; //litres
  1949.  
  1950. [KSPField(guiActive = true, guiName = "Oil Temp: ")]
  1951. public float oilTemp = 0f; // this will be ambient air temp when off and will cool to this.
  1952.  
  1953. public float oilMaxTemp = 260f;// celcius; after this chance of oilCond loss is higher.
  1954. public float carbTemp = 30f; // this will be ambient air temp.
  1955. public float maxEngTemp = 200f; //celcius
  1956.  
  1957. [KSPField]
  1958. public bool airCooled = true;
  1959.  
  1960. [KSPField]
  1961. public float coolantCapacity = 10f; //litres
  1962.  
  1963. public float coolantTemp = 0f; //litres
  1964.  
  1965. public float engTemp = 0f; //this will be ambient air temp when off. and will cool to this
  1966.  
  1967. public float overHeatMod = 1.0125f; // heat and wear rates are increased!
  1968. public float coolingEff = 0.025f; //% loss of heat when operating under max rpm and with at least 50% oil level
  1969.  
  1970. public int secureRandom; // storage for a random number.
  1971.  
  1972. public List<IDliqCool> getAllLCool = new List<IDliqCool>();
  1973.  
  1974. public Transform iceForceTransform;
  1975. public Transform propellerLocation;
  1976. public Transform[] exh;
  1977. public Vector3 thrustDirection;
  1978. public GameObject exhaustFX1;
  1979. public GameObject oilBurningFX;
  1980. public Light lightOne;
  1981. public GameObject oilBurnTrailFX;
  1982. public FXGroup soundGroup, soundStart, soundFail, soundDrone, soundSuperC, soundBackF;
  1983.  
  1984. private Transform animateTransform;
  1985. private Transform animateDefaultTransform;
  1986. private bool firstRun = true;
  1987.  
  1988. [KSPField(guiActive = false, isPersistant = true)]
  1989. public bool doItOnce = true;
  1990.  
  1991. #region Export Direct Drive
  1992. [KSPField]
  1993. public bool hasDirectOutput = false;
  1994.  
  1995.  
  1996. #endregion
  1997.  
  1998. #region Superchargers
  1999. [KSPField(isPersistant = true, guiActiveEditor = true, guiActive = false, guiName = "Supercharged"), UI_Toggle(controlEnabled = false, disabledText = "No", enabledText = "Yes")]
  2000. public bool isSupercharged = false;
  2001.  
  2002. [KSPField(isPersistant = true, guiActiveEditor = true, guiActive = false, guiName = "TwoStage"), UI_Toggle(controlEnabled = false, disabledText = "No", enabledText = "Yes")]
  2003. public bool isTwoStageAuto = false;
  2004.  
  2005. [KSPField(isPersistant = true, guiActiveEditor = true, guiActive = false, guiName = "Low Boost"), UI_FloatRange(minValue = 1.05f, maxValue = 1.7f, stepIncrement = 0.05f)]
  2006. public float boostLowMultiplier = 1.1f;
  2007.  
  2008. [KSPField(isPersistant = true, guiActiveEditor = true, guiActive = false, guiName = "High Boost"), UI_FloatRange(minValue = 1.1f, maxValue = 1.7f, stepIncrement = 0.05f)]
  2009. public float boostHighMultiplier = 1.45f;
  2010.  
  2011. [KSPField]
  2012. public double twoStageTripAlt = 3000f;
  2013.  
  2014. public float currentBoostMulti = 1.1f;
  2015.  
  2016. #endregion
  2017.  
  2018. #region Experimental Thrust Averaging
  2019.  
  2020. public Transform iceAvgThrustPosition;
  2021.  
  2022. [KSPField]
  2023. public bool useThrustAveraging = false;
  2024. public Transform actualThrustPosition;
  2025.  
  2026. #endregion
  2027.  
  2028. #region KerbalStuff
  2029. public Kerbal callKerbalStats;
  2030. public KerbalEVA findKerbal;
  2031. public string lastKerbalName;
  2032. public float ourKerbalsStupid = 0f;
  2033. public bool ourKerbalIsBadass = false;
  2034. public float ourKerbalCourage = 0f;
  2035. #endregion
  2036.  
  2037. public bool checkOnce = true;
  2038.  
  2039. [KSPEvent(guiName = "Toggle Prop Pitch", guiActive = false, guiActiveUnfocused = false, unfocusedRange = 5f)]
  2040. public void setPitch()
  2041. {
  2042. if (variPitch != true)
  2043. {
  2044. togglePitch = true;
  2045. }
  2046.  
  2047. }
  2048.  
  2049. [KSPEvent(name = "autoIgnition", active = true, guiActive = true, guiName = "Auto Start")]
  2050. public void letsAutoStart()
  2051. {
  2052. if (ctrlEngine == true)
  2053. {
  2054. if (elecOn == false)
  2055. {
  2056. if (sparkEff > 0f)
  2057. {
  2058. elecOn = true;
  2059. print("Electricals On!");
  2060.  
  2061. }
  2062. else if (sparkEff <= 0f)
  2063. {
  2064. sparkEff = 0f;
  2065. elecOn = false;
  2066. print("Electrical needs fixing... cleaning time!");
  2067. }
  2068. }
  2069.  
  2070. if (fuelOn == false)
  2071. {
  2072. if (sparkEff > 0f)
  2073. {
  2074. fuelOn = true;
  2075. print("Fuel System On!");
  2076.  
  2077. }
  2078. else if (sparkEff <= 0f)
  2079. {
  2080. print("Plugs are Fouled, clean them!");
  2081. }
  2082. }
  2083.  
  2084. if (starterOn == false)
  2085. {
  2086. if (starterCond >= 1f && elecOn == true && runState != "Seized" && runState != "Dead")
  2087. {
  2088. if (runState == "Off" || runState == "Stalled")
  2089. {
  2090. soundStart.audio.Play();
  2091. starterOn = true;
  2092. print("Starter Engaged!");
  2093. }
  2094. else if (runState == "Running" || runState == "Overheated" || runState == "Starting")
  2095. {
  2096. starterCond = starterCond - (UnityEngine.Random.Range(1f, 5f));
  2097. }
  2098. }
  2099. else if (starterCond < 1f || elecOn == false)
  2100. {
  2101. print("Starter must be damaged, or Electric Power is off!");
  2102. }
  2103. }
  2104.  
  2105.  
  2106. }
  2107.  
  2108. }
  2109.  
  2110. [KSPEvent(name = "controlENG", active = true, guiActive = true, guiName = "Control Engine")]
  2111. public void letsControlEngine()
  2112. {
  2113. if (ctrlEngine == false)
  2114. {
  2115. ctrlEngine = true;
  2116. }
  2117. else if (ctrlEngine == true)
  2118. {
  2119. ctrlEngine = false;
  2120. }
  2121. }
  2122.  
  2123.  
  2124. [KSPEvent(name = "shutdownENG", active = true, guiActive = true, guiName = "Shutdown Engine")]
  2125. public void letsShutdownEngine()
  2126. {
  2127. if (elecOn == true)
  2128. {
  2129. elecOn = false;
  2130. fuelOn = false;
  2131. runState = "Off";
  2132. }
  2133.  
  2134. }
  2135.  
  2136. [KSPEvent(name = "toggleThrustAvg", active = true, guiActive = false, guiName = "Average Thrust Position")]
  2137. public void letsAverageThrust()
  2138. {
  2139. if (useThrustAveraging == false)
  2140. {
  2141. print("Thrust Averaging On");
  2142. useThrustAveraging = true;
  2143. }
  2144. else if (useThrustAveraging == true)
  2145. {
  2146. print("Thrust Averaging Off");
  2147. useThrustAveraging = false;
  2148. }
  2149. }
  2150.  
  2151. [KSPEvent(name = "toggleCarbHeat", active = true, guiActive = false, guiName = "Carb Heat")]
  2152. public void letsHeatCarbs()
  2153. {
  2154. if (carbHeat == false)
  2155. {
  2156. print("Carb Heat On");
  2157. carbHeat = true;
  2158. }
  2159. else if (carbHeat == true)
  2160. {
  2161. print("Carb Heat Off");
  2162. carbHeat = false;
  2163. }
  2164. }
  2165.  
  2166. [KSPAction("Auto Start Engine")]
  2167. public void doAutoStartEngine(KSPActionParam param)
  2168. {
  2169. letsAutoStart();
  2170. }
  2171.  
  2172. #region EVA Repair/Inspection Options
  2173.  
  2174. [KSPEvent(active = true, guiName = "Inspect Engine", guiActiveUnfocused = true, externalToEVAOnly = true, guiActive = false, unfocusedRange = 4f)]
  2175. public void inspectEngine()
  2176. {
  2177. if (fixOngoing == false)
  2178. {
  2179. jobName = "inspect";
  2180. fixTime = 15 * (1f + ourKerbalsStupid);
  2181. startTime = Time.time;
  2182. print(startTime + " is the time the job started.");
  2183. ScreenMessages.PostScreenMessage(new ScreenMessage("Okay now... let me have a look!", fixTime, ScreenMessageStyle.UPPER_CENTER));
  2184. fixOngoing = true;
  2185. doneTime = fixTime + startTime;
  2186.  
  2187. }
  2188. }
  2189.  
  2190. [KSPEvent(active = true, guiName = "Clean Filters", guiActiveUnfocused = true, externalToEVAOnly = true, guiActive = false, unfocusedRange = 4f)]
  2191. public void fixFilters()
  2192. {
  2193. if (fixOngoing == false)
  2194. {
  2195. jobName = "airfilter";
  2196. fixTime = 10f * (1f + ourKerbalsStupid);
  2197. startTime = Time.time;
  2198. print(startTime + " is the time the job started.");
  2199. ScreenMessages.PostScreenMessage(new ScreenMessage("It will take me a few moments to fix the filter...", fixTime, ScreenMessageStyle.UPPER_CENTER));
  2200. fixOngoing = true;
  2201. doneTime = fixTime + startTime;
  2202. }
  2203.  
  2204.  
  2205. }
  2206.  
  2207. [KSPEvent(active = true, guiName = "Clean Electrical", guiActiveUnfocused = true, externalToEVAOnly = true, guiActive = false, unfocusedRange = 4f)]
  2208. public void fixElec()
  2209. {
  2210. if (fixOngoing == false)
  2211. {
  2212. jobName = "electrical";
  2213. fixTime = 15f * (1f + ourKerbalsStupid);
  2214. startTime = Time.time;
  2215. print(startTime + " is the time the job started.");
  2216. ScreenMessages.PostScreenMessage(new ScreenMessage("Hopefully I won't get a shock working on this electrical system...", fixTime, ScreenMessageStyle.UPPER_CENTER));
  2217. fixOngoing = true;
  2218. doneTime = fixTime + startTime;
  2219.  
  2220. }
  2221.  
  2222. }
  2223.  
  2224. [KSPEvent(active = true, guiName = "Change Oil", guiActiveUnfocused = true, externalToEVAOnly = true, guiActive = false, unfocusedRange = 4f)]
  2225. public void fixOil()
  2226. {
  2227. if (fixOngoing == false)
  2228. {
  2229. jobName = "oilservice";
  2230. fixTime = 20f * (1f + ourKerbalsStupid);
  2231. startTime = Time.time;
  2232. print(startTime + " is the time the job started.");
  2233. ScreenMessages.PostScreenMessage(new ScreenMessage("Why do I get stuck changing this oil?...", fixTime, ScreenMessageStyle.UPPER_CENTER));
  2234. fixOngoing = true;
  2235. takeOilOnce = true;
  2236. doneTime = fixTime + startTime;
  2237.  
  2238.  
  2239. }
  2240.  
  2241. }
  2242.  
  2243. [KSPEvent(active = true, guiName = "Fix Engine", guiActiveUnfocused = true, externalToEVAOnly = true, guiActive = false, unfocusedRange = 4f)]
  2244. public void fixState()
  2245. {
  2246. if (fixOngoing == false)
  2247. {
  2248. jobName = "engine";
  2249. fixTime = 45f * (1f + ourKerbalsStupid);
  2250. startTime = Time.time;
  2251. print(startTime + " is the time the job started.");
  2252. ScreenMessages.PostScreenMessage(new ScreenMessage("This might take a while! Please be patient! ...and quiet!...", fixTime, ScreenMessageStyle.UPPER_CENTER));
  2253. fixOngoing = true;
  2254. takeOilOnce = true;
  2255. doneTime = fixTime + startTime;
  2256.  
  2257.  
  2258. }
  2259.  
  2260. }
  2261.  
  2262. #endregion
  2263.  
  2264. public override void OnStart(PartModule.StartState state)
  2265. {
  2266. base.OnStart(state);
  2267. propellerLocation = base.part.FindModelTransform("propeller");
  2268. iceForceTransform = base.part.FindModelTransform("thrustTransform");
  2269.  
  2270.  
  2271. actualThrustPosition = iceForceTransform;
  2272. iceAvgThrustPosition = iceForceTransform;
  2273.  
  2274. #region find cylinder exhaust ports
  2275.  
  2276. try
  2277. {
  2278.  
  2279. exh = base.part.FindModelTransforms("exh");
  2280. }
  2281. catch
  2282. {
  2283. print("Problem locating exhausts");
  2284. }
  2285.  
  2286. if (exh.Count() > 0)
  2287. {
  2288. print("Found " + exh.Count() + " Exhaust Ports");
  2289. }
  2290.  
  2291. #endregion
  2292.  
  2293.  
  2294. #region visualFX
  2295. if (exhaustFX1 == null || exhaustFX1.activeInHierarchy == false)
  2296. {
  2297.  
  2298. try
  2299. {
  2300.  
  2301. exhaustFX1 = GameDatabase.Instance.GetModel("IDiCEr1/Effects/ExhaustFX/model");
  2302. }
  2303. catch
  2304. {
  2305. print("Problem locating exhFX");
  2306. }
  2307.  
  2308. if (exhaustFX1 != null)
  2309. {
  2310.  
  2311. exhaustFX1.SetActive(false);
  2312. exhaustFX1.transform.position = this.part.transform.position;
  2313.  
  2314. exhaustFX1.transform.parent = this.part.transform;
  2315. exhaustFX1.gameObject.layer = 0;
  2316.  
  2317. }
  2318.  
  2319. }
  2320.  
  2321. oilBurningFX = (GameObject)GameObject.Instantiate(UnityEngine.Resources.Load("Effects/fx_smokeTrail_medium"));
  2322. oilBurningFX.particleEmitter.emit = false;
  2323. oilBurningFX.transform.parent = this.part.transform;
  2324. oilBurningFX.transform.localPosition = new Vector3(0, 0, 1.25f);
  2325. oilBurningFX.transform.localRotation = this.part.transform.rotation;
  2326. oilBurningFX.particleEmitter.useWorldSpace = false;
  2327. oilBurningFX.particleEmitter.minSize = 0.85f;
  2328. oilBurningFX.particleEmitter.maxSize = 1.3f;
  2329. oilBurningFX.particleEmitter.localVelocity = new Vector3(0, 0, 2f);
  2330. oilBurningFX.particleEmitter.minEnergy = 0.35f;
  2331. oilBurningFX.particleEmitter.maxEnergy = 0.65f;
  2332. oilBurningFX.particleEmitter.minEmission = 120f;
  2333.  
  2334. oilBurningFX.particleEmitter.angularVelocity = 0.0f;
  2335. oilBurningFX.particleEmitter.rndRotation = false;
  2336. oilBurningFX.particleEmitter.rndAngularVelocity = 0f;
  2337. oilBurningFX.particleEmitter.rndVelocity = new Vector3(0, 0, 0);
  2338. lightOne = oilBurningFX.AddComponent<Light>();
  2339. lightOne.color = Color.red;
  2340. lightOne.type = LightType.Point;
  2341. lightOne.range = 1.25f;
  2342. lightOne.enabled = false;
  2343.  
  2344.  
  2345. oilBurnTrailFX = (GameObject)GameObject.Instantiate(UnityEngine.Resources.Load("Effects/fx_smokeTrail_light"));
  2346. oilBurnTrailFX.particleEmitter.emit = false;
  2347. oilBurnTrailFX.transform.parent = propellerLocation;
  2348. oilBurnTrailFX.transform.localPosition = new Vector3(0, 0, 0.2f);
  2349. oilBurnTrailFX.transform.localRotation = propellerLocation.rotation;
  2350. oilBurnTrailFX.particleEmitter.useWorldSpace = true;
  2351. oilBurnTrailFX.particleEmitter.minSize = 1f;
  2352. oilBurnTrailFX.particleEmitter.maxSize = 6f;
  2353. oilBurnTrailFX.particleEmitter.localVelocity = new Vector3(0, 0, 1.5f);
  2354. oilBurnTrailFX.particleEmitter.maxEnergy = 10f;
  2355. oilBurnTrailFX.particleEmitter.minEmission = 3000f;
  2356. oilBurnTrailFX.particleEmitter.angularVelocity = 0.01f;
  2357. oilBurnTrailFX.particleEmitter.rndRotation = false;
  2358.  
  2359.  
  2360.  
  2361. #endregion
  2362. #region Sound FX
  2363. soundDrone.audio = gameObject.AddComponent<AudioSource>();
  2364. soundGroup.audio = gameObject.AddComponent<AudioSource>();
  2365. soundStart.audio = gameObject.AddComponent<AudioSource>();
  2366. soundFail.audio = gameObject.AddComponent<AudioSource>();
  2367. soundSuperC.audio = gameObject.AddComponent<AudioSource>();
  2368. soundBackF.audio = gameObject.AddComponent<AudioSource>();
  2369.  
  2370.  
  2371. if (soundDrone.audio != null)
  2372. {
  2373.  
  2374. soundDrone.audio.volume = GameSettings.SHIP_VOLUME;
  2375. soundDrone.audio.rolloffMode = AudioRolloffMode.Linear;
  2376. soundDrone.audio.dopplerLevel = 0f;
  2377. soundDrone.audio.panLevel = 1f;
  2378.  
  2379. soundDrone.audio.clip = GameDatabase.Instance.GetAudioClip(sfxEngineDrone);
  2380. soundDrone.audio.loop = true;
  2381. soundDrone.audio.playOnAwake = false;
  2382. soundDrone.audio.priority = 1;
  2383. }
  2384. if (soundGroup.audio != null)
  2385. {
  2386.  
  2387. soundGroup.audio.volume = GameSettings.SHIP_VOLUME * 0.25f;
  2388. soundGroup.audio.rolloffMode = AudioRolloffMode.Linear;
  2389. soundGroup.audio.dopplerLevel = 0f;
  2390. soundGroup.audio.panLevel = 1f;
  2391.  
  2392. soundGroup.audio.clip = GameDatabase.Instance.GetAudioClip(sfxEngineGroup);
  2393. soundGroup.audio.loop = true;
  2394. soundGroup.audio.playOnAwake = false;
  2395. soundGroup.audio.priority = 2;
  2396. }
  2397. if (soundStart.audio != null)
  2398. {
  2399. soundStart.audio.volume = GameSettings.SHIP_VOLUME;
  2400. soundStart.audio.rolloffMode = AudioRolloffMode.Linear;
  2401. soundStart.audio.dopplerLevel = 0f;
  2402. soundStart.audio.panLevel = 1f;
  2403. soundStart.audio.clip = GameDatabase.Instance.GetAudioClip(sfxEngineStart);
  2404. soundStart.audio.loop = false;
  2405. soundStart.audio.playOnAwake = false;
  2406. soundStart.audio.priority = 3;
  2407. }
  2408. if (soundFail.audio != null)
  2409. {
  2410. soundFail.audio.volume = GameSettings.SHIP_VOLUME * 0.025f;
  2411. soundFail.audio.rolloffMode = AudioRolloffMode.Linear;
  2412. soundFail.audio.dopplerLevel = 0f;
  2413. soundFail.audio.panLevel = 1f;
  2414. soundFail.audio.clip = GameDatabase.Instance.GetAudioClip(sfxFail);
  2415. soundFail.audio.loop = true;
  2416. soundFail.audio.playOnAwake = false;
  2417. soundFail.audio.priority = 5;
  2418. }
  2419. if (soundSuperC.audio != null)
  2420. {
  2421.  
  2422. soundSuperC.audio.volume = GameSettings.SHIP_VOLUME;
  2423. soundSuperC.audio.rolloffMode = AudioRolloffMode.Linear;
  2424. soundSuperC.audio.dopplerLevel = 0f;
  2425. soundSuperC.audio.panLevel = 1f;
  2426.  
  2427. soundSuperC.audio.clip = GameDatabase.Instance.GetAudioClip(sfxSupercharger);
  2428. soundSuperC.audio.loop = true;
  2429. soundSuperC.audio.playOnAwake = false;
  2430. soundSuperC.audio.priority = 4;
  2431. }
  2432. if (soundBackF.audio != null)
  2433. {
  2434.  
  2435. soundBackF.audio.volume = GameSettings.SHIP_VOLUME;
  2436. soundBackF.audio.rolloffMode = AudioRolloffMode.Linear;
  2437. soundBackF.audio.dopplerLevel = 0f;
  2438. soundBackF.audio.panLevel = 1f;
  2439.  
  2440. soundBackF.audio.clip = GameDatabase.Instance.GetAudioClip(sfxEngineBackF);
  2441. soundBackF.audio.loop = false;
  2442. soundBackF.audio.playOnAwake = false;
  2443. soundBackF.audio.priority = 5;
  2444. }
  2445.  
  2446. #endregion
  2447.  
  2448. }
  2449.  
  2450.  
  2451. public void Update()
  2452. {
  2453. if (!HighLogic.LoadedSceneIsFlight) return;
  2454.  
  2455. if (this.vessel == FlightGlobals.ActiveVessel && ctrlEngine == true)
  2456. {
  2457.  
  2458. if (hasDirectOutput == true && useMultiThrottle == false && useWThrottle == true)
  2459. {
  2460. float throttlePos = FlightInputHandler.state.mainThrottle;
  2461.  
  2462. if (FlightInputHandler.state.mainThrottle < 0.1f)
  2463. {
  2464. FlightInputHandler.state.mainThrottle = throttlePos += 0.125f * Time.deltaTime;
  2465. }
  2466.  
  2467. if (Input.GetKey(KeyCode.W) && FlightInputHandler.state.mainThrottle < guiThrottle)
  2468. {
  2469. FlightInputHandler.state.mainThrottle = throttlePos += 0.125f * Time.deltaTime;
  2470. }
  2471. else if (!Input.GetKey(KeyCode.W) && FlightInputHandler.state.mainThrottle > 0.1f)
  2472. {
  2473. FlightInputHandler.state.mainThrottle = throttlePos -= 0.1f * Time.deltaTime;
  2474. }
  2475.  
  2476. if (Input.GetKey(KeyCode.S) && FlightInputHandler.state.mainThrottle > 0.1f)
  2477. {
  2478. FlightInputHandler.state.mainThrottle = throttlePos -= 0.25f * Time.deltaTime;
  2479. }
  2480.  
  2481. if (Input.GetKeyDown(KeyCode.LeftControl) && useWThrottle == true)
  2482. {
  2483. useWThrottle = false;
  2484. }
  2485.  
  2486.  
  2487. }
  2488.  
  2489. #region Toggle pitch
  2490. if (togglePitch == true && variPitch == false)
  2491. {
  2492. if (propPitch == 1f && togglePitch == true)
  2493. {
  2494. propPitch = -1f;
  2495. togglePitch = false;
  2496. pitchModifier = 1f;
  2497. }
  2498. if (propPitch == -1f && togglePitch == true)
  2499. {
  2500. propPitch = 0f;
  2501. togglePitch = false;
  2502. pitchModifier = 1f;
  2503. }
  2504. if (propPitch == 0f && togglePitch == true)
  2505. {
  2506. propPitch = 1f;
  2507. togglePitch = false;
  2508. pitchModifier = 1f;
  2509. }
  2510.  
  2511.  
  2512.  
  2513.  
  2514. }
  2515. else if(togglePitch == false && variPitch == true)
  2516. {
  2517. if (Input.GetKey(KeyCode.RightShift) && Input.GetKeyDown(KeyCode.KeypadPlus))
  2518. {
  2519. if (propPitch < 1f)
  2520. {
  2521. propPitch = propPitch + 0.1f;
  2522. pitchModifier = propPitch;
  2523. }
  2524.  
  2525.  
  2526. }
  2527. if (Input.GetKey(KeyCode.RightShift) && Input.GetKeyDown(KeyCode.KeypadMinus))
  2528. {
  2529. if (propPitch > -1f)
  2530. {
  2531. propPitch = propPitch - 0.1f;
  2532. pitchModifier = propPitch;
  2533. }
  2534.  
  2535.  
  2536. }
  2537.  
  2538. if (Input.GetKey(KeyCode.RightShift) && Input.GetKeyDown(KeyCode.KeypadDivide))
  2539. {
  2540. if (propPitch != 0f)
  2541. {
  2542. propPitch = 0f;
  2543. pitchModifier = 1f;
  2544. }
  2545.  
  2546. }
  2547.  
  2548. }
  2549.  
  2550. #endregion
  2551.  
  2552. if (Input.GetKey(KeyCode.RightShift) && Input.GetKeyDown(KeyCode.S))
  2553. {
  2554. if (starterOn == false)
  2555. {
  2556. if (starterCond >= 1f && elecOn == true && runState != "Seized" && runState != "Dead")
  2557. {
  2558. if (runState == "Off" || runState == "Stalled")
  2559. {
  2560. soundStart.audio.Play();
  2561. starterOn = true;
  2562. print("Starter Engaged!");
  2563. }
  2564. else if (runState == "Running" || runState == "Overheated" || runState == "Starting")
  2565. {
  2566. starterCond = starterCond - (UnityEngine.Random.Range(1f, 5f)); //damage the starter!
  2567. }
  2568. }
  2569. else if (starterCond < 1f || elecOn == false)
  2570. {
  2571. print("Starter must be damaged, or Electric Power is off!");
  2572. }
  2573. }
  2574. }
  2575.  
  2576. if (Input.GetKey(KeyCode.RightShift) && Input.GetKeyDown(KeyCode.F))
  2577. {
  2578. if (fuelOn == false)
  2579. {
  2580. if (sparkEff > 0f)
  2581. {
  2582. fuelOn = true;
  2583. print("Fuel System On!");
  2584.  
  2585. }
  2586. else if (sparkEff <= 0f)
  2587. {
  2588. print("Plugs are Fouled, clean them!");
  2589. }
  2590. }
  2591. else if (fuelOn == true)
  2592. {
  2593. fuelOn = false;
  2594. }
  2595.  
  2596. }
  2597.  
  2598. if (Input.GetKey(KeyCode.RightShift) && Input.GetKeyDown(KeyCode.E))
  2599. {
  2600. if (elecOn == false)
  2601. {
  2602. if (sparkEff > 0f)
  2603. {
  2604. elecOn = true;
  2605. print("Electricals On!");
  2606.  
  2607. }
  2608. else if (sparkEff <= 0f)
  2609. {
  2610. sparkEff = 0f;
  2611. elecOn = false;
  2612. print("Electrical needs fixing... cleaning time!");
  2613. }
  2614. }
  2615. else if (elecOn == true)
  2616. {
  2617. elecOn = false;
  2618. }
  2619. }
  2620. }
  2621. }
  2622.  
  2623. public void FixedUpdate()
  2624. {
  2625. if (HighLogic.LoadedSceneIsEditor)
  2626. {
  2627. if (hasDirectOutput == false)
  2628. {
  2629. Fields["useWThrottle"].guiActiveEditor = false;
  2630. }
  2631. }
  2632.  
  2633. if (!HighLogic.LoadedSceneIsFlight) return;
  2634.  
  2635. if (doItOnce == true)
  2636. {
  2637. origEngPerformance = enginePerformanceMulti;
  2638.  
  2639. doItOnce = false;
  2640. }
  2641.  
  2642. if (firstRun == true)
  2643. {
  2644. if (animatedPart != "none")
  2645. {
  2646. print("Running the animatePart ICE code");
  2647. animateTransform = part.FindModelTransform(animatedPart);
  2648. if (animateTransform != null)
  2649. {
  2650. animateDefaultTransform = new GameObject().transform;
  2651. animateDefaultTransform.localRotation = animateTransform.localRotation;
  2652. animateDefaultTransform.localPosition = animateTransform.localPosition;
  2653.  
  2654. print("animatePart found and set!");
  2655. }
  2656.  
  2657. getICEdDrive = this.vessel.FindPartModulesImplementing<IDdDrive>().FirstOrDefault();
  2658. }
  2659.  
  2660. if (hasDirectOutput == false)
  2661. {
  2662. Fields["useWThrottle"].guiActive = false;
  2663. }
  2664.  
  2665. getAllLCool = this.vessel.FindPartModulesImplementing<IDliqCool>();
  2666.  
  2667. firstRun = false;
  2668. }
  2669.  
  2670. if (dmgOutOfWhack == true)
  2671. {
  2672. persistantRunRough();
  2673.  
  2674. }
  2675.  
  2676. #region Experimental Thrust Averaging
  2677.  
  2678. actualThrustPosition.position = iceForceTransform.position;
  2679. actualThrustPosition.rotation = iceForceTransform.rotation;
  2680.  
  2681. if (useThrustAveraging == true)
  2682. {
  2683. iceAvgThrustPosition.position = Vector3.Lerp(this.vessel.transform.position, iceForceTransform.position, 0.0000000001f);
  2684.  
  2685. }
  2686.  
  2687.  
  2688. #endregion
  2689.  
  2690. #region Random Failure Call
  2691. failureTimer -= Time.deltaTime;
  2692.  
  2693. if (failureTimer <= 0 && FlightGlobals.ActiveVessel == this.vessel)
  2694. {
  2695. failureTimer = failureCooldown;
  2696.  
  2697. checkRandomFailure();
  2698. }
  2699.  
  2700. #endregion
  2701.  
  2702. if (lightOne.enabled == true)
  2703. {
  2704. int randFlicker = rndNumber.rndRoll(1, 101);
  2705. float randIntensity = (float)rndNumber.rndRoll(1, 3);
  2706.  
  2707. if (randFlicker <= 18)
  2708. {
  2709. lightOne.intensity = randIntensity;
  2710.  
  2711. }
  2712. else lightOne.intensity = 0f;
  2713. }
  2714.  
  2715.  
  2716.  
  2717. if (FlightGlobals.ActiveVessel.isEVA == true)
  2718. {
  2719. ProtoCrewMember getStats = FlightGlobals.ActiveVessel.GetVesselCrew().FirstOrDefault();
  2720. if (lastKerbalName != getStats.name) // only update stats if the kerbal isn't the same as the last kerbal we checked.
  2721. {
  2722. checkKerbal();
  2723. }
  2724. }
  2725.  
  2726. #region INSPECTION CHECK
  2727. if (fixOngoing == true && doneTime < Time.time && jobName == "inspect")
  2728. {
  2729. print("Job completed in... " + fixTime + " seconds, at" + Time.time);
  2730. fixOngoing = false;
  2731. jobName = "nil";
  2732.  
  2733. float messageDisplayTime = 10f;
  2734. int checkNumSystems = 3;
  2735. bool check1 = false;
  2736. bool check2 = false;
  2737. bool check3 = false;
  2738.  
  2739. for (int i = 0; i < checkNumSystems; i++)
  2740. {
  2741. if (i == 0) check1 = true;
  2742. if (i == 1) check2 = true;
  2743. if (i == 2) check3 = true;
  2744.  
  2745.  
  2746.  
  2747. float randomInspect = (float)rndNumber.rndDouble();
  2748. float inspectRating = 1f;
  2749. float kerbalSmart = 1f - ourKerbalsStupid;
  2750.  
  2751.  
  2752. if (randomInspect <= ((inspectRating + kerbalSmart) / 2) && check1 == true) //******************AIRFILTER
  2753. {
  2754. print("We made the inspection roll!");
  2755. if (airEff >= 0.9f) ScreenMessages.PostScreenMessage(new ScreenMessage("Air Filter looks brand new!", messageDisplayTime, ScreenMessageStyle.UPPER_CENTER));
  2756. if (airEff >= 0.5f && airEff < 0.9f) ScreenMessages.PostScreenMessage(new ScreenMessage("Air Filter is used but still good!", messageDisplayTime, ScreenMessageStyle.UPPER_CENTER));
  2757. if (airEff > 0.25f && airEff < 0.5f) ScreenMessages.PostScreenMessage(new ScreenMessage("Air Filter is dirty! I wouldn't fly around the block with that thing.", messageDisplayTime, ScreenMessageStyle.UPPER_CENTER));
  2758. if (airEff <= 0.2f) ScreenMessages.PostScreenMessage(new ScreenMessage("This is not an air filter, it's totally destroyed!", messageDisplayTime, ScreenMessageStyle.UPPER_CENTER));
  2759. check1 = false;
  2760. }
  2761. else if (randomInspect > ((inspectRating + kerbalSmart) / 2) && check1 == true)
  2762. {
  2763. print("Kerbal makes mistake doing inspection!"); // AIR filter Inspection could be right could be wrong who knows!
  2764. float randomBS = UnityEngine.Random.Range(0f, 4f);
  2765.  
  2766. if (randomBS <= 1f) ScreenMessages.PostScreenMessage(new ScreenMessage("Air Filter looks brand new!", messageDisplayTime, ScreenMessageStyle.UPPER_CENTER));
  2767. if (randomBS <= 2f && randomBS > 1f) ScreenMessages.PostScreenMessage(new ScreenMessage("Air Filter is used but still good!", messageDisplayTime, ScreenMessageStyle.UPPER_CENTER));
  2768. if (randomBS <= 3f && randomBS > 2f) ScreenMessages.PostScreenMessage(new ScreenMessage("Air Filter is dirty! I wouldn't fly around the block with that thing.", messageDisplayTime, ScreenMessageStyle.UPPER_CENTER));
  2769. if (randomBS <= 4f && randomBS > 3f) ScreenMessages.PostScreenMessage(new ScreenMessage("This is not an air filter, it's totally destroyed!", messageDisplayTime, ScreenMessageStyle.UPPER_CENTER));
  2770. check1 = false;
  2771. }
  2772.  
  2773. if (randomInspect <= ((inspectRating + kerbalSmart) / 2) && check2 == true) //*******************OIL CONDITION
  2774. {
  2775. print("We made the inspection roll!");
  2776. if (oilCond >= 0.9f) ScreenMessages.PostScreenMessage(new ScreenMessage("Oil looks great, liquid gold!", messageDisplayTime, ScreenMessageStyle.UPPER_CENTER));
  2777. if (oilCond >= 0.5f && oilCond < 0.9f) ScreenMessages.PostScreenMessage(new ScreenMessage("This oil is brown, still smells good!", messageDisplayTime, ScreenMessageStyle.UPPER_CENTER));
  2778. if (oilCond >= 0.25f && oilCond < 0.5f) ScreenMessages.PostScreenMessage(new ScreenMessage("This oil is very used, but still might last a little while longer", messageDisplayTime, ScreenMessageStyle.UPPER_CENTER));
  2779. if (oilCond > 0f && oilCond < 0.25f) ScreenMessages.PostScreenMessage(new ScreenMessage("Yuk! This oil is totally burnt, Change immediately!", messageDisplayTime, ScreenMessageStyle.UPPER_CENTER));
  2780. if (oilCond == 0f) ScreenMessages.PostScreenMessage(new ScreenMessage("The oil that is left is burned all into the engine, what a mess!", messageDisplayTime, ScreenMessageStyle.UPPER_CENTER));
  2781. check2 = false;
  2782. }
  2783. else if (randomInspect > ((inspectRating + kerbalSmart) / 2) && check2 == true)
  2784. {
  2785. print("Kerbal makes mistake doing inspection!"); // OIL INSPECTION could be right could be wrong who knows!
  2786. float randomBS = UnityEngine.Random.Range(0f, 5f);
  2787. if (runState == "Seized" || runState == "Dead") randomBS = 5f;
  2788. if (randomBS <= 1f) ScreenMessages.PostScreenMessage(new ScreenMessage("Oil looks great, liquid gold!", messageDisplayTime, ScreenMessageStyle.UPPER_CENTER));
  2789. if (randomBS <= 2f && randomBS > 1f) ScreenMessages.PostScreenMessage(new ScreenMessage("This oil is brown, still smells good!", messageDisplayTime, ScreenMessageStyle.UPPER_CENTER));
  2790. if (randomBS <= 3f && randomBS > 2f) ScreenMessages.PostScreenMessage(new ScreenMessage("This oil is very used, but still might last a little while longer", messageDisplayTime, ScreenMessageStyle.UPPER_CENTER));
  2791. if (randomBS <= 4f && randomBS > 3f) ScreenMessages.PostScreenMessage(new ScreenMessage("Yuk! This oil is totally burnt, Change immediately!", messageDisplayTime, ScreenMessageStyle.UPPER_CENTER));
  2792. if (randomBS <= 5f && randomBS > 4f) ScreenMessages.PostScreenMessage(new ScreenMessage("The oil that is left is burned all into the engine, what a mess!", messageDisplayTime, ScreenMessageStyle.UPPER_CENTER));
  2793. check2 = false;
  2794. }
  2795.  
  2796. if (randomInspect <= ((inspectRating + kerbalSmart) / 2) && check3 == true) //************************ ELECTRICAL
  2797. {
  2798. print("We made the inspection roll!");
  2799. if (sparkEff >= 0.9f) ScreenMessages.PostScreenMessage(new ScreenMessage("Electrical contacts look clean!", messageDisplayTime, ScreenMessageStyle.UPPER_CENTER));
  2800. if (sparkEff >= 0.5f && sparkEff < 0.9f) ScreenMessages.PostScreenMessage(new ScreenMessage("Electrical contacts look normal, keep an eye on it!", messageDisplayTime, ScreenMessageStyle.UPPER_CENTER));
  2801. if (sparkEff >= 0.25f && sparkEff < 0.5f) ScreenMessages.PostScreenMessage(new ScreenMessage("These Electrical systems look dirty and worn, they might last for a while", messageDisplayTime, ScreenMessageStyle.UPPER_CENTER));
  2802. if (sparkEff > 0.0f && sparkEff < 0.25f) ScreenMessages.PostScreenMessage(new ScreenMessage("Contact points are nearly gone, the whole thing looks barely functional!", messageDisplayTime, ScreenMessageStyle.UPPER_CENTER));
  2803. if (sparkEff == 0f) ScreenMessages.PostScreenMessage(new ScreenMessage("Electrical system is fried! Needs total overhaul...", messageDisplayTime, ScreenMessageStyle.UPPER_CENTER));
  2804. check3 = false;
  2805. }
  2806. else if (randomInspect > ((inspectRating + kerbalSmart) / 2) && check3 == true)
  2807. {
  2808. print("Kerbal makes mistake doing inspection!"); // could be right could be wrong who knows!
  2809. float randomBS = UnityEngine.Random.Range(0f, 5f);
  2810.  
  2811. if (randomBS <= 1f) ScreenMessages.PostScreenMessage(new ScreenMessage("Electrical contacts look clean!", messageDisplayTime, ScreenMessageStyle.UPPER_CENTER));
  2812. if (randomBS <= 2f && randomBS > 1f) ScreenMessages.PostScreenMessage(new ScreenMessage("Electrical contacts look normal, keep an eye on it!", messageDisplayTime, ScreenMessageStyle.UPPER_CENTER));
  2813. if (randomBS <= 3f && randomBS > 2f) ScreenMessages.PostScreenMessage(new ScreenMessage("These Electrical systems look dirty and worn, they might last for a while", messageDisplayTime, ScreenMessageStyle.UPPER_CENTER));
  2814. if (randomBS <= 4f && randomBS > 3f) ScreenMessages.PostScreenMessage(new ScreenMessage("Contact points are nearly gone, the whole thing looks barely functional!", messageDisplayTime, ScreenMessageStyle.UPPER_CENTER));
  2815. if (randomBS <= 5f && randomBS > 4f) ScreenMessages.PostScreenMessage(new ScreenMessage("Electrical system is fried! Needs total overhaul...", messageDisplayTime, ScreenMessageStyle.UPPER_CENTER));
  2816. check3 = false;
  2817. }
  2818.  
  2819. if (runState == "Seized") ScreenMessages.PostScreenMessage(new ScreenMessage("This engine is seized! It won't start until it's repaired.", messageDisplayTime, ScreenMessageStyle.UPPER_CENTER));
  2820. if (runState == "Dead") ScreenMessages.PostScreenMessage(new ScreenMessage("This engine is dead! It can't be fixed.", messageDisplayTime, ScreenMessageStyle.UPPER_CENTER));
  2821. }
  2822. }
  2823. #endregion
  2824.  
  2825. #region FIXING TIME CHECK & JOB COMPLETION
  2826. if (fixOngoing == true && doneTime > Time.time && (this.part.transform.position.magnitude - FlightGlobals.ActiveVessel.transform.position.magnitude) > 4f || fixOngoing == true && doneTime > Time.time && FlightGlobals.ActiveVessel.isEVA == false)
  2827. {
  2828. ScreenMessages.PostScreenMessage(new ScreenMessage("You botched the job! Please stay within 4m of the engine, do not switch away or enter a vessel.", 10f, ScreenMessageStyle.UPPER_CENTER));
  2829. fixOngoing = false;
  2830. jobName = "nil";
  2831. }
  2832.  
  2833.  
  2834. if (fixOngoing == true && doneTime < Time.time && jobName == "airfilter")
  2835. {
  2836. print("Job completed in... " + fixTime + " seconds, at" + Time.time);
  2837. ScreenMessages.PostScreenMessage(new ScreenMessage("Air filter is fixed!", 10f, ScreenMessageStyle.UPPER_CENTER));
  2838. fixOngoing = false;
  2839. jobName = "nil";
  2840.  
  2841. if (airEff < 1f)
  2842. {
  2843. airEff = (1f * (1f - ourKerbalsStupid) + 1f) * 0.5f; //the most a kerbal can restore this is directly related to how smart he is!
  2844. print("Airfilter condition is now... " + airEff);
  2845. }
  2846.  
  2847. }
  2848.  
  2849. if (fixOngoing == true && doneTime < Time.time && jobName == "electrical")
  2850. {
  2851. print("Job completed in... " + fixTime + " seconds, at" + Time.time);
  2852. ScreenMessages.PostScreenMessage(new ScreenMessage("Electrical systems look much better now!", 10f, ScreenMessageStyle.UPPER_CENTER));
  2853. fixOngoing = false;
  2854. jobName = "nil";
  2855.  
  2856. if (sparkEff < 1f)
  2857. {
  2858. sparkEff = (1f * (1f - ourKerbalsStupid) + 1f) * 0.5f;
  2859. print("Electrical System condition is now... " + sparkEff);
  2860. }
  2861.  
  2862. }
  2863.  
  2864. if (fixOngoing == true && doneTime < Time.time && jobName == "oilservice")
  2865. {
  2866.  
  2867. fixOngoing = false;
  2868. jobName = "nil";
  2869.  
  2870. if (oilCond < 100f || oilLevel < 100f || dmgOilLeak == true)
  2871. {
  2872. print("Inside the condition...");
  2873.  
  2874. List<Collider> nearestColliders = new List<Collider>(Physics.OverlapSphere(iceForceTransform.position, 40f));
  2875. foreach (Collider col in nearestColliders)
  2876. {
  2877.  
  2878. if (!col.attachedRigidbody)
  2879. {
  2880.  
  2881. continue;
  2882. }
  2883.  
  2884. Part p = col.attachedRigidbody.GetComponent<Part>();
  2885. if (!p)
  2886. {
  2887.  
  2888. continue;
  2889. }
  2890.  
  2891. print("check3");
  2892. PartResourceList resourceList = p.Resources;
  2893. foreach (PartResource resource in resourceList)
  2894. {
  2895. if (resource.resourceName == "KobilOne")
  2896. {
  2897. print("Found a part with oil!");
  2898. if (resource.amount < oilCapacity)
  2899. {
  2900. ScreenMessages.PostScreenMessage(new ScreenMessage("Oil Station has insufficient oil, can't finish this job!", 3f, ScreenMessageStyle.UPPER_CENTER));
  2901. }
  2902. else if (resource.amount >= oilCapacity)
  2903. {
  2904. if (takeOilOnce == true)
  2905. {
  2906. resource.amount = resource.amount - oilCapacity;
  2907. ScreenMessages.PostScreenMessage(new ScreenMessage("Oil is changed and seals are fixed! Note: Source has " + resource.amount + " oil remaining", 10f, ScreenMessageStyle.UPPER_CENTER));
  2908. print("Job completed in... " + fixTime + " seconds, at" + Time.time);
  2909. oilCond = 1f;
  2910. oilLevel = 100f;
  2911. dmgOilLeak = false;
  2912. dmgOutOfWhack = false;
  2913. takeOilOnce = false;
  2914. oilBurningFX.particleEmitter.emit = false;
  2915. lightOne.enabled = false;
  2916. }
  2917. }
  2918. }
  2919.  
  2920. }
  2921.  
  2922.  
  2923.  
  2924. }
  2925.  
  2926. }
  2927. else print("No Condition met... " + oilCond);
  2928.  
  2929. }
  2930.  
  2931. if (fixOngoing == true && doneTime < Time.time && jobName == "engine")
  2932. {
  2933. if (runState == "Seized")
  2934. {
  2935. print("Inside the condition...");
  2936.  
  2937. List<Collider> nearestColliders = new List<Collider>(Physics.OverlapSphere(iceForceTransform.position, 40f));
  2938. foreach (Collider col in nearestColliders)
  2939. {
  2940.  
  2941. if (!col.attachedRigidbody)
  2942. {
  2943.  
  2944. continue;
  2945. }
  2946.  
  2947. Part p = col.attachedRigidbody.GetComponent<Part>();
  2948. if (!p)
  2949. {
  2950.  
  2951. continue;
  2952. }
  2953.  
  2954.  
  2955. PartResourceList resourceList = p.Resources;
  2956. foreach (PartResource resource in resourceList)
  2957. {
  2958. if (resource.resourceName == "SpareParts")
  2959. {
  2960. print("Found a part with SpareParts!");
  2961. if (resource.amount < 0.25)
  2962. {
  2963. ScreenMessages.PostScreenMessage(new ScreenMessage("Can't find enough SpareParts within 40m, can't finish this job!", 3f, ScreenMessageStyle.UPPER_CENTER));
  2964. }
  2965. else if (resource.amount >= 0.25)
  2966. {
  2967. if (takeOilOnce == true)
  2968. {
  2969. resource.amount = resource.amount - 0.25;
  2970. print("Job completed in... " + fixTime + " seconds, at" + Time.time);
  2971. ScreenMessages.PostScreenMessage(new ScreenMessage("Engine is restored, take it easy next time!", 10f, ScreenMessageStyle.UPPER_CENTER));
  2972. fixOngoing = false;
  2973. jobName = "nil";
  2974. takeOilOnce = false;
  2975. runState = "Off";
  2976.  
  2977. }
  2978. }
  2979. }
  2980. }
  2981. }
  2982. }
  2983. ScreenMessages.PostScreenMessage(new ScreenMessage("Engine is not damaged, do an oil change!", 5f, ScreenMessageStyle.UPPER_CENTER));
  2984. fixOngoing = false;
  2985. jobName = "nil";
  2986. takeOilOnce = false;
  2987.  
  2988.  
  2989. }
  2990. #endregion
  2991.  
  2992. if (dmgOilLeak == true) oilLeak();
  2993.  
  2994.  
  2995. soundFail.audio.volume = (0.025f * GameSettings.SHIP_VOLUME);
  2996.  
  2997. #region reset animated part if there is one...
  2998. animateTimer -= Time.deltaTime;
  2999.  
  3000. if (animateTimer <= 0)
  3001. {
  3002. animateTimer = (((1f - throttleActual) + 0.01f) * 0.1f);
  3003.  
  3004.  
  3005. if (animateTransform != null)
  3006. {
  3007. animateTransform.localRotation = animateDefaultTransform.localRotation;
  3008. animateTransform.localPosition = animateDefaultTransform.localPosition;
  3009. }
  3010. }
  3011. #endregion
  3012.  
  3013. if (checkOnce == true)
  3014. {
  3015. oilTemp = FlightGlobals.getExternalTemperature((float)this.vessel.altitude, this.vessel.mainBody);
  3016. engTemp = FlightGlobals.getExternalTemperature((float)this.vessel.altitude, this.vessel.mainBody);
  3017. checkOnce = false;
  3018. }
  3019.  
  3020. if (airCooled == true)
  3021. {
  3022. if (FlightGlobals.ActiveVessel.rb_velocity.magnitude >= 60f)
  3023. {
  3024. if (oilTemp > 160f)
  3025. {
  3026. coolingEff = 0.08f;
  3027. }
  3028. else coolingEff = 0.018f;
  3029. }
  3030. else if (FlightGlobals.ActiveVessel.rb_velocity.magnitude >= 20f)
  3031. {
  3032. if (oilTemp > 160f)
  3033. {
  3034. coolingEff = 0.065f;
  3035. }
  3036. else coolingEff = 0.0125f;
  3037. }
  3038. else if (FlightGlobals.ActiveVessel.rb_velocity.magnitude < 20f)
  3039. {
  3040. if (oilTemp > 160f)
  3041. {
  3042. coolingEff = 0.025f;
  3043. }
  3044. else coolingEff = 0.001f;
  3045. }
  3046. }
  3047. else
  3048. {
  3049. coolingEff = 0.0f; //make air cooling useless
  3050.  
  3051. if (getAllLCool != null && getAllLCool.Count() > 0)
  3052. {
  3053. coolantTemp = engTemp;
  3054. this.part.temperature = coolantTemp;
  3055.  
  3056. int[] allRads = new int[getAllLCool.Count];
  3057.  
  3058. for (int i = 0; i < allRads.Length; i++)
  3059. {
  3060. getAllLCool[i].inputTemp = coolantTemp;
  3061.  
  3062. if (getAllLCool[i].flapPos != 0f)
  3063. {
  3064. float percentAffected = (getAllLCool[i].flowRate / this.coolantCapacity) * 100f;
  3065. float cooledPortionTemp = (((this.vessel.rigidbody.velocity.magnitude * getAllLCool[i].flapPos) * getAllLCool[i].radSize) * 0.01f) * coolantTemp;
  3066. if (cooledPortionTemp == 0f) cooledPortionTemp = 1f; //0 meaning no cooling is done therefore multiply to cool by 1 to keep temp unchanged/uncooled.
  3067. float finalReturnTemp = (coolantTemp * ((100f - percentAffected) * 0.01f)) + (cooledPortionTemp * (percentAffected * 0.01f));
  3068. engTemp = finalReturnTemp;
  3069. coolantTemp = finalReturnTemp;
  3070.  
  3071. }
  3072. }
  3073.  
  3074.  
  3075. }
  3076.  
  3077.  
  3078.  
  3079. }
  3080.  
  3081. if (runState == "Off")
  3082. {
  3083. soundDrone.audio.Stop();
  3084. soundGroup.audio.Stop();
  3085. soundFail.audio.Stop();
  3086. soundSuperC.audio.Stop();
  3087. currentRPM = Mathf.Lerp(currentRPM, 0f, 1f);
  3088.  
  3089. if (engTemp > FlightGlobals.getExternalTemperature((float)this.vessel.altitude, this.vessel.mainBody))
  3090. {
  3091. engTemp = engTemp - coolingEff;
  3092. oilTemp = engTemp;
  3093. }
  3094.  
  3095. if (exhaustFX1 != null)
  3096. {
  3097. exhaustFX1.SetActive(false);
  3098. }
  3099.  
  3100. }
  3101.  
  3102. if (runState == "Off" && fuelOn == true && elecOn == true && starterOn == true && runState != "Seized" && runState != "Dead" || runState == "Stalled" && fuelOn == true && elecOn == true && starterOn == true && runState != "Seized" && runState != "Dead")
  3103. {
  3104. print("Starting Engine!");
  3105. runState = "Starting";
  3106. }
  3107.  
  3108. if (runState == "Starting" && fuelOn == true && elecOn == true && starterOn == true && runState != "Seized" && runState != "Dead")
  3109. {
  3110. starterOn = false;
  3111. currentRPM = engineIdleSpeed;
  3112.  
  3113. createBackfire();
  3114.  
  3115. float tempStartMod = (oilMaxTemp * 0.5f) / oilTemp ;
  3116. if (tempStartMod > 25f) tempStartMod = 25f;
  3117. if (tempStartMod < 0f) tempStartMod = 0f;
  3118. float chanceToStart = (((100f - tempStartMod) * sparkEff) * airEff);//Try to start... airfilter & spark condition plays a role as well as how warm the engine oil is!
  3119. float randStartRoll = (float)rndNumber.rndRoll(1, 101);
  3120.  
  3121. if (randStartRoll < chanceToStart)
  3122. {
  3123. print("Engine Started!");
  3124. runState = "Running";
  3125. currentRPM = Mathf.Lerp(currentRPM, (throttleActual * (((engineRedline * Math.Abs(pitchModifier)) * 1.05f))) + (FlightGlobals.ActiveVessel.rb_velocity.magnitude * 3.25f), 0.3f); // begin the engine turning!!!
  3126. }
  3127. else runState = "Off";
  3128. }
  3129.  
  3130. #region Engine is Running or Running Overheated
  3131. if (runState == "Running" && fuelOn == true && elecOn == true && starterOn == false || runState == "Overheated" && fuelOn == true && elecOn == true && starterOn == false)
  3132. {
  3133.  
  3134.  
  3135. checkThrottle();
  3136.  
  3137. #region Supercharger Operations ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  3138.  
  3139. if (isSupercharged == true)
  3140. {
  3141. if (this.vessel.altitude < twoStageTripAlt || isTwoStageAuto == false)
  3142. {
  3143. currentBoostMulti = boostLowMultiplier;
  3144. if (soundSuperC.audio.isPlaying == false)
  3145. {
  3146. soundSuperC.audio.Play();
  3147. }
  3148. soundSuperC.audio.volume = (((boostLowMultiplier - 1f) * 1.35f) * GameSettings.SHIP_VOLUME) * throttleActual;
  3149.  
  3150. //print("Stage one Active");
  3151. }
  3152. else if (this.vessel.altitude > twoStageTripAlt && isTwoStageAuto == true)
  3153. {
  3154. currentBoostMulti = boostHighMultiplier;
  3155. if (soundSuperC.audio.isPlaying == false)
  3156. {
  3157. soundSuperC.audio.Play();
  3158. }
  3159. soundSuperC.audio.volume = (((boostHighMultiplier - 1f) * 1.4f) * GameSettings.SHIP_VOLUME) * throttleActual;
  3160.  
  3161. //print("Stage two Active");
  3162. }
  3163.  
  3164. }
  3165. else if (isSupercharged == false) currentBoostMulti = 1f; // no supercharger - no effect.
  3166.  
  3167. actualAirDensity = (float)this.vessel.atmDensity * currentBoostMulti;
  3168. if (actualAirDensity > 1f) actualAirDensity = 1f;
  3169.  
  3170.  
  3171. #endregion
  3172.  
  3173. #region Sound Event Code for RUNNING state.
  3174. if (runState == "Running" || runState == "Overheated")
  3175. {
  3176. if (soundDrone.audio.isPlaying == false)
  3177. {
  3178. soundDrone.audio.Play();
  3179.  
  3180. if (soundGroup.audio.isPlaying == true)
  3181. {
  3182. soundGroup.audio.Stop();
  3183. }
  3184.  
  3185. }
  3186. soundDrone.audio.volume = (1f * GameSettings.SHIP_VOLUME) * throttleActual;
  3187. soundGroup.audio.volume = (0.25f * GameSettings.SHIP_VOLUME) * throttleActual;
  3188.  
  3189.  
  3190. if (hasDirectOutput == true && getICEdDrive!= null)
  3191. {
  3192. soundDrone.audio.pitch = ((getICEdDrive.rpmOutput + engineIdleSpeed) * 1f) / (engineRedline * 0.1f);
  3193. }
  3194. else
  3195. {
  3196. soundDrone.audio.pitch = ((((currentRPM * 0.5f) + ((float)FlightGlobals.ActiveVessel.rb_velocity.magnitude * 5f)) * 0.8f) / (engineRedline * 1.025f)) + 0.3f;
  3197. if (soundDrone.audio.pitch > 4f) soundDrone.audio.pitch = 4f;
  3198.  
  3199. }
  3200.  
  3201.  
  3202. }
  3203.  
  3204. #endregion
  3205.  
  3206. float degPerSec = currentRPM * 6f;
  3207.  
  3208. ignitionTimer -= Time.deltaTime;
  3209.  
  3210. if (ignitionTimer <= 0)
  3211. {
  3212. ignitionTimer = ignCooldown;
  3213.  
  3214. if(madeCharge == true) madeCharge = false;
  3215.  
  3216.  
  3217. cylStats[] engineID = new cylStats[numOfCyls];
  3218. for (int i = 0; i < engineID.Length; i++)
  3219. {
  3220. engineID[i] = new cylStats();
  3221. engineID[i].iceCylNum = i;
  3222.  
  3223. engineID[i].cylForceIdeal = (engineDisplacement * enginePerformanceMulti) / numOfCyls;
  3224. engineID[i].addHeat = engineID[i].cylForceIdeal * 0.00075f;
  3225. engineID[i].powerArcOn = (360 / numOfCyls) * i;
  3226. engineID[i].powerArcOff = engineID[i].powerArcOn + camTime;
  3227. if (engineID[i].powerArcOff > 360) engineID[i].powerArcOff = (engineID[i].powerArcOff - 360);
  3228. engineID[i].useAirRate = ((((engineDisplacement * 61.0237f) * currentRPM) * ((1f - actualAirDensity) + 1f)) / 3456f) * 0.000471947443f;
  3229. engineID[i].useFuelRate = (engineID[i].useAirRate * actualAirDensity) * fuelAirMix;
  3230.  
  3231.  
  3232. engTemp += (engineID[i].addHeat * engineHeatup * ((throttleActual * 0.25f) + 1f)); // use engine reliable - heat buildup in weak engines
  3233. oilTemp = engTemp;
  3234.  
  3235.  
  3236. if (atRotation > engineID[i].powerArcOn && atRotation < engineID[i].powerArcOff && lastCylToFire != engineID[i].iceCylNum)//don't fire if it's not in it's firing location and don't fire if it's the same cylinder as last time.
  3237. {
  3238. #region Use Resources
  3239. double resourceConsumed = (double)Mathf.Abs(engineID[i].useFuelRate) * (double)TimeWarp.deltaTime;
  3240. if (!CheatOptions.InfiniteFuel)
  3241. {
  3242.  
  3243. double receivedResource = base.part.RequestResource(resourceType, resourceConsumed);
  3244.  
  3245. if (receivedResource >= resourceConsumed - 0.0001d)
  3246. {
  3247. sparkEff = sparkEff - ((float)receivedResource + wearRate) * 0.00015f; // the more the fuel gets ignited in the engine the quicker the electrics get dirty.
  3248.  
  3249. }
  3250. else if (receivedResource < resourceConsumed)
  3251. {
  3252.  
  3253. print("Out of Fuel/Fuel Problem");
  3254. runState = "Stalled";
  3255. }
  3256.  
  3257. double airConsumed = (double)Mathf.Abs(engineID[i].useAirRate * 25f) * (double)TimeWarp.deltaTime;
  3258. double receivedAir = base.part.RequestResource("IntakeAir", airConsumed);
  3259.  
  3260. if (receivedAir >= airConsumed - 0.001d)
  3261. {
  3262. float tuneModifier = 0.000015f;
  3263. if (FlightGlobals.ActiveVessel.heightFromTerrain < 500.0d) tuneModifier = 0.000015f; // filter gets dirtier closer to the ground
  3264. if (FlightGlobals.ActiveVessel.heightFromTerrain > 500.0d) tuneModifier = 0.0000035f;
  3265.  
  3266. airEff = airEff - ((float)receivedAir + wearRate) * tuneModifier; // the more air that passes the filter the quicker it gets dirty.
  3267.  
  3268. if (airEff <= 0.2f)
  3269. {
  3270. print("Air Filter Jammed! Clean Filter");
  3271. runState = "Stalled";
  3272.  
  3273. createBackfire();
  3274. }
  3275.  
  3276. }
  3277. else if (receivedAir < airConsumed)
  3278. {
  3279.  
  3280. print("Out of Oxygen!");
  3281. runState = "Stalled";
  3282.  
  3283. createBackfire();
  3284. }
  3285.  
  3286. double elecConsumed = wearRate;
  3287.  
  3288. double receivedElec = base.part.RequestResource("ElectricCharge", elecConsumed);
  3289.  
  3290.  
  3291. }
  3292. #endregion
  3293.  
  3294. #region Prop Power and Direction
  3295. if (propPitch > 0f && propPitch < 1f)
  3296. {
  3297. thrustDirection = -iceForceTransform.forward;
  3298. propScalePower = (1f - propPitch) + 1f;
  3299.  
  3300. }
  3301. else if (propPitch == 1f)
  3302. {
  3303. thrustDirection = -iceForceTransform.forward;
  3304. propScalePower = 1f;
  3305.  
  3306. }
  3307. else if (propPitch < 0f && propPitch > -1f)
  3308. {
  3309. thrustDirection = iceForceTransform.forward;
  3310. propScalePower = (1f - Math.Abs(propPitch)) + 1f;
  3311. }
  3312. else if (propPitch == -1f)
  3313. {
  3314. thrustDirection = iceForceTransform.forward;
  3315. propScalePower = 1f;
  3316. }
  3317. else if (propPitch == 0)
  3318. {
  3319. propScalePower = 0f;
  3320. }
  3321. #endregion
  3322.  
  3323. if (useThrustAveraging == false)
  3324. {
  3325. base.rigidbody.AddForceAtPosition(thrustDirection * (((((((engineID[i].cylForceIdeal * sparkEff) * airEff) * throttleActual) * propScalePower) * coldLoss) * actualAirDensity) * currentBoostMulti), actualThrustPosition.position); // changed from iceForceTransform...
  3326. }
  3327. if (useThrustAveraging == true)
  3328. {
  3329. base.rigidbody.AddForceAtPosition(thrustDirection * (((((((engineID[i].cylForceIdeal * sparkEff) * airEff) * throttleActual) * propScalePower) * coldLoss) * actualAirDensity) * currentBoostMulti), iceAvgThrustPosition.position); // changed from iceForceTransform...
  3330. }
  3331.  
  3332. if (exhaustFX1 != null && exh[engineID[i].iceCylNum] != null)
  3333. {
  3334.  
  3335. exhaustFX1.SetActive(true);
  3336. exhaustFX1.transform.position = exh[engineID[i].iceCylNum].position;
  3337. exhaustFX1.transform.localRotation = exh[engineID[i].iceCylNum].localRotation;
  3338. }
  3339.  
  3340. #region Engine Idling Sound
  3341. if (soundGroup.audio.isPlaying == false && runState == "Running" || soundGroup.audio.isPlaying == false && runState == "Overheated")
  3342. {
  3343. soundGroup.audio.volume = (0.25f * GameSettings.SHIP_VOLUME);
  3344. soundGroup.audio.Play();
  3345.  
  3346. }
  3347. #endregion
  3348.  
  3349. lastCylForce = engineID[i].cylForceIdeal;
  3350. lastCylToFire = engineID[i].iceCylNum;
  3351.  
  3352.  
  3353. #region CarbIce *********************************++++++++++++++++
  3354.  
  3355. float carbHeated = 0f;
  3356. if (carbHeat == true) carbHeated = oilTemp * 0.5f;
  3357.  
  3358. carbTemp = (FlightGlobals.getExternalTemperature((float)this.vessel.altitude, this.vessel.mainBody) + carbHeated);
  3359. if (carbTemp < 2.78f && carbTemp >= 0.0f)
  3360. {
  3361. carbIce -= 0.0005f;
  3362. if (carbIce < 0.5f) carbIce = 0.5f;
  3363. }
  3364. else carbIce += 0.00001f; //Shouldn't de-ice itself without carb heat applied.
  3365.  
  3366. if (carbHeat == true) carbIce += 0.00004f; // add this extra de-icing.
  3367. if (carbIce > 1f) carbIce = 1f;
  3368.  
  3369.  
  3370. #endregion
  3371.  
  3372.  
  3373. #region generator ****************************************
  3374.  
  3375. if (madeCharge == false) // just charge this vessels batteries
  3376. {
  3377. foreach (Part aPart in FlightGlobals.ActiveVessel.Parts)
  3378. {
  3379. PartResourceList resourceList = aPart.Resources;
  3380. foreach (PartResource resource in resourceList)
  3381. {
  3382. if (resource.resourceName == "ElectricCharge" && madeCharge == false)
  3383. {
  3384.  
  3385. double chargeRate = (((float)engineDisplacement * 0.0025) * throttleActual) * (double)TimeWarp.deltaTime;
  3386. if (remoteCharger == true) chargeRate = chargeRate * 7000.0;
  3387. double receivedResource = base.part.RequestResource("ElectricCharge", -chargeRate);
  3388.  
  3389. if (remoteCharger == false) madeCharge = true;
  3390. #region RemoteCharger Only ********
  3391. if (remoteCharger == true && madeCharge == false)
  3392. {
  3393. if (animateTransform != null)
  3394. {
  3395. animateTransform.localRotation = animateDefaultTransform.localRotation;
  3396. animateTransform.Rotate(Vector3.forward * ((float)rndNumber.rndDouble() * throttleActual));
  3397. animateTransform.Rotate(Vector3.left * ((float)rndNumber.rndDouble() * throttleActual));
  3398. animateTransform.Rotate(Vector3.up * ((float)rndNumber.rndDouble() * throttleActual));
  3399. animateTransform.localPosition = new Vector3(animateDefaultTransform.localPosition.x, animateDefaultTransform.localPosition.y * 1.005f, animateDefaultTransform.localPosition.z);
  3400. }
  3401.  
  3402. foreach (Vessel v in FlightGlobals.Vessels)
  3403. {
  3404. if (Vector3.Distance(v.transform.position, this.transform.position) < 40f)
  3405. {
  3406. foreach (Part rPart in v.Parts)
  3407. {
  3408. PartResourceList rresourceList = aPart.Resources;
  3409. foreach (PartResource rresource in resourceList)
  3410. {
  3411. if (resource.resourceName == "ElectricCharge" && madeCharge == false)
  3412. {
  3413. resource.amount = resource.amount + (0.3d * throttleActual) * (double)TimeWarp.deltaTime;
  3414.  
  3415. madeCharge = true;
  3416. }
  3417. }
  3418. }
  3419.  
  3420. }
  3421. }
  3422.  
  3423. }
  3424. #endregion
  3425. }
  3426. }
  3427. }
  3428.  
  3429. }
  3430.  
  3431. #endregion
  3432.  
  3433. }
  3434. else
  3435. {
  3436. if (useThrustAveraging == false)
  3437. {
  3438. base.rigidbody.AddForceAtPosition(thrustDirection * ((((((((engineID[i].cylForceIdeal * 0.15f) * sparkEff) * airEff) * throttleActual) * propScalePower) * coldLoss) * actualAirDensity) * currentBoostMulti), actualThrustPosition.position); // changed from iceForceTransform...
  3439. }
  3440. if (useThrustAveraging == true)
  3441. {
  3442. base.rigidbody.AddForceAtPosition(thrustDirection * ((((((((engineID[i].cylForceIdeal * 0.15f) * sparkEff) * airEff) * throttleActual) * propScalePower) * coldLoss) * actualAirDensity) * currentBoostMulti), iceAvgThrustPosition.position); // changed from iceForceTransform...
  3443. }
  3444.  
  3445. }
  3446.  
  3447. atRotation = atRotation + (int)(degPerSec * 0.001f);
  3448. if (atRotation > 360) atRotation = (atRotation - 360);
  3449. if (currentRPM >= engineIdleSpeed)
  3450. {
  3451. currentRPM = Mathf.Lerp(currentRPM, (throttleActual * (((engineRedline * Math.Abs(pitchModifier)) * 1.05f))) + (FlightGlobals.ActiveVessel.rb_velocity.magnitude * 3.25f), 0.3f);
  3452. #region Gearbox effect for Direct Drive only!!! ********************************
  3453. if (hasDirectOutput == true)
  3454. {
  3455. if (animateTransform != null)
  3456. {
  3457. animateTransform.localRotation = animateDefaultTransform.localRotation;
  3458. animateTransform.Rotate(Vector3.forward * ((float)rndNumber.rndDouble() * throttleActual));
  3459. animateTransform.Rotate(Vector3.left * ((float)rndNumber.rndDouble() * throttleActual));
  3460. animateTransform.Rotate(Vector3.up * ((float)rndNumber.rndDouble() * throttleActual));
  3461. animateTransform.localPosition = new Vector3(animateDefaultTransform.localPosition.x, animateDefaultTransform.localPosition.y * 1.005f, animateDefaultTransform.localPosition.z);
  3462. }
  3463.  
  3464. currentRPM = Mathf.Lerp(currentRPM, (throttleActual * ((engineRedline * 1.05f))) + (FlightGlobals.ActiveVessel.rb_velocity.magnitude * 3.25f), 0.3f);
  3465. }
  3466. #endregion
  3467. }
  3468. if (currentRPM < engineIdleSpeed) // at the lowest throttle setting the engine slows to idle speed.
  3469. {
  3470. currentRPM = Mathf.Lerp(currentRPM, ((throttleActual + 0.03f) * (((engineRedline * Math.Abs(pitchModifier)) * 1.05f))) + (FlightGlobals.ActiveVessel.rb_velocity.magnitude * 3.25f), 0.3f);
  3471.  
  3472. float randomStallCheck = rndNumber.rndRoll(1, 1001);
  3473. if(randomStallCheck < 5f)
  3474. {
  3475. runState = "Stalled";
  3476. //insert puttering sound later.
  3477. }
  3478. }
  3479.  
  3480. }
  3481.  
  3482.  
  3483.  
  3484. }
  3485.  
  3486. }
  3487. #endregion
  3488.  
  3489. if (elecOn == false || fuelOn == false)
  3490. {
  3491. if (runState == "Running" || runState == "Overheated")
  3492. {
  3493. runState = "Off";
  3494. currentRPM = Mathf.Lerp(currentRPM, 0f, 1f);
  3495. soundSuperC.audio.Stop();
  3496. soundDrone.audio.Stop();
  3497. soundGroup.audio.Stop();
  3498. soundFail.audio.Stop();
  3499.  
  3500. oilBurningFX.particleEmitter.emit = false;
  3501. lightOne.enabled = false;
  3502. oilBurnTrailFX.particleEmitter.emit = false;
  3503.  
  3504. if (engTemp > FlightGlobals.getExternalTemperature((float)this.vessel.altitude, this.vessel.mainBody))
  3505. {
  3506. engTemp = engTemp - coolingEff;
  3507. oilTemp = engTemp;
  3508. }
  3509. }
  3510. }
  3511. #region Cooling with Airflow on Air Cooled engines
  3512. if (runState == "Running" || runState == "Overheated")
  3513. {
  3514. if (currentRPM > engineRedline && oilLevel > 50f) // normal overheat
  3515. {
  3516. this.part.SetHighlightColor(Color.red);
  3517. this.part.SetHighlight(true);
  3518. engTemp = engTemp * (overHeatMod * 0.9884f);
  3519. oilTemp = Mathf.Lerp(oilTemp, engTemp, 1f);
  3520. }
  3521. else if (currentRPM > engineRedline && oilLevel < 50f) // worse condition
  3522. {
  3523. this.part.SetHighlightColor(Color.red);
  3524. this.part.SetHighlight(true);
  3525. engTemp = engTemp * (overHeatMod * 0.9885f + (wearRate * 10f));
  3526. oilTemp = Mathf.Lerp(oilTemp, engTemp, 1f);
  3527. }
  3528. else if (currentRPM < engineRedline && oilLevel > 50f) // best condition
  3529. {
  3530. this.part.SetHighlightColor(Color.clear);
  3531. this.part.SetHighlight(false);
  3532. if (engTemp > FlightGlobals.getExternalTemperature((float)this.vessel.altitude, this.vessel.mainBody))
  3533. {
  3534. engTemp = engTemp - coolingEff;
  3535. oilTemp = engTemp;
  3536. }
  3537. }
  3538. else if (currentRPM < engineRedline && oilLevel < 50f) // not ideal
  3539. {
  3540. this.part.SetHighlightColor(Color.clear);
  3541. this.part.SetHighlight(false);
  3542. if (engTemp > FlightGlobals.getExternalTemperature((float)this.vessel.altitude, this.vessel.mainBody))
  3543. {
  3544. engTemp = engTemp - (coolingEff * 0.9f);
  3545. oilTemp = engTemp;
  3546. }
  3547. }
  3548. #endregion
  3549.  
  3550.  
  3551. }
  3552.  
  3553. if (oilTemp < 0f) oilTemp = 0f;
  3554. if (engTemp < 0f) engTemp = 0f;
  3555.  
  3556. if (engTemp > oilMaxTemp * 1.2f) engTemp = oilMaxTemp * 1.2f;
  3557.  
  3558.  
  3559. if (engTemp > maxEngTemp && runState == "Running" || engTemp > maxEngTemp && runState == "Overheated")
  3560. {
  3561.  
  3562.  
  3563. if(oilTemp > oilMaxTemp)
  3564. {
  3565. if (oilCond > 0f)
  3566. {
  3567. oilCond = (oilCond - ((oilTemp - oilMaxTemp) * wearRate));
  3568. if (oilCond < 0f) oilCond = 0f;
  3569. runState = "Overheated";
  3570. }
  3571.  
  3572.  
  3573. if (oilCond <= 0f)
  3574. {
  3575.  
  3576. if (oilLevel > 0f)
  3577. {
  3578. if(soundFail.audio.isPlaying == false) soundFail.audio.Play();
  3579. soundFail.audio.volume = 0.025f;
  3580. oilBurningFX.particleEmitter.emit = true;
  3581. lightOne.enabled = true;
  3582. oilBurnTrailFX.particleEmitter.emit = true;
  3583. oilLevel = oilLevel - (wearRate * (currentRPM * 0.05f));
  3584. if (oilLevel < 0.1f) oilLevel = 0f;
  3585. dmgOilLeak = true;
  3586. }
  3587.  
  3588.  
  3589. if (oilLevel <= 0f)
  3590. {
  3591. soundFail.audio.Stop();
  3592.  
  3593. float deadEngChance = (float)rndNumber.rndRoll(1, 101);
  3594. if (deadEngChance < 50f)
  3595. {
  3596. runState = "Seized";
  3597. currentRPM = Mathf.Lerp(currentRPM, 0f, 5f);
  3598. }
  3599. else if (deadEngChance > 50f)
  3600. {
  3601. runState = "Dead";
  3602. currentRPM = Mathf.Lerp(currentRPM, 0f, 5f);
  3603. }
  3604.  
  3605. }
  3606.  
  3607.  
  3608. }
  3609.  
  3610. }
  3611.  
  3612.  
  3613.  
  3614. }
  3615. if (oilTemp < oilMaxTemp && runState == "Overheated")
  3616. {
  3617. runState = "Running";
  3618. }
  3619.  
  3620. if (oilTemp < oilMaxTemp && oilTemp > (oilMaxTemp * 0.5f) && runState == "Running")
  3621. {
  3622. coldLoss = 1f;
  3623. }
  3624. if (oilTemp < oilMaxTemp && oilTemp < (oilMaxTemp * 0.25f) && runState == "Running")
  3625. {
  3626.  
  3627. coldLoss = 0.5f; //it will run worse if it's under 1/4 max oil temp .
  3628.  
  3629. if (throttleActual > 0.25f)//running above this can cause backfires - causing premature wear on the electrical system.
  3630. {
  3631. float randomBackFireCheck = rndNumber.rndRoll(1, 1001);
  3632. if (randomBackFireCheck < 4f)
  3633. {
  3634. dmgMissFire = true;
  3635. missFire();
  3636. }
  3637. }
  3638.  
  3639. if (currentRPM > engineRedline)
  3640. {
  3641. float randomBackFireCheck = rndNumber.rndRoll(1, 1001);
  3642. if (randomBackFireCheck < 2f)
  3643. {
  3644. dmgMissFire = true;
  3645. missFire();
  3646. dmgOilLeak = true;
  3647. }
  3648. }
  3649.  
  3650. }
  3651. #region Engine Stalled, Seized or Dead
  3652. if (runState == "Stalled")
  3653. {
  3654.  
  3655.  
  3656. if (engTemp > FlightGlobals.getExternalTemperature((float)this.vessel.altitude, this.vessel.mainBody))
  3657. {
  3658. engTemp = engTemp - coolingEff;
  3659. oilTemp = engTemp;
  3660. }
  3661. currentRPM = Mathf.Lerp(currentRPM, 0f, 1f);
  3662. soundDrone.audio.Stop();
  3663. soundGroup.audio.Stop();
  3664. soundFail.audio.Stop();
  3665. soundSuperC.audio.Stop();
  3666.  
  3667. oilBurningFX.particleEmitter.emit = false;
  3668. lightOne.enabled = false;
  3669. oilBurnTrailFX.particleEmitter.emit = false;
  3670. if (exhaustFX1 != null)
  3671. {
  3672. exhaustFX1.SetActive(false);
  3673. }
  3674.  
  3675. }
  3676.  
  3677. if (runState == "Overheated") //is running and overheated - this is a running but damaged runState.
  3678. {
  3679. //print("Warning Engine Overheated!");
  3680. }
  3681.  
  3682. if (runState == "Seized")
  3683. {
  3684.  
  3685. soundDrone.audio.Stop();
  3686. soundGroup.audio.Stop();
  3687. soundFail.audio.Stop();
  3688. soundSuperC.audio.Stop();
  3689.  
  3690. oilBurningFX.particleEmitter.emit = false;
  3691. lightOne.enabled = false;
  3692. oilBurnTrailFX.particleEmitter.emit = false;
  3693. if (engTemp > FlightGlobals.getExternalTemperature((float)this.vessel.altitude, this.vessel.mainBody))
  3694. {
  3695. engTemp = engTemp - coolingEff;
  3696. oilTemp = engTemp;
  3697. }
  3698. if (exhaustFX1 != null)
  3699. {
  3700. exhaustFX1.SetActive(false);
  3701. }
  3702.  
  3703. }
  3704.  
  3705. if (runState == "Dead")
  3706. {
  3707.  
  3708. soundDrone.audio.Stop();
  3709. soundGroup.audio.Stop();
  3710. soundFail.audio.Stop();
  3711. soundSuperC.audio.Stop();
  3712.  
  3713. oilBurningFX.particleEmitter.emit = false;
  3714. lightOne.enabled = false;
  3715. oilBurnTrailFX.particleEmitter.emit = false;
  3716. if (engTemp > FlightGlobals.getExternalTemperature((float)this.vessel.altitude, this.vessel.mainBody))
  3717. {
  3718. engTemp = engTemp - coolingEff;
  3719. oilTemp = engTemp;
  3720. }
  3721.  
  3722. if (exhaustFX1 != null)
  3723. {
  3724. exhaustFX1.SetActive(false);
  3725. }
  3726.  
  3727. }
  3728. #endregion
  3729.  
  3730.  
  3731.  
  3732. }
  3733.  
  3734. public void checkRandomFailure()
  3735. {
  3736. float randChangeToFail = (float)rndNumber.rndRoll(1, 1001);
  3737.  
  3738. if (randChangeToFail <= 3f || runState == "Overheated" && randChangeToFail <= 6f) //while overheated the chance of a failure is 2x...
  3739. {
  3740. float failureChoose = (float)rndNumber.rndRoll(1, 31);
  3741. if (failureChoose <= 10f)
  3742. {
  3743. dmgOilLeak = true;
  3744. oilLeak();
  3745. print("Oil Leaking!");
  3746. }
  3747. if (failureChoose > 10f && failureChoose <= 20f) missFire();
  3748. if (failureChoose > 20f && failureChoose <= 30f) fuelCutout();
  3749.  
  3750. }
  3751.  
  3752. }
  3753.  
  3754. public void oilLeak()
  3755. {
  3756. if (runState == "Running" && dmgOilLeak == true || runState == "Overheated" && dmgOilLeak == true)
  3757. {
  3758. oilLevel = oilLevel - (wearRate * (currentRPM * 0.02f));
  3759. if (oilLevel < 0f) oilLevel = 0f;
  3760. }
  3761. }
  3762.  
  3763. public void missFire()
  3764. {
  3765. if (runState == "Running" && dmgMissFire == true || runState == "Overheated" && dmgMissFire == true)
  3766. {
  3767.  
  3768.  
  3769. createBackfire();
  3770. float randomWear = UnityEngine.Random.Range(0f, 1f);
  3771. sparkEff = sparkEff - (randomWear * (wearRate * 100f));
  3772. if (sparkEff < 0f) sparkEff = 0f;
  3773. dmgMissFire = false;
  3774. print("Missfire! Spark efficiency is now: " + sparkEff);
  3775. }
  3776. }
  3777.  
  3778. public void fuelCutout()
  3779. {
  3780. if (runState == "Running" && dmgFuelCutout == true || runState == "Overheated" && dmgFuelCutout == true)
  3781. {
  3782. print("Fuel issue... Stalled!");
  3783. runState = "Stalled";
  3784. dmgFuelCutout = false;
  3785. }
  3786. }
  3787.  
  3788. public void checkThrottle()
  3789. {
  3790. if (!this.vessel.isEVA && this.vessel == FlightGlobals.ActiveVessel)
  3791. {
  3792. if (useMultiThrottle == true && useWThrottle == false)
  3793. {
  3794. throttleActual = guiThrottle;
  3795. }
  3796. else throttleActual = FlightInputHandler.state.mainThrottle;
  3797.  
  3798. lastGoodThrottle = throttleActual;
  3799. }
  3800. else if (this.vessel.isEVA || this.vessel != FlightGlobals.ActiveVessel)
  3801. {
  3802. throttleActual = lastGoodThrottle;
  3803. }
  3804.  
  3805.  
  3806.  
  3807. }
  3808.  
  3809. public void checkKerbal()
  3810. {
  3811.  
  3812. ProtoCrewMember getStats = FlightGlobals.ActiveVessel.GetVesselCrew().FirstOrDefault();
  3813. lastKerbalName = getStats.name;
  3814.  
  3815. bool oneTime = true;
  3816.  
  3817.  
  3818. foreach (ProtoCrewMember crewMember in this.vessel.GetVesselCrew())
  3819. {
  3820.  
  3821. if (lastKerbalName == crewMember.name && oneTime == true)
  3822. {
  3823. ourKerbalsStupid = crewMember.stupidity;
  3824. ourKerbalIsBadass = crewMember.isBadass;
  3825. ourKerbalCourage = crewMember.courage;
  3826.  
  3827. string showKerStats = crewMember.name + " has a technicial rating of " + (1f - ourKerbalsStupid);
  3828. ScreenMessages.PostScreenMessage(new ScreenMessage(showKerStats, 3f, ScreenMessageStyle.UPPER_CENTER));
  3829. oneTime = false;
  3830. }
  3831. }
  3832.  
  3833.  
  3834.  
  3835. }
  3836.  
  3837. public void createBackfire()
  3838. {
  3839. GameObject fxBFInstance = new GameObject();
  3840.  
  3841. try
  3842. {
  3843.  
  3844. fxBFInstance = GameDatabase.Instance.GetModel("IDiCEr1/Effects/BackfireFX/model");
  3845. }
  3846. catch
  3847. {
  3848. print("Problem locating BackfireFX");
  3849. }
  3850.  
  3851. if (fxBFInstance != null && exh != null)
  3852. {
  3853. if (soundBackF.audio.isPlaying == false) soundBackF.audio.Play();
  3854. fxBFInstance.SetActive(true);
  3855. fxBFInstance.transform.parent = this.part.transform;
  3856. fxBFInstance.transform.position = exh[lastCylToFire].position; //current cylinder position
  3857. fxBFInstance.transform.localRotation = exh[lastCylToFire].localRotation; //???
  3858.  
  3859. Destroy(fxBFInstance, 2f);
  3860. }
  3861. }
  3862.  
  3863. public void persistantRunRough()
  3864. {
  3865. float randomBackFireCheck = rndNumber.rndRoll(0, 100);
  3866. if (randomBackFireCheck < 2f)
  3867. {
  3868. dmgMissFire = true;
  3869. missFire();
  3870. }
  3871. }
  3872.  
  3873. public void ApplyDamage(float damageState)
  3874. {
  3875. print("Inside ApplyDamage for ICE!");
  3876. if (damageState < 1f)
  3877. {
  3878. float specialDamage = (float)rndNumber.rndRoll(0, 100);
  3879. if (specialDamage < 50f)
  3880. {
  3881. float doDamage = (float)rndNumber.rndRoll(0, 100);
  3882. if (doDamage < 40f)
  3883. {
  3884. wearRate = 0.0005f;
  3885. ScreenMessages.PostScreenMessage(new ScreenMessage("Engine doesn't sound right!", 3f, ScreenMessageStyle.UPPER_CENTER));
  3886. }
  3887. if (doDamage < 60f && doDamage >= 40f)
  3888. {
  3889. ScreenMessages.PostScreenMessage(new ScreenMessage("Engine took damage and stalled! Try to restart it.", 3f, ScreenMessageStyle.UPPER_CENTER));
  3890. runState = "Stalled";
  3891. }
  3892. if (doDamage < 70f && doDamage >= 60f)
  3893. {
  3894. dmgOilLeak = true;
  3895. ScreenMessages.PostScreenMessage(new ScreenMessage("Oil is leaking from the engine!", 3f, ScreenMessageStyle.UPPER_CENTER));
  3896. }
  3897. if (doDamage < 80f && doDamage >= 70f)
  3898. {
  3899. ScreenMessages.PostScreenMessage(new ScreenMessage("Engine sounds really rough! We should land!", 3f, ScreenMessageStyle.UPPER_CENTER));
  3900. dmgOutOfWhack = true;
  3901. }
  3902. if (doDamage < 90f && doDamage >= 80f)
  3903. {
  3904. ScreenMessages.PostScreenMessage(new ScreenMessage("Engine took a serious hit, I think something is wrong!", 3f, ScreenMessageStyle.UPPER_CENTER));
  3905. enginePerformanceMulti *= (float)rndNumber.rndRoll(1, 100) * 0.01f;
  3906.  
  3907. }
  3908. if (doDamage == 100f && doDamage >= 90f)
  3909. {
  3910. //engineHeatup???
  3911. ScreenMessages.PostScreenMessage(new ScreenMessage("Engine was hit, still sounds and looks okay...", 3f, ScreenMessageStyle.UPPER_CENTER));
  3912. }
  3913. }
  3914.  
  3915. }
  3916. if (damageState == 1f)//normal/fixed state.... reset all to normal
  3917. {
  3918. //range = origRange;
  3919. //isJammed = false;
  3920. }
  3921.  
  3922. }
  3923.  
  3924. }
  3925.  
  3926. public class cylStats
  3927. {
  3928. public int iceCylNum;
  3929. public int powerArcOn;
  3930. public int powerArcOff;
  3931. public float cylForceIdeal;
  3932. public float useFuelRate;
  3933. public float useAirRate;
  3934. public float addHeat;
  3935. }
  3936.  
  3937.  
  3938.  
  3939.  
  3940. public class rndNumber
  3941. {
  3942.  
  3943. public static System.Random rnd = new System.Random();
  3944. public static int rndRoll(int min, int max)
  3945. {
  3946. return rnd.Next(min, max);
  3947. }
  3948.  
  3949. public static System.Random rnd2 = new System.Random();
  3950. public static double rndDouble()
  3951. {
  3952. return rnd2.NextDouble();
  3953. }
  3954.  
  3955.  
  3956. }
  3957.  
  3958. public class IDliqCool : PartModule
  3959. {
  3960.  
  3961. [KSPField]
  3962. public float radSize = 0.3f;
  3963.  
  3964. [KSPField]
  3965. public float thermoOpen = 170f;
  3966.  
  3967. [KSPField]
  3968. public float thermoClose = 155f;
  3969.  
  3970. public float boilOver = 190f;
  3971.  
  3972. [KSPField]
  3973. public float flowRate = 0.2f;//LPS
  3974.  
  3975. [KSPField(guiActive = true, guiName = "Open x100% ")]
  3976. public float flapPos = 0f;//0 closed 1 full open
  3977.  
  3978. public bool doItOnce = true;
  3979.  
  3980. public bool hasRadFlap = true;
  3981.  
  3982. public bool doChange = false;
  3983.  
  3984. public float inputTemp = 0f;
  3985.  
  3986. public Transform radFlap;
  3987.  
  3988. public void FixedUpdate()
  3989. {
  3990. if (!HighLogic.LoadedSceneIsFlight) return;
  3991. if (doItOnce == true)
  3992. {
  3993. try
  3994. {
  3995. radFlap = part.FindModelTransform("radFlap");
  3996. }
  3997. catch
  3998. {
  3999. Debug.Log("Can't find radFlap");
  4000. hasRadFlap = false;
  4001. }
  4002.  
  4003. if (hasRadFlap == true)
  4004. {
  4005. radFlap.Rotate(0f, 0f, -90f);
  4006. }
  4007.  
  4008. doItOnce = false;
  4009. }
  4010.  
  4011. if (hasRadFlap == true && flapPos < 1f && inputTemp > thermoOpen)
  4012. {
  4013. flapPos += 0.01f;
  4014. radFlap.Rotate(0f, 0f, +1f);
  4015. }
  4016. if (hasRadFlap == true && flapPos > 0f && inputTemp < thermoClose)
  4017. {
  4018. flapPos -= 0.01f;
  4019. radFlap.Rotate(0f, 0f, -1f);
  4020. }
  4021. if (flapPos < 0f)
  4022. {
  4023. flapPos = 0f;
  4024. }
  4025. if (flapPos > 1f)
  4026. {
  4027. flapPos = 1f;
  4028. }
  4029.  
  4030.  
  4031. }
  4032.  
  4033. }
  4034.  
  4035. public class IDdDrive : PartModule
  4036. {
  4037.  
  4038. [KSPField(isPersistant = true, guiActiveEditor = true, guiActive = false, guiName = "Forward Gears"), UI_FloatRange(minValue = 1f, maxValue = 6f, stepIncrement = 1f)]
  4039. public float numOfGears = 5;//forward gears
  4040.  
  4041. [KSPField(isPersistant = true, guiActiveEditor = true, guiActive = false, guiName = "First Ratio"), UI_FloatRange(minValue = 2.85f, maxValue = 3.85f, stepIncrement = 0.05f)]
  4042. public float firstGear = 3.85f;//ratio of gear
  4043.  
  4044. [KSPField(isPersistant = true, guiActiveEditor = true, guiActive = false, guiName = "Second Ratio"), UI_FloatRange(minValue = 1.8f, maxValue = 2.75f, stepIncrement = 0.05f)]
  4045. public float secondGear = 2.2f;//ratio of gear
  4046.  
  4047. [KSPField(isPersistant = true, guiActiveEditor = true, guiActive = false, guiName = "Third Ratio"), UI_FloatRange(minValue = 1.3f, maxValue = 1.85f, stepIncrement = 0.05f)]
  4048. public float thirdGear = 1.4f;//ratio of gear
  4049.  
  4050. [KSPField(isPersistant = true, guiActiveEditor = true, guiActive = false, guiName = "Fourth Ratio"), UI_FloatRange(minValue = 0.9f, maxValue = 1.45f, stepIncrement = 0.05f)]
  4051. public float fourthGear = 1.0f;//ratio of gear
  4052.  
  4053. [KSPField(isPersistant = true, guiActiveEditor = true, guiActive = false, guiName = "Fifth Ratio"), UI_FloatRange(minValue = 0.8f, maxValue = 1.2f, stepIncrement = 0.05f)]
  4054. public float fifthGear = 0.81f;//ratio of gear
  4055.  
  4056. [KSPField(isPersistant = true, guiActiveEditor = true, guiActive = false, guiName = "Sixth Ratio"), UI_FloatRange(minValue = 0.5f, maxValue = 0.85f, stepIncrement = 0.05f)]
  4057. public float sixthGear = 0.78f;//ratio of gear
  4058.  
  4059. [KSPField(isPersistant = true, guiActiveEditor = true, guiActive = false, guiName = "Rev. Ratio"), UI_FloatRange(minValue = 2.85f, maxValue = 3.85f, stepIncrement = 0.05f)]
  4060. public float reverseGear = 3.70f;//ratio of gear
  4061.  
  4062. [KSPField(isPersistant = true, guiActiveEditor = true, guiActive = false, guiName = "Final Ratio"), UI_FloatRange(minValue = 2.7f, maxValue = 4.1f, stepIncrement = 0.1f)]
  4063. public float finalDrive = 2.9f;// Differential ratio
  4064.  
  4065. [KSPField(isPersistant = true, guiActiveEditor = true, guiActive = true, guiName = "Slip Lock %"), UI_FloatRange(minValue = 0.1f, maxValue = 1.0f, stepIncrement = 0.1f)]
  4066. public float limitedSlip = 0.1f;// Differential ratio
  4067.  
  4068. [KSPField(isPersistant = true, guiActiveEditor = true, guiActive = true, guiName = "Slip Lock"), UI_Toggle(controlEnabled = false, disabledText = "No", enabledText = "Yes")]
  4069. public bool lsdEnabled = false;
  4070.  
  4071. public bool inReverse = false;
  4072.  
  4073. public bool inNeutral = true;
  4074.  
  4075. public float gearedForceMulti = 0f;
  4076.  
  4077. [KSPField]
  4078. public float shiftTime = 0.125f;
  4079.  
  4080. [KSPField]
  4081. public float dragInGearMulti = 1f;
  4082.  
  4083. [KSPField]
  4084. public bool isDamaged = false;
  4085.  
  4086. [KSPField(guiActiveEditor = false, guiActive = true, guiName = "RPM Out")]
  4087. public float rpmOutput = 0.0f;
  4088. [KSPField(guiActiveEditor = false, guiActive = true, guiName = "In Gear")]
  4089. public int currentGear = 0;
  4090. [KSPField(guiActiveEditor = false, guiActive = true, guiName = "RPM In")]
  4091. public float inputRPM = 0.0f;
  4092. public bool firstRun = true;
  4093. public IDice getICEOutput;
  4094. public List<IDice> getAllICE = new List<IDice>();
  4095. public float coupledICEOutput = 0f;
  4096.  
  4097. public float dmgMulti = 1f;
  4098.  
  4099. public override void OnStart(PartModule.StartState state)
  4100. {
  4101. base.OnStart(state);
  4102.  
  4103. if (HighLogic.LoadedSceneIsFlight)
  4104. {
  4105. foreach (Part aPart in vessel.Parts)
  4106. {
  4107. foreach (PartModule aModule in aPart.Modules)
  4108. {
  4109. if (aModule is IDice)
  4110. {
  4111. IDice thisEngine = aModule.GetComponent<IDice>();
  4112.  
  4113. getAllICE.Add(thisEngine);
  4114. print("Added an engine");
  4115. }
  4116. }
  4117.  
  4118.  
  4119. }
  4120.  
  4121. }
  4122. }
  4123.  
  4124.  
  4125. public void Update()
  4126. {
  4127. if (!HighLogic.LoadedSceneIsFlight) return;
  4128.  
  4129. if (this.vessel == FlightGlobals.ActiveVessel)
  4130. {
  4131. if (Input.GetKeyDown(KeyCode.PageUp))
  4132. {
  4133. bool changeOnce = true;
  4134.  
  4135. if (currentGear < numOfGears)
  4136. {
  4137. if (inReverse == false && changeOnce == true)
  4138. {
  4139. currentGear = currentGear + 1;
  4140. print("Shifted into " + currentGear);
  4141. ScreenMessages.PostScreenMessage(new ScreenMessage("Shifted into " + currentGear, 2f, ScreenMessageStyle.UPPER_CENTER));
  4142. changeOnce = false;
  4143. if (FlightInputHandler.state.mainThrottle > 0.1f)
  4144. {
  4145. FlightInputHandler.state.mainThrottle *= 0.65f;
  4146. if (FlightInputHandler.state.mainThrottle < 0.1f)
  4147. {
  4148. FlightInputHandler.state.mainThrottle = 0.1f;
  4149. }
  4150. }
  4151. }
  4152. if (inReverse == true && changeOnce == true)
  4153. {
  4154. inReverse = false;
  4155. inNeutral = true;
  4156. currentGear = 0;
  4157. print("Shifted into Neutral");
  4158. ScreenMessages.PostScreenMessage(new ScreenMessage("Neutral Selected", 4f, ScreenMessageStyle.UPPER_CENTER));
  4159. changeOnce = false;
  4160. }
  4161.  
  4162. }
  4163.  
  4164.  
  4165.  
  4166. }
  4167. if (Input.GetKeyDown(KeyCode.PageDown))
  4168. {
  4169. bool changeOnce = true;
  4170.  
  4171. if (currentGear > 1 && changeOnce == true)
  4172. {
  4173. currentGear = currentGear - 1;
  4174. print("Shifted into " + currentGear);
  4175. ScreenMessages.PostScreenMessage(new ScreenMessage("Shifted back to " + currentGear, 2f, ScreenMessageStyle.UPPER_CENTER));
  4176. changeOnce = false;
  4177. if (FlightInputHandler.state.mainThrottle > 0.1f)
  4178. {
  4179. FlightInputHandler.state.mainThrottle *= 1.35f;
  4180. if (FlightInputHandler.state.mainThrottle > 1f)
  4181. {
  4182. FlightInputHandler.state.mainThrottle = 1f;
  4183. }
  4184. }
  4185. }
  4186. if (currentGear == 1 && changeOnce == true)
  4187. {
  4188. currentGear = 0;
  4189. inNeutral = true;
  4190. print("Shifted into Neutral");
  4191. ScreenMessages.PostScreenMessage(new ScreenMessage("Neutral Selected", 4f, ScreenMessageStyle.UPPER_CENTER));
  4192. changeOnce = false;
  4193. }
  4194. if (currentGear == 0 && changeOnce == true)
  4195. {
  4196. currentGear = -1;
  4197. inReverse = true;
  4198. inNeutral = false;
  4199. print("Shifted into Reverse");
  4200. ScreenMessages.PostScreenMessage(new ScreenMessage("Reverse Gear Selected", 4f, ScreenMessageStyle.UPPER_CENTER));
  4201. changeOnce = false;
  4202.  
  4203. }
  4204.  
  4205.  
  4206. }
  4207. }
  4208.  
  4209. }
  4210.  
  4211. public void FixedUpdate()
  4212. {
  4213. if (!HighLogic.LoadedSceneIsFlight) return;
  4214.  
  4215.  
  4216.  
  4217. if (firstRun == true && this.vessel == FlightGlobals.ActiveVessel)
  4218. {
  4219. currentGear = 0;
  4220. getICEOutput = this.vessel.FindPartModulesImplementing<IDice>().FirstOrDefault();
  4221.  
  4222. firstRun = false;
  4223. }
  4224.  
  4225. if (getICEOutput != null)
  4226. {
  4227. coupledICEOutput = 0f;
  4228. float collectInputRPM = 0f;
  4229.  
  4230. for (int i = 0; i < getAllICE.Count; i++)
  4231. {
  4232. if (getAllICE[i].lastCylForce > 0f && getAllICE[i].coupleOutput == true)
  4233. {
  4234. coupledICEOutput += getAllICE[i].lastCylForce;
  4235. collectInputRPM += getAllICE[i].currentRPM;
  4236. }
  4237. }
  4238.  
  4239. inputRPM = collectInputRPM / (float)getAllICE.Count;
  4240.  
  4241. if (inputRPM > 0.0f)
  4242. {
  4243. if (currentGear == 0) inNeutral = true;
  4244.  
  4245. if (currentGear == 1)
  4246. {
  4247. inNeutral = false;
  4248.  
  4249. gearedForceMulti = (firstGear * finalDrive) * dmgMulti;
  4250. rpmOutput = (inputRPM / firstGear) / finalDrive;
  4251. }
  4252. if (currentGear == 2)
  4253. {
  4254. inNeutral = false;
  4255.  
  4256. gearedForceMulti = (secondGear * finalDrive) * dmgMulti;
  4257. rpmOutput = (inputRPM / secondGear) / finalDrive;
  4258. }
  4259. if (currentGear == 3)
  4260. {
  4261. inNeutral = false;
  4262.  
  4263. gearedForceMulti = (thirdGear * finalDrive) * dmgMulti;
  4264. rpmOutput = (inputRPM / thirdGear) / finalDrive;
  4265. }
  4266. if (currentGear == 4)
  4267. {
  4268. inNeutral = false;
  4269.  
  4270. gearedForceMulti = (fourthGear * finalDrive) * dmgMulti;
  4271. rpmOutput = (inputRPM / fourthGear) / finalDrive;
  4272. }
  4273. if (currentGear == 5)
  4274. {
  4275. inNeutral = false;
  4276.  
  4277. gearedForceMulti = (fifthGear * finalDrive) * dmgMulti;
  4278. rpmOutput = (inputRPM / fifthGear) / finalDrive;
  4279. }
  4280. if (currentGear == 6)
  4281. {
  4282. inNeutral = false;
  4283.  
  4284. gearedForceMulti = (sixthGear * finalDrive) * dmgMulti;
  4285. rpmOutput = (inputRPM / sixthGear) / finalDrive;
  4286. }
  4287. if (inNeutral == true)
  4288. {
  4289. currentGear = 0;
  4290. gearedForceMulti = 0f;
  4291. rpmOutput = rpmOutput * 0.9995f;
  4292. }
  4293. if (inReverse == true)
  4294. {
  4295. inNeutral = false;
  4296.  
  4297. gearedForceMulti = (reverseGear * finalDrive) * dmgMulti;
  4298. rpmOutput = (inputRPM * reverseGear) / finalDrive;
  4299.  
  4300. }
  4301.  
  4302. }
  4303.  
  4304. if (isDamaged == true) rpmOutput = 0f;
  4305.  
  4306.  
  4307.  
  4308. }
  4309. }
  4310.  
  4311. public void ApplyDamage(float damageState)
  4312. {
  4313. print("Inside ApplyDamage for ICE!");
  4314. if (damageState < 1f)
  4315. {
  4316. dmgMulti = damageState;
  4317. }
  4318. if (damageState == 1f)
  4319. {
  4320. dmgMulti = damageState;
  4321. }
  4322.  
  4323. }
  4324.  
  4325. }
Advertisement
Add Comment
Please, Sign In to add comment