Advertisement
Guest User

IDICE

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