void addRootPart(Part root) { //Debug.Log (String.Format ("[EL GUI] root: {0}", root)); buildCost = new BuildCost (); buildCost.addPart (root); ExShipInfoEventCatcher ec = (ExShipInfoEventCatcher)root.AddModule ("ExShipInfoEventCatcher"); ec.shipinfo = this; }
void addPart(Part part) { Debug.Log (String.Format ("[EL GUI] attach: {0}", part)); buildCost.addPart (part); var ship = EditorLogic.fetch.ship; parts_count = ship.parts.Count; ExShipInfoEventCatcher ec = (ExShipInfoEventCatcher)part.AddModule ("ExShipInfoEventCatcher"); ec.shipinfo = this; }
void AttachCollector(Part toPart) { toPart.AddModule("ModuleExhaustCapture"); ModuleExhaustCapture newModule = toPart.FindModuleImplementing<ModuleExhaustCapture>(); ModuleResource outPutRes = new ModuleResource(); if (primaryResourceName != null && primaryResourceRate != 0 && PartResourceLibrary.Instance.resourceDefinitions.Contains(primaryResourceName)) { outPutRes.name = primaryResourceName; outPutRes.id = PartResourceLibrary.Instance.GetDefinition(primaryResourceName).id; //Do I need this outPutRes.rate = primaryResourceRate*thrustMultiplier; newModule.outputResources.Add(outPutRes); print("PZER: Capture " + outPutRes.name + " " + outPutRes.id + " added with a real rate of " + outPutRes.rate * thrustMultiplier); } else { print("PZER: " + part.partName + " has bad primary resource/rate: " + primaryResourceName +" rate: " + primaryResourceRate); } if (secondaryResourceName != null && secondaryResourceRate != 0 && PartResourceLibrary.Instance.resourceDefinitions.Contains(secondaryResourceName)) { outPutRes.name = secondaryResourceName; outPutRes.id = PartResourceLibrary.Instance.GetDefinition(secondaryResourceName).id; //see above outPutRes.rate = secondaryResourceRate * thrustMultiplier; newModule.outputResources.Add(outPutRes); print("PZER: Secondary capture " + outPutRes.name + " " + outPutRes.id + " added with a real rate of " + outPutRes.rate * thrustMultiplier); } else { print("PZER: " + part.partName + " has bad secondary resource/rate: " + secondaryResourceName + " rate: " + secondaryResourceRate); } newModule.heatIncrease = (float)additionalHeatRate; }
public void PartUnpacked(Part part) { if (HighLogic.LoadedSceneIsFlight == false) return; WBIExtractionMonitor extractionMonitor = null; if (part.FindModuleImplementing<ModuleResourceHarvester>() == null) return; //Add an extraction monitor if needed. extractionMonitor = part.FindModuleImplementing<WBIExtractionMonitor>(); if (extractionMonitor == null) { extractionMonitor = (WBIExtractionMonitor)part.AddModule("WBIExtractionMonitor"); extractionMonitor.OnActive(); extractionMonitor.OnStart(PartModule.StartState.Landed); extractionMonitor = null; } }
private void AddPartModule(Part part) { try { if (!part.Modules.Contains("LifeSupportModule")) { Debug.Log("TAC missing!"); ConfigNode node = new ConfigNode("MODULE"); node.AddValue("name", "LifeSupportModule"); part.AddModule(node); } else { Debug.Log("TAC already there!"); } } catch (Exception ex) { Debug.LogError("TAC Life Support (AddLifeSupport) [" + this.GetInstanceID().ToString("X") + "][" + Time.time + "]: Failed to add the part module: " + ex.Message + "\n" + ex.StackTrace); } }
public static void AddDecouplerJointReinforcementModule(Part p) { p.AddModule("KJRDecouplerReinforcementModule"); (p.Modules["KJRDecouplerReinforcementModule"] as KJRDecouplerReinforcementModule).OnPartUnpack(); if (debug) Debug.Log("Added KJRDecouplerReinforcementModule to part " + p.partInfo.title); }
private void EvaAddPartModule(Part part) { try { ConfigNode node = new ConfigNode("MODULE"); node.AddValue("name", "LifeSupportModule"); part.AddModule(node); } catch (Exception ex) { this.LogError("Error adding the part module to EVA (expected?): " + ex.Message + "\n" + ex.StackTrace); } }
void FixedUpdate() { if (!gameObject.activeInHierarchy) { return; } //floating origin and velocity offloading corrections if (!FloatingOrigin.Offset.IsZero() || !Krakensbane.GetFrameVelocity().IsZero()) { transform.position -= FloatingOrigin.OffsetNonKrakensbane; prevPosition -= FloatingOrigin.OffsetNonKrakensbane; startPosition -= FloatingOrigin.OffsetNonKrakensbane; } distanceFromStart = Vector3.Distance(transform.position, startPosition); if (Time.time - startTime < stayTime && transform.parent != null) { transform.rotation = transform.parent.rotation; transform.position = spawnTransform.position; //+(transform.parent.rigidbody.velocity*Time.fixedDeltaTime); } else { if (transform.parent != null && parentRB) { transform.parent = null; rb.isKinematic = false; rb.velocity = parentRB.velocity + Krakensbane.GetFrameVelocityV3f(); } } if (rb && !rb.isKinematic) { //physics if (FlightGlobals.RefFrameIsRotating) { rb.velocity += FlightGlobals.getGeeForceAtPosition(transform.position) * Time.fixedDeltaTime; } //guidance and attitude stabilisation scales to atmospheric density. float atmosMultiplier = Mathf.Clamp01(2.5f * (float) FlightGlobals.getAtmDensity(FlightGlobals.getStaticPressure(transform.position), FlightGlobals.getExternalTemperature(), FlightGlobals.currentMainBody)); //model transform. always points prograde transform.rotation = Quaternion.RotateTowards(transform.rotation, Quaternion.LookRotation(rb.velocity + Krakensbane.GetFrameVelocity(), transform.up), atmosMultiplier * (0.5f * (Time.time - startTime)) * 50 * Time.fixedDeltaTime); if (Time.time - startTime < thrustTime && Time.time - startTime > stayTime) { thrustVector.x = randomThrustDeviation * (1 - (Mathf.PerlinNoise(4 * Time.time, randThrustSeed) * 2)) / massScalar; //this needs to scale w/ rocket mass, or light projectiles will be thrustVector.y = randomThrustDeviation * (1 - (Mathf.PerlinNoise(randThrustSeed, 4 * Time.time) * 2)) / massScalar; //far more affected than heavier ones rb.AddRelativeForce(thrustVector); }//0.012/rocketmass - use .012 as baseline, it's the mass of hte hydra, which the randomTurstdeviation was originally calibrated for } if (Time.time - startTime > thrustTime) { foreach (var pe in pEmitters) { if (pe != null) { pe.emit = false; } } } if (Time.time - startTime > 0.1f + stayTime) { hasPenetrated = true; hasDetonated = false; penTicker = 0; currPosition = transform.position; float dist = (currPosition - prevPosition).magnitude; RocketRay = new Ray(prevPosition, currPosition - prevPosition); var hits = Physics.RaycastAll(RocketRay, dist, 9076737); if (hits.Length > 0) { var orderedHits = hits.OrderBy(x => x.distance); using (var hitsEnu = orderedHits.GetEnumerator()) { while (hitsEnu.MoveNext()) { if (!hasPenetrated || hasDetonated) { break; } RaycastHit hit = hitsEnu.Current; Part hitPart = null; KerbalEVA hitEVA = null; try { hitPart = hit.collider.gameObject.GetComponentInParent <Part>(); hitEVA = hit.collider.gameObject.GetComponentUpwards <KerbalEVA>(); } catch (NullReferenceException e) { Debug.LogWarning("[BDArmory.BDArmory]:NullReferenceException for Kinetic Hit: " + e.Message); return; } if (hitEVA != null) { hitPart = hitEVA.part; // relative velocity, separate from the below statement, because the hitpart might be assigned only above if (hitPart.rb != null) { impactVelocity = (rb.velocity - (hitPart.rb.velocity + Krakensbane.GetFrameVelocityV3f())).magnitude; } else { impactVelocity = rb.velocity.magnitude; } ProjectileUtils.ApplyDamage(hitPart, hit, 1, 1, caliber, rocketMass, impactVelocity, bulletDmgMult, distanceFromStart, explosive, false, sourceVessel, rocketName); break; } if (hitPart != null && hitPart.vessel == sourceVessel) { continue; //avoid autohit; } Vector3 impactVector = rb.velocity; if (hitPart != null && hitPart.rb != null) { // using relative velocity vector instead of just rocket velocity // since KSP vessels can easily be moving faster than rockets impactVector = rb.velocity - (hitPart.rb.velocity + Krakensbane.GetFrameVelocityV3f()); } float hitAngle = Vector3.Angle(impactVector, -hit.normal); if (ProjectileUtils.CheckGroundHit(hitPart, hit, caliber)) { ProjectileUtils.CheckBuildingHit(hit, rocketMass, rb.velocity, bulletDmgMult); Detonate(hit.point, false); return; } impactVelocity = impactVector.magnitude; if (gravitic) { var ME = hitPart.FindModuleImplementing <ModuleMassAdjust>(); if (ME == null) { ME = (ModuleMassAdjust)hitPart.AddModule("ModuleMassAdjust"); } ME.massMod += massMod; ME.duration += BDArmorySettings.WEAPON_FX_DURATION; } if (concussion) { hitPart.rb.AddForceAtPosition(impactVector.normalized * impulse, hit.point, ForceMode.Acceleration); Detonate(hit.point, false); hasDetonated = true; return; //impulse rounds shouldn't penetrate/do damage } float anglemultiplier = (float)Math.Cos(Math.PI * hitAngle / 180.0); float thickness = ProjectileUtils.CalculateThickness(hitPart, anglemultiplier); float penetration = ProjectileUtils.CalculatePenetration(caliber, rocketMass, impactVelocity); float penetrationFactor = ProjectileUtils.CalculateArmorPenetration(hitPart, anglemultiplier, hit, penetration, thickness, caliber); if (penetration > thickness) { rb.velocity = rb.velocity * (float)Math.Sqrt(thickness / penetration); if (penTicker > 0) { rb.velocity *= 0.55f; } } if (penetrationFactor > 1) { hasPenetrated = true; ProjectileUtils.ApplyDamage(hitPart, hit, 1, penetrationFactor, caliber, rocketMass, impactVelocity, bulletDmgMult, distanceFromStart, explosive, false, sourceVessel, rocketName); penTicker += 1; ProjectileUtils.CheckPartForExplosion(hitPart); if (explosive) { transform.position += (rb.velocity * Time.fixedDeltaTime) / 3; Detonate(transform.position, false); hasDetonated = true; } } else // stopped by armor { if (hitPart.rb != null && hitPart.rb.mass > 0) { float forceAverageMagnitude = impactVelocity * impactVelocity * (1f / hit.distance) * rocketMass; float accelerationMagnitude = forceAverageMagnitude / (hitPart.vessel.GetTotalMass() * 1000); hitPart.rb.AddForceAtPosition(impactVector.normalized * accelerationMagnitude, hit.point, ForceMode.Acceleration); if (BDArmorySettings.DRAW_DEBUG_LABELS) { Debug.Log("[BDArmory.PooledRocket]: Force Applied " + Math.Round(accelerationMagnitude, 2) + "| Vessel mass in kgs=" + hitPart.vessel.GetTotalMass() * 1000 + "| rocket effective mass =" + rocketMass); } } hasPenetrated = false; ProjectileUtils.ApplyDamage(hitPart, hit, 1, penetrationFactor, caliber, rocketMass, impactVelocity, bulletDmgMult, distanceFromStart, explosive, false, sourceVessel, rocketName); Detonate(hit.point, false); hasDetonated = true; } if (penTicker >= 2) { Detonate(hit.point, false); return; } if (rb.velocity.magnitude <= 100 && hasPenetrated && (Time.time - startTime > thrustTime)) { if (BDArmorySettings.DRAW_DEBUG_LABELS) { Debug.Log("[BDArmory.PooledRocket]: Rocket ballistic velocity too low, stopping"); } Detonate(hit.point, false); return; } if (!hasPenetrated || hasDetonated) { break; } } } } } else if (FlightGlobals.getAltitudeAtPos(currPosition) <= 0) { Detonate(currPosition, false); } prevPosition = currPosition; if (Time.time - startTime > lifeTime) // life's 10s, quite a long time for faster rockets { Detonate(transform.position, true); } if (distanceFromStart >= maxAirDetonationRange)//rockets are performance intensive, lets cull those that have flown too far away { Detonate(transform.position, false); } if (ProximityAirDetonation(distanceFromStart)) { Detonate(transform.position, false); } }
public void Awake() { // Set inventory module for every eva kerbal KIS_Shared.DebugLog("Set KIS config..."); ConfigNode nodeSettings = GameDatabase.Instance.GetConfigNode("KIS/settings/KISConfig"); if (nodeSettings == null) { KIS_Shared.DebugError("KIS settings.cfg not found or invalid !"); return; } // Set global settings ConfigNode nodeGlobal = nodeSettings.GetNode("Global"); if (nodeGlobal.HasValue("itemDebug")) { ModuleKISInventory.debugContextMenu = bool.Parse(nodeGlobal.GetValue("itemDebug")); } if (nodeGlobal.HasValue("breathableAtmoPressure")) { breathableAtmoPressure = float.Parse(nodeGlobal.GetValue("breathableAtmoPressure")); } ConfigNode nodeEvaInventory = nodeSettings.GetNode("EvaInventory"); ConfigNode nodeEvaPickup = nodeSettings.GetNode("EvaPickup"); ConfigNode nodeStackable = nodeSettings.GetNode("StackableItemOverride"); ConfigNode nodeStackableModule = nodeSettings.GetNode("StackableModule"); // Set stackable items list stackableList.Clear(); foreach (string partName in nodeStackable.GetValues("partName")) { stackableList.Add(partName); } // Set stackable module list stackableModules.Clear(); foreach (string moduleName in nodeStackableModule.GetValues("moduleName")) { stackableModules.Add(moduleName); } //-------Male Kerbal // Adding module to EVA cause an unknown error but work Part evaPrefab = PartLoader.getPartInfoByName("kerbalEVA").partPrefab; try { evaPrefab.AddModule("ModuleKISInventory"); } catch {} try { evaPrefab.AddModule("ModuleKISPickup"); } catch { } // Set inventory module for eva ModuleKISInventory evaInventory = evaPrefab.GetComponent <ModuleKISInventory>(); if (evaInventory) { if (nodeGlobal.HasValue("kerbalDefaultMass")) { evaInventory.kerbalDefaultMass = float.Parse(nodeGlobal.GetValue("kerbalDefaultMass")); } SetInventoryConfig(nodeEvaInventory, evaInventory); evaInventory.invType = ModuleKISInventory.InventoryType.Eva; KIS_Shared.DebugLog("Eva inventory module loaded successfully"); } // Set pickup module for eva ModuleKISPickup evaPickup = evaPrefab.GetComponent <ModuleKISPickup>(); if (evaPickup) { if (nodeEvaPickup.HasValue("grabKey")) { KISAddonPickup.grabKey = nodeEvaPickup.GetValue("grabKey"); } if (nodeEvaPickup.HasValue("attachKey")) { KISAddonPickup.attachKey = nodeEvaPickup.GetValue("attachKey"); } if (nodeEvaPickup.HasValue("allowPartAttach")) { evaPickup.allowPartAttach = bool.Parse(nodeEvaPickup.GetValue("allowPartAttach")); } if (nodeEvaPickup.HasValue("allowStaticAttach")) { evaPickup.allowStaticAttach = bool.Parse(nodeEvaPickup.GetValue("allowStaticAttach")); } if (nodeEvaPickup.HasValue("allowPartStack")) { evaPickup.allowPartStack = bool.Parse(nodeEvaPickup.GetValue("allowPartStack")); } if (nodeEvaPickup.HasValue("maxDistance")) { evaPickup.maxDistance = float.Parse(nodeEvaPickup.GetValue("maxDistance")); } if (nodeEvaPickup.HasValue("grabMaxMass")) { evaPickup.grabMaxMass = float.Parse(nodeEvaPickup.GetValue("grabMaxMass")); } if (nodeEvaPickup.HasValue("dropSndPath")) { evaPickup.dropSndPath = nodeEvaPickup.GetValue("dropSndPath"); } if (nodeEvaPickup.HasValue("attachPartSndPath")) { evaPickup.attachPartSndPath = nodeEvaPickup.GetValue("attachPartSndPath"); } if (nodeEvaPickup.HasValue("detachPartSndPath")) { evaPickup.detachPartSndPath = nodeEvaPickup.GetValue("detachPartSndPath"); } if (nodeEvaPickup.HasValue("attachStaticSndPath")) { evaPickup.attachStaticSndPath = nodeEvaPickup.GetValue("attachStaticSndPath"); } if (nodeEvaPickup.HasValue("detachStaticSndPath")) { evaPickup.detachStaticSndPath = nodeEvaPickup.GetValue("detachStaticSndPath"); } if (nodeEvaPickup.HasValue("draggedIconResolution")) { KISAddonPickup.draggedIconResolution = int.Parse(nodeEvaPickup.GetValue("draggedIconResolution")); } KIS_Shared.DebugLog("Eva pickup module loaded successfully"); } //-------Female Kerbal // Adding module to EVA cause an unknown error but work Part evaFemalePrefab = PartLoader.getPartInfoByName("kerbalEVAfemale").partPrefab; try { evaFemalePrefab.AddModule("ModuleKISInventory"); } catch { } try { evaFemalePrefab.AddModule("ModuleKISPickup"); } catch { } // Set inventory module for eva ModuleKISInventory evaFemaleInventory = evaFemalePrefab.GetComponent <ModuleKISInventory>(); if (evaFemaleInventory) { if (nodeGlobal.HasValue("kerbalDefaultMass")) { evaFemaleInventory.kerbalDefaultMass = float.Parse(nodeGlobal.GetValue("kerbalDefaultMass")); } SetInventoryConfig(nodeEvaInventory, evaFemaleInventory); evaFemaleInventory.invType = ModuleKISInventory.InventoryType.Eva; KIS_Shared.DebugLog("Eva inventory module loaded successfully"); } // Set pickup module for eva ModuleKISPickup evaFemalePickup = evaFemalePrefab.GetComponent <ModuleKISPickup>(); if (evaFemalePickup) { if (nodeEvaPickup.HasValue("grabKey")) { KISAddonPickup.grabKey = nodeEvaPickup.GetValue("grabKey"); } if (nodeEvaPickup.HasValue("attachKey")) { KISAddonPickup.attachKey = nodeEvaPickup.GetValue("attachKey"); } if (nodeEvaPickup.HasValue("allowPartAttach")) { evaFemalePickup.allowPartAttach = bool.Parse(nodeEvaPickup.GetValue("allowPartAttach")); } if (nodeEvaPickup.HasValue("allowStaticAttach")) { evaFemalePickup.allowStaticAttach = bool.Parse(nodeEvaPickup.GetValue("allowStaticAttach")); } if (nodeEvaPickup.HasValue("allowPartStack")) { evaFemalePickup.allowPartStack = bool.Parse(nodeEvaPickup.GetValue("allowPartStack")); } if (nodeEvaPickup.HasValue("maxDistance")) { evaFemalePickup.maxDistance = float.Parse(nodeEvaPickup.GetValue("maxDistance")); } if (nodeEvaPickup.HasValue("grabMaxMass")) { evaFemalePickup.grabMaxMass = float.Parse(nodeEvaPickup.GetValue("grabMaxMass")); } if (nodeEvaPickup.HasValue("dropSndPath")) { evaFemalePickup.dropSndPath = nodeEvaPickup.GetValue("dropSndPath"); } if (nodeEvaPickup.HasValue("attachPartSndPath")) { evaFemalePickup.attachPartSndPath = nodeEvaPickup.GetValue("attachPartSndPath"); } if (nodeEvaPickup.HasValue("detachPartSndPath")) { evaFemalePickup.detachPartSndPath = nodeEvaPickup.GetValue("detachPartSndPath"); } if (nodeEvaPickup.HasValue("attachStaticSndPath")) { evaFemalePickup.attachStaticSndPath = nodeEvaPickup.GetValue("attachStaticSndPath"); } if (nodeEvaPickup.HasValue("detachStaticSndPath")) { evaFemalePickup.detachStaticSndPath = nodeEvaPickup.GetValue("detachStaticSndPath"); } if (nodeEvaPickup.HasValue("draggedIconResolution")) { KISAddonPickup.draggedIconResolution = int.Parse(nodeEvaPickup.GetValue("draggedIconResolution")); } KIS_Shared.DebugLog("Eva pickup module loaded successfully"); } // Set inventory module for every pod with crew capacity KIS_Shared.DebugLog("Loading pod inventory..."); foreach (AvailablePart avPart in PartLoader.LoadedPartsList) { if (avPart.name == "kerbalEVA") { continue; } if (avPart.name == "kerbalEVA_RD") { continue; } if (avPart.name == "kerbalEVAfemale") { continue; } if (!avPart.partPrefab) { continue; } if (avPart.partPrefab.CrewCapacity < 1) { continue; } KIS_Shared.DebugLog("Found part with CrewCapacity : " + avPart.name); for (int i = 0; i < avPart.partPrefab.CrewCapacity; i++) { try { ModuleKISInventory moduleInventory = avPart.partPrefab.AddModule("ModuleKISInventory") as ModuleKISInventory; SetInventoryConfig(nodeEvaInventory, moduleInventory); moduleInventory.podSeat = i; moduleInventory.invType = ModuleKISInventory.InventoryType.Pod; KIS_Shared.DebugLog("Pod inventory module(s) for seat " + i + " loaded successfully"); } catch { KIS_Shared.DebugWarning("Pod inventory module(s) for seat " + i + " can't be loaded !"); } } } }
public static void CheckDamageFX(Part part, float caliber, float penetrationFactor, bool explosivedamage, bool incendiary, string attacker, RaycastHit hitLoc) { if (!BDArmorySettings.BATTLEDAMAGE || BDArmorySettings.PAINTBALL_MODE) { return; } if (ProjectileUtils.IsIgnoredPart(part)) { return; // Ignore ignored parts. } double damageChance = Mathf.Clamp((BDArmorySettings.BD_DAMAGE_CHANCE * ((1 - part.GetDamagePercentage()) * 10) * (penetrationFactor / 2)), 0, 100); //more heavily damaged parts more likely to take battledamage if (BDArmorySettings.BD_TANKS) { if (part.HasFuel()) { var alreadyburning = part.GetComponentInChildren <FireFX>(); var rubbertank = part.FindModuleImplementing <ModuleSelfSealingTank>(); if (rubbertank != null) { if (rubbertank.SSTank && part.GetDamagePercentage() > 0.5f) { return; } } if (penetrationFactor > 1.2) { if (alreadyburning != null) { BulletHitFX.AttachFire(hitLoc, part, caliber, attacker); } else { BulletHitFX.AttachLeak(hitLoc, part, caliber, explosivedamage, incendiary, attacker); } } } } if (BDArmorySettings.BD_FIRES_ENABLED) { if (part.isBattery()) { var alreadyburning = part.GetComponentInChildren <FireFX>(); if (alreadyburning == null) { double Diceroll = UnityEngine.Random.Range(0, 100); if (explosivedamage) { Diceroll *= 0.33; } if (incendiary) { Diceroll *= 0.66; } if (BDArmorySettings.DRAW_DEBUG_LABELS) { Debug.Log("[BDArmory.BattleDamageHandler]: Battery Dice Roll: " + Diceroll); } if (Diceroll <= BDArmorySettings.BD_DAMAGE_CHANCE) { BulletHitFX.AttachFire(hitLoc, part, caliber, attacker); } } } } //AmmoBins if (BDArmorySettings.BD_AMMOBINS && part.GetDamagePercentage() < 0.9f) //explosions have penetration of 0.5, should stop explosions phasing though parts from detonating ammo { var ammo = part.FindModuleImplementing <ModuleCASE>(); if (ammo != null) { ammo.SourceVessel = attacker; //moving this here so shots that destroy ammoboxes outright still report attacker if 'Ammo Explodes When Destroyed' is enabled if (penetrationFactor > 1.2) { double Diceroll = UnityEngine.Random.Range(0, 100); if (incendiary) { Diceroll *= 0.66; } if (BDArmorySettings.DRAW_DEBUG_LABELS) { Debug.Log("[BDArmory.BattleDamageHandler]: Ammo TAC DiceRoll: " + Diceroll + "; needs: " + damageChance); } if (Diceroll <= (damageChance) && part.GetDamagePercentage() < 0.95f) { ammo.DetonateIfPossible(); } } if (!ammo.hasDetonated) //hit didn't destroy box { ammo.SourceVessel = ammo.vessel.GetName(); } } } //Propulsaion Damage if (BDArmorySettings.BD_PROPULSION) { if (part.isEngine() && part.GetDamagePercentage() < 0.95f) //first hit's free { foreach (var engine in part.GetComponentsInChildren <ModuleEngines>()) { bool isSRB = false; bool SRBFuelled = false; if (!engine.allowShutdown && engine.throttleLocked) { isSRB = true; using (IEnumerator <PartResource> resources = part.Resources.GetEnumerator()) while (resources.MoveNext()) { if (resources.Current == null) { continue; } if (resources.Current.resourceName.Contains("SolidFuel")) { if (resources.Current.amount > 1d) { SRBFuelled = true; } } } } if (engine.thrustPercentage > BDArmorySettings.BD_PROP_FLOOR) //engines take thrust damage per hit { //AP does bonus damage engine.thrustPercentage -= (((1 - part.GetDamagePercentage()) * (penetrationFactor / 2)) * BDArmorySettings.BD_PROP_DAM_RATE) * 10; //convert from damagepercent to thrustpercent Mathf.Clamp(engine.thrustPercentage, BDArmorySettings.BD_PROP_FLOOR, 100); //even heavily damaged engines will still put out something if (BDArmorySettings.DRAW_DEBUG_LABELS) { Debug.Log("[BDArmory.BattleDamageHandler]: engine thrust: " + engine.thrustPercentage); } engine.PlayFlameoutFX(true); /* * float enginelevel = engine.thrustPercentage; * if (BDArmorySettings.BD_BALANCED_THRUST) //need to poke this more later, not working properly * { * using (List<Part>.Enumerator pSym = part.symmetryCounterparts.GetEnumerator()) * while (pSym.MoveNext()) * { * if (pSym.Current == null) continue; * if (pSym.Current != part && pSym.Current.vessel == part.vessel) * { * var symEngine = pSym.Current.FindModuleImplementing<ModuleEngines>(); * if (symEngine != null) * { * symEngine.thrustPercentage = enginelevel; * } * } * } * } */ } if (part.GetDamagePercentage() < 0.75f || (part.GetDamagePercentage() < 0.82f && penetrationFactor > 2)) { var leak = part.GetComponentInChildren <FuelLeakFX>(); if (leak == null && !isSRB) //engine isn't a srb { BulletHitFX.AttachLeak(hitLoc, part, caliber, explosivedamage, incendiary, attacker); } } if (part.GetDamagePercentage() < 0.50f || (part.GetDamagePercentage() < 0.625f && penetrationFactor > 2)) { var alreadyburning = part.GetComponentInChildren <FireFX>(); if (isSRB) //srbs are steel tubes full of explosives; treat differently { if ((explosivedamage || incendiary) && SRBFuelled) { BulletHitFX.AttachFire(hitLoc, part, caliber, attacker); } } else { if (alreadyburning == null) { BulletHitFX.AttachFire(hitLoc, part, caliber, attacker, -1, 1, true); } } } if (part.GetDamagePercentage() < (BDArmorySettings.BD_PROP_FLAMEOUT / 100)) { if (engine.EngineIgnited) { if (isSRB) //SRB is lit, and casing integrity fails due to damage; boom { var Rupture = (ModuleCASE)part.AddModule("ModuleCASE"); Rupture.CASELevel = 0; Rupture.DetonateIfPossible(); } else { engine.PlayFlameoutFX(true); engine.Shutdown(); //kill a badly damaged engine and don't allow restart engine.allowRestart = false; } } } } } if (BDArmorySettings.BD_INTAKES) //intake damage { var intake = part.FindModuleImplementing <ModuleResourceIntake>(); if (intake != null) { float HEBonus = 0.7f; if (explosivedamage) { HEBonus = 1.4f; } if (incendiary) { HEBonus = 1.1f; } intake.intakeSpeed *= (1 - (((1 - part.GetDamagePercentage()) * HEBonus) * (BDArmorySettings.BD_PROP_DAM_RATE / 2))); //HE does bonus damage Mathf.Clamp((float)intake.intakeSpeed, 0, 99999); intake.area *= (1 - (((1 - part.GetDamagePercentage()) * HEBonus) / BDArmorySettings.BD_PROP_DAM_RATE)); //HE does bonus damage Mathf.Clamp((float)intake.area, 0.0005f, 99999); //even shredded intake ducting will still get some air to engines if (BDArmorySettings.DRAW_DEBUG_LABELS) { Debug.Log("[BDArmory.BattleDamageHandler]: Intake damage: Current Area: " + intake.area + "; Intake Speed: " + intake.intakeSpeed); } } } if (BDArmorySettings.BD_GIMBALS) //engine gimbal damage { var gimbal = part.FindModuleImplementing <ModuleGimbal>(); if (gimbal != null) { double HEBonus = 1; if (explosivedamage) { HEBonus = 1.4; } if (incendiary) { HEBonus = 1.25; } //gimbal.gimbalRange *= (1 - (((1 - part.GetDamagePercentatge()) * HEBonus) / BDArmorySettings.BD_PROP_DAM_RATE)); //HE does bonus damage double Diceroll = UnityEngine.Random.Range(0, 100); if (BDArmorySettings.DRAW_DEBUG_LABELS) { Debug.Log("[BDArmory.BattleDamageHandler]: Gimbal DiceRoll: " + Diceroll); } if (Diceroll <= (BDArmorySettings.BD_DAMAGE_CHANCE * HEBonus)) { gimbal.enabled = false; gimbal.gimbalRange = 0; if (incendiary) { BulletHitFX.AttachFire(hitLoc, part, caliber, attacker, 20); } } } } } //Aero Damage if (BDArmorySettings.BD_AEROPARTS) { float HEBonus = 1; if (explosivedamage) { HEBonus = 2; //explosive rounds blow bigger holes in wings } Mathf.Clamp(penetrationFactor, 0.1f, 3); HEBonus /= penetrationFactor; //faster rounds punch cleaner holes float liftDam = ((caliber / 20000) * HEBonus) * BDArmorySettings.BD_LIFT_LOSS_RATE; if (part.GetComponent <ModuleLiftingSurface>() != null) { ModuleLiftingSurface wing; wing = part.GetComponent <ModuleLiftingSurface>(); //2x4m wing board = 2 Lift, 0.25 Lift/m2. 20mm round = 20*20=400/20000= 0.02 Lift reduced per hit, 100 rounds to reduce lift to 0. mind you, it only takes ~15 rounds to destroy the wing... if (wing.deflectionLiftCoeff > ((part.mass * 5) + liftDam)) //stock mass/lift ratio is 10; 0.2t wing has 2.0 lift; clamp lift lost at half { wing.deflectionLiftCoeff -= liftDam; } if (BDArmorySettings.DRAW_DEBUG_LABELS) { Debug.Log("[BDArmory.BattleDamageHandler]: " + part.name + "took lift damage: " + liftDam + ", current lift: " + wing.deflectionLiftCoeff); } } if (part.GetComponent <ModuleControlSurface>() != null && part.GetDamagePercentage() > 0.125f) { ModuleControlSurface aileron; aileron = part.GetComponent <ModuleControlSurface>(); if (aileron.deflectionLiftCoeff > ((part.mass * 2.5f) + liftDam)) //stock ctrl surface mass/lift ratio is 5 { aileron.deflectionLiftCoeff -= liftDam; } if (BDArmorySettings.BD_CTRL_SRF) { int Diceroll = (int)UnityEngine.Random.Range(0f, 100f); if (explosivedamage) { HEBonus = 1.2f; } if (incendiary) { HEBonus = 1.1f; } if (Diceroll <= (BDArmorySettings.BD_DAMAGE_CHANCE * HEBonus)) { aileron.actuatorSpeed = 0; aileron.authorityLimiter = 0; aileron.ctrlSurfaceRange = 0; if (incendiary) { BulletHitFX.AttachFire(hitLoc, part, caliber, attacker, 10); } } } } } //Subsystems if (BDArmorySettings.BD_SUBSYSTEMS) { double Diceroll = UnityEngine.Random.Range(0, 100); if (BDArmorySettings.DRAW_DEBUG_LABELS) { Debug.Log("[BDArmory.BattleDamageHandler]: Subsystem DiceRoll: " + Diceroll + "; needs: " + damageChance); } if (Diceroll <= (damageChance) && part.GetDamagePercentage() < 0.95f) { if (part.GetComponent <ModuleReactionWheel>() != null) //should have this be separate dice rolls, else a part with more than one of these will lose them all { ModuleReactionWheel SAS; //could have torque reduced per hit SAS = part.GetComponent <ModuleReactionWheel>(); part.RemoveModule(SAS); } if (part.GetComponent <ModuleRadar>() != null) { ModuleRadar radar; //would need to mod detection curve to degrade performance on hit radar = part.GetComponent <ModuleRadar>(); part.RemoveModule(radar); } if (part.GetComponent <ModuleAlternator>() != null) { ModuleAlternator alt; //damaging alternator is probably just petty. Could reduce output per hit alt = part.GetComponent <ModuleAlternator>(); part.RemoveModule(alt); } if (part.GetComponent <ModuleAnimateGeneric>() != null) { ModuleAnimateGeneric anim; anim = part.GetComponent <ModuleAnimateGeneric>(); // could reduce anim speed, open percent per hit part.RemoveModule(anim); } if (part.GetComponent <ModuleDecouple>() != null) { ModuleDecouple stage; stage = part.GetComponent <ModuleDecouple>(); //decouplers decouple stage.Decouple(); } if (part.GetComponent <ModuleECMJammer>() != null) { ModuleECMJammer ecm; ecm = part.GetComponent <ModuleECMJammer>(); //could reduce ecm strngth/rcs modifier part.RemoveModule(ecm); } if (part.GetComponent <ModuleGenerator>() != null) { ModuleGenerator gen; gen = part.GetComponent <ModuleGenerator>(); part.RemoveModule(gen); } if (part.GetComponent <ModuleResourceConverter>() != null) { ModuleResourceConverter isru; isru = part.GetComponent <ModuleResourceConverter>(); //could reduce efficiency, increase heat per hit part.RemoveModule(isru); } if (part.GetComponent <ModuleResourceConverter>() != null) { ModuleTurret turret; turret = part.GetComponent <ModuleTurret>(); //could reduce traverse speed, range per hit part.RemoveModule(turret); } if (part.GetComponent <ModuleTargetingCamera>() != null) { ModuleTargetingCamera cam; cam = part.GetComponent <ModuleTargetingCamera>(); // gimbal range?? part.RemoveModule(cam); } if (BDArmorySettings.DRAW_DEBUG_LABELS) { Debug.Log("[BDArmory.BattleDamageHandler]: " + part.name + "took subsystem damage"); } if (Diceroll <= (damageChance * 2)) { if (incendiary) { BulletHitFX.AttachFire(hitLoc, part, caliber, attacker, 20); } } } } //Command parts if (BDArmorySettings.BD_COCKPITS && penetrationFactor > 1.2f && part.GetDamagePercentage() < 0.9f) //lets have this be triggered by penetrative damage, not blast splash { if (part.GetComponent <ModuleCommand>() != null) { double ControlDiceRoll = UnityEngine.Random.Range(0, 100); if (BDArmorySettings.DRAW_DEBUG_LABELS) { Debug.Log("[BDArmory.BattleDamageHandler]: Command DiceRoll: " + ControlDiceRoll); } if (ControlDiceRoll <= (BDArmorySettings.BD_DAMAGE_CHANCE * 2)) { using (List <Part> .Enumerator craftPart = part.vessel.parts.GetEnumerator()) { using (var control = VesselModuleRegistry.GetModules <BDModulePilotAI>(part.vessel).GetEnumerator()) // FIXME should this be IBDAIControl? while (control.MoveNext()) { if (control.Current == null) { continue; } control.Current.evasionThreshold += 5; //pilot jitteriness increases control.Current.maxSteer *= 0.9f; if (control.Current.steerDamping > 0.625f) //damage to controls { control.Current.steerDamping -= 0.125f; } if (control.Current.dynamicSteerDampingPitchFactor > 0.625f) { control.Current.dynamicSteerDampingPitchFactor -= 0.125f; } if (control.Current.dynamicSteerDampingRollFactor > 0.625f) { control.Current.dynamicSteerDampingRollFactor -= 0.125f; } if (control.Current.dynamicSteerDampingYawFactor > 0.625f) { control.Current.dynamicSteerDampingYawFactor -= 0.125f; } } //GuardRange reduction to sim canopy/sensor damage? if (BDArmorySettings.DRAW_DEBUG_LABELS) { Debug.Log("[BDArmory.BattleDamageHandler]: " + part.name + "took command damage"); } } } } } if (part.protoModuleCrew.Count > 0 && penetrationFactor > 1.5f && part.GetDamagePercentage() < 0.95f) { if (BDArmorySettings.BD_PILOT_KILLS) { float PilotTAC = Mathf.Clamp((BDArmorySettings.BD_DAMAGE_CHANCE / part.mass), 0.01f, 100); //larger cockpits = greater volume = less chance any hit will pass through a region of volume containing a pilot float killchance = UnityEngine.Random.Range(0, 100); if (BDArmorySettings.DRAW_DEBUG_LABELS) { Debug.Log("[BDArmory.BattleDamageHandler]: Pilot TAC: " + PilotTAC + "; dice roll: " + killchance); } if (killchance <= PilotTAC) //add penetrationfactor threshold? hp threshold? { ProtoCrewMember crewMember = part.protoModuleCrew.FirstOrDefault(x => x != null); if (crewMember != null) { crewMember.UnregisterExperienceTraits(part); //crewMember.outDueToG = true; //implement temp KO to simulate wounding? crewMember.Die(); if (part.IsKerbalEVA()) { part.Die(); } else { part.RemoveCrewmember(crewMember); // sadly, I wasn't able to get the K.I.A. portrait working } //Vessel.CrewWasModified(part.vessel); //Debug.Log("[BDArmory.BattleDamageHandler]: " + crewMember.name + " was killed by damage to cabin!"); if (HighLogic.CurrentGame.Parameters.Difficulty.MissingCrewsRespawn) { crewMember.StartRespawnPeriod(); } //ScreenMessages.PostScreenMessage(crewMember.name + " killed by damage to " + part.vessel.name + part.partName + ".", 5.0f, ScreenMessageStyle.UPPER_LEFT); ScreenMessages.PostScreenMessage("Cockpit snipe on " + part.vessel.GetName() + "! " + crewMember.name + " killed!", 5.0f, ScreenMessageStyle.UPPER_LEFT); BDACompetitionMode.Instance.OnVesselModified(part.vessel); } } } } }
// FIXME Use an object pool for flames? public static void AttachLeak(RaycastHit hit, Part hitPart, float caliber, bool explosive, bool incendiary, string sourcevessel) { if (BDArmorySettings.BATTLEDAMAGE && BDArmorySettings.BD_TANKS) { if (leakFXPool == null) { leakFXPool = FuelLeakFX.CreateLeakFXPool("BDArmory/FX/FuelLeakFX/model"); } var fuelLeak = leakFXPool.GetPooledObject(); var leakFX = fuelLeak.GetComponentInChildren <FuelLeakFX>(); leakFX.AttachAt(hitPart, hit, new Vector3(0.25f, 0f, 0f)); leakFX.transform.localScale = Vector3.one * (caliber / 10); var leak = hitPart.FindModuleImplementing <ModuleDrainFuel>(); if (leak != null) //only apply one leak to engines { if (BDArmorySettings.BD_FIRES_ENABLED) { bool startFire = false; int ammoMod = 10; //10% chance of AP rounds starting fires from sparks/tracers/etc if (explosive) { ammoMod = 33; //33% chance of starting fires from HE rounds } if (incendiary) { ammoMod = 90; //90% chance of starting fires from inc rounds } double Diceroll = UnityEngine.Random.Range(0, 100); if (Diceroll <= ammoMod) { startFire = true; } //Debug.Log("[FIRE DEBUG] diceroll: " + Diceroll); if (startFire) { int leakcount = 0; foreach (var existingLeakFX in hitPart.GetComponentsInChildren <FuelLeakFX>()) { existingLeakFX.lifeTime = 0; //kill leakFX, start fire leakcount++; } leak.drainDuration = 0; AttachFire(hit, hitPart, caliber, sourcevessel, -1, leakcount); } } else { if (!hitPart.isEngine()) { leak.drainDuration += (20 * BDArmorySettings.BD_TANK_LEAK_TIME); leak.drainRate += ((caliber / 100) * BDArmorySettings.BD_TANK_LEAK_RATE); } } } else { leak = (ModuleDrainFuel)hitPart.AddModule("ModuleDrainFuel"); leak.drainRate = ((caliber / 10) * BDArmorySettings.BD_TANK_LEAK_RATE); leak.drainDuration = (BDArmorySettings.BD_TANK_LEAK_TIME); leakFX.lifeTime = (BDArmorySettings.BD_TANK_LEAK_TIME); if (hitPart.isEngine()) { leak.drainDuration = (100 * BDArmorySettings.BD_TANK_LEAK_TIME); leakFX.lifeTime = (100 * BDArmorySettings.BD_TANK_LEAK_TIME); } } if (BDArmorySettings.DRAW_DEBUG_LABELS) { Debug.Log("[BDArmory.BulletHitFX]: BulletHit attaching fuel leak, drainrate: " + leak.drainRate); } fuelLeak.SetActive(true); } }
private void Start() { if (!CompatibilityChecker.IsAllCompatible()) { this.enabled = false; return; } _vessel = gameObject.GetComponent <Vessel>(); this.enabled = true; if (_vessel.rootPart.Modules.Contains("MissileLauncher") && _vessel.parts.Count == 1) { _vessel.rootPart.dragModel = Part.DragModel.CUBE; this.enabled = false; return; } _currentGeoModules = new List <GeometryPartModule>(); for (int i = 0; i < _vessel.parts.Count; i++) { Part p = _vessel.parts[i]; p.maximum_drag = 0; p.minimum_drag = 0; p.angularDrag = 0; /*p.dragModel = Part.DragModel.NONE; * p.dragReferenceVector = Vector3.zero; * p.dragScalar = 0; * p.dragVector = Vector3.zero; * p.dragVectorDir = Vector3.zero; * p.dragVectorDirLocal = Vector3.zero; * p.dragVectorMag = 0; * p.dragVectorSqrMag = 0; * * p.bodyLiftMultiplier = 0; * p.bodyLiftScalar = 0;*/ GeometryPartModule g = p.GetComponent <GeometryPartModule>(); if ((object)g != null) { _currentGeoModules.Add(g); if (g.Ready) { geoModulesReady++; } } if (p.Modules.Contains <KerbalEVA>() || p.Modules.Contains <FlagSite>()) { Debug.Log("Handling Stuff for KerbalEVA / Flag"); g = (GeometryPartModule)p.AddModule("GeometryPartModule"); g.OnStart(StartState()); p.AddModule("FARAeroPartModule").OnStart(StartState()); _currentGeoModules.Add(g); } } GameEvents.onVesselGoOffRails.Add(VesselUpdateEvent); //GameEvents.onVesselChange.Add(VesselUpdateEvent); //GameEvents.onVesselLoaded.Add(VesselUpdate); //GameEvents.onVesselCreate.Add(VesselUpdateEvent); GameEvents.onVesselWasModified.Add(VesselUpdateEvent); RequestUpdateVoxel(false); if (_vessel == null) { _vessel = gameObject.GetComponent <Vessel>(); if (_vessel == null) { return; } } if (_vehicleAero == null) { _vehicleAero = new VehicleAerodynamics(); _vesselIntakeRamDrag = new VesselIntakeRamDrag(); } //Debug.Log("Starting " + _vessel.vesselName + " aero properties"); }
// Method to add Docking Hatches to all parts that have Docking Nodes private void AddHatchModuleToPartPrefabs() { IEnumerable <AvailablePart> parts = PartLoader.LoadedPartsList.Where(p => p.partPrefab != null); foreach (AvailablePart part in parts) { Part partPrefab = part.partPrefab; // If the part does not have any modules set up then move to the next part if (null == partPrefab.Modules) { continue; } List <ModuleDockingNode> listDockNodes = new List <ModuleDockingNode>(); List <ModuleDockingHatch> listDockHatches = new List <ModuleDockingHatch>(); // Build a temporary list of docking nodes to consider. This is necassery can we can not add hatch modules to the modules list while we are enumerating the very same list! foreach (ModuleDockingNode dockNode in partPrefab.Modules.OfType <ModuleDockingNode>()) { listDockNodes.Add(dockNode); } foreach (ModuleDockingHatch dockHatch in partPrefab.Modules.OfType <ModuleDockingHatch>()) { listDockHatches.Add(dockHatch); } foreach (ModuleDockingNode dockNode in listDockNodes) { // Does this docking node have a corresponding hatch? ModuleDockingHatch hatch = null; foreach (ModuleDockingHatch h in listDockHatches) { if (h.IsRelatedDockingNode(dockNode)) { hatch = h; break; } } if (null == hatch) { // There is no corresponding hatch - add one. ConfigNode node = new ConfigNode("MODULE"); node.AddValue("name", "ModuleDockingHatch"); if (dockNode.referenceAttachNode != string.Empty) { Debug.Log("Adding ModuleDockingHatch to part " + part.title + " and the docking node that uses attachNode " + dockNode.referenceAttachNode); node.AddValue("docNodeAttachmentNodeName", dockNode.referenceAttachNode); } else { if (dockNode.nodeTransformName != string.Empty) { Debug.Log("Adding ModuleDockingHatch to part " + part.title + " and the docking node that uses transform " + dockNode.nodeTransformName); node.AddValue("docNodeTransformName", dockNode.nodeTransformName); } } { // This block is required as calling AddModule and passing in the node throws an exception if Awake has not been called. The method Awaken uses reflection to call then private method Awake. See http://forum.kerbalspaceprogram.com/threads/27851 for more information. PartModule pm = partPrefab.AddModule("ModuleDockingHatch"); if (Awaken(pm)) { Debug.Log("Loading the ModuleDockingHatch config"); pm.Load(node); } else { Debug.LogWarning("Failed to call Awaken so the config has not been loaded."); } } } } } }
public static void addUsageModulesToPart(Part part) { // list of modules to add as a string string addModules = ""; // check part resources foreach (PartResource resource in part.Resources) { // electric batteries (ignore empty batts, probably alternator) if (resource.resourceName == "ElectricCharge" && resource.maxAmount > 0.0 && resource.hideFlow == false) { addModules += "usageBatteries;"; } } // check part modules bool addUsagePods = (part.CrewCapacity > 0); foreach (PartModule module in part.Modules) { // add engine usage if (module is ModuleEngines) { addModules += "usageEngines;"; } // add gimbal usage else if (module is ModuleGimbal) { addModules += "usageGimbal;"; } // add crewed command pod usage else if (module is ModuleCommand) { addModules += "usagePods;"; addUsagePods = false; } // add crewed command pod usage else if (module is ModuleReactionWheel) { addModules += "usageReactionWheels;"; } } // add other modules based on part parameters if (addUsagePods) { addModules += "usagePods;"; } // add generic time usage (aging) for unknown part if no other modules were added if (addModules.Length == 0) { KerbalGUIManager.print("Adding usageGeneric to " + part.partInfo.name); part.AddModule("usageGeneric"); } // add known modules else { string[] modulesIds = addModules.Split(new char[] { ';' }, System.StringSplitOptions.RemoveEmptyEntries); foreach (string moduleId in modulesIds) { KerbalGUIManager.print("Adding " + moduleId + " to " + part.partInfo.name); part.AddModule(moduleId); } } }
private void Update() { if (HighLogic.LoadedScene == GameScenes.LOADING || HighLogic.LoadedScene == GameScenes.MAINMENU) { List <AvailablePart> parts = PartLoader.LoadedPartsList; int i = partLoadedIndex; for (; parts != null && i < parts.Count; i++) { AvailablePart ap = parts[i]; if (ap.partUrl != null && ap.partUrl != "") { Part part = ap.partPrefab; TextureUnloaderPartModule module = (TextureUnloaderPartModule)part.AddModule(typeof(TextureUnloaderPartModule).Name); MethodInfo mI = typeof(PartModule).GetMethod("Awake", BindingFlags.NonPublic | BindingFlags.Instance); mI.Invoke(module, null); module.Load(moduleNode); module.Unload(true); } } partLoadedIndex = i; } }
private bool Attach(Part part) { bool attached = false; List<string> toAttach = new List<string>(); // print("scanning " + part.name + " for needed attachments"); foreach (PartModule pm in part.Modules) { foreach (Attachment attach in attachments.FindAll(a => a.attachTo == pm.moduleName && !part.Modules.Contains(a.moduleName))) { if (attach.RestrictionsMet(part)) { toAttach.Add(attach.moduleName); } } } foreach (string a in toAttach) { print("Attaching " + a + " to " + part.name); var pm = part.AddModule(a); attached = true; } return attached; }
public static void AddLaunchClampReinforcementModule(Part p) { p.AddModule("KJRLaunchClampReinforcementModule"); (p.Modules["KJRLaunchClampReinforcementModule"] as KJRLaunchClampReinforcementModule).OnPartUnpack(); Log.dbg("Added KJRLaunchClampReinforcementModule to part ", p.partInfo.title); }
public static void AddDecouplerJointReinforcementModule(Part p) { p.AddModule("KJRDecouplerReinforcementModule"); (p.Modules["KJRDecouplerReinforcementModule"] as KJRDecouplerReinforcementModule).OnPartUnpack(); Log.dbg("Added KJRDecouplerReinforcementModule to part ", p.partInfo.title); }
/// <summary> /// Check for bullet collision in the upcoming period. /// </summary> /// <param name="period">Period to consider, typically Time.fixedDeltaTime</param> /// <param name="reverse">Also perform raycast in reverse to detect collisions from rays starting within an object.</param> /// <returns>true if a collision is detected, false otherwise.</returns> public bool CheckBulletCollision(float period, bool reverse = false) { //reset our hit variables to default state hasPenetrated = true; hasDetonated = false; hasRicocheted = false; penTicker = 0; currPosition = transform.position; float dist = currentVelocity.magnitude * period; bulletRay = new Ray(currPosition, currentVelocity + 0.5f * period * FlightGlobals.getGeeForceAtPosition(transform.position)); var hits = Physics.RaycastAll(bulletRay, dist, 9076737); if (reverse) { var reverseHits = Physics.RaycastAll(new Ray(currPosition + currentVelocity * period, -currentVelocity), dist, 9076737); for (int i = 0; i < reverseHits.Length; ++i) { reverseHits[i].distance = dist - reverseHits[i].distance; } hits = hits.Concat(reverseHits).ToArray(); } if (hits.Length > 0) { var orderedHits = hits.OrderBy(x => x.distance); using (var hitsEnu = orderedHits.GetEnumerator()) { while (hitsEnu.MoveNext()) { if (!hasPenetrated || hasRicocheted || hasDetonated) { return(true); } RaycastHit hit = hitsEnu.Current; Part hitPart = null; KerbalEVA hitEVA = null; try { hitPart = hit.collider.gameObject.GetComponentInParent <Part>(); hitEVA = hit.collider.gameObject.GetComponentUpwards <KerbalEVA>(); } catch (NullReferenceException e) { Debug.Log("[BDArmory.PooledBullet]:NullReferenceException for Ballistic Hit: " + e.Message); return(true); } if (hitEVA != null) { hitPart = hitEVA.part; // relative velocity, separate from the below statement, because the hitpart might be assigned only above if (hitPart.rb != null) { impactVelocity = (currentVelocity * dragVelocityFactor - (hitPart.rb.velocity + Krakensbane.GetFrameVelocityV3f())).magnitude; } else { impactVelocity = currentVelocity.magnitude * dragVelocityFactor; } distanceTraveled += hit.distance; ProjectileUtils.ApplyDamage(hitPart, hit, 1, 1, caliber, bulletMass, impactVelocity, bulletDmgMult, distanceTraveled, explosive, hasRicocheted, sourceVessel, bullet.name); ExplosiveDetonation(hitPart, hit, bulletRay); KillBullet(); // Kerbals are too thick-headed for penetration... return(true); } if (hitPart != null && hitPart.vessel == sourceVessel) { continue; //avoid autohit; } Vector3 impactVector = currentVelocity; if (hitPart != null && hitPart.rb != null) { // using relative velocity vector instead of just bullet velocity // since KSP vessels might move faster than bullets impactVector = currentVelocity * dragVelocityFactor - (hitPart.rb.velocity + Krakensbane.GetFrameVelocityV3f()); } float hitAngle = Vector3.Angle(impactVector, -hit.normal); if (ProjectileUtils.CheckGroundHit(hitPart, hit, caliber)) { ProjectileUtils.CheckBuildingHit(hit, bulletMass, currentVelocity, bulletDmgMult); if (!RicochetScenery(hitAngle)) { ExplosiveDetonation(hitPart, hit, bulletRay); KillBullet(); distanceTraveled += hit.distance; return(true); } else { DoRicochet(hitPart, hit, hitAngle, hit.distance / dist, period); return(true); } } //Standard Pipeline Hitpoints, Armor and Explosives impactVelocity = impactVector.magnitude; if (massMod != 0) { var ME = hitPart.FindModuleImplementing <ModuleMassAdjust>(); if (ME == null) { ME = (ModuleMassAdjust)hitPart.AddModule("ModuleMassAdjust"); } ME.massMod += massMod; ME.duration += BDArmorySettings.WEAPON_FX_DURATION; } if (impulse != 0 && hitPart.rb != null) { hitPart.rb.AddForceAtPosition(impactVector.normalized * impulse, hit.point, ForceMode.Acceleration); ProjectileUtils.ApplyScore(hitPart, sourceVessel, distanceTraveled, 0, bullet.name); break; //impulse rounds shouldn't penetrate/do damage } float anglemultiplier = (float)Math.Cos(Math.PI * hitAngle / 180.0); float thickness = ProjectileUtils.CalculateThickness(hitPart, anglemultiplier); float penetration = ProjectileUtils.CalculatePenetration(caliber, bulletMass, impactVelocity, apBulletMod); float penetrationFactor = ProjectileUtils.CalculateArmorPenetration(hitPart, anglemultiplier, hit, penetration, thickness, caliber); if (penetration > thickness) { currentVelocity = currentVelocity * (float)Math.Sqrt(thickness / penetration); if (penTicker > 0) { currentVelocity *= 0.55f; } flightTimeElapsed -= period; } if (penetrationFactor >= 2) { //its not going to bounce if it goes right through hasRicocheted = false; } else { if (RicochetOnPart(hitPart, hit, hitAngle, impactVelocity, hit.distance / dist, period)) { hasRicocheted = true; } } if (penetrationFactor > 1 && !hasRicocheted) //fully penetrated continue ballistic damage { hasPenetrated = true; ProjectileUtils.ApplyDamage(hitPart, hit, 1, penetrationFactor, caliber, bulletMass, impactVelocity, bulletDmgMult, distanceTraveled, explosive, hasRicocheted, sourceVessel, bullet.name); penTicker += 1; ProjectileUtils.CheckPartForExplosion(hitPart); //Explosive bullets that penetrate should explode shortly after //if penetration is very great, they will have moved on //checking velocity as they would not be able to come out the other side //if (explosive && penetrationFactor < 3 || currentVelocity.magnitude <= 800f) if (explosive) { //move bullet transform.position += (currentVelocity * period) / 3; distanceTraveled += hit.distance; ExplosiveDetonation(hitPart, hit, bulletRay); hasDetonated = true; KillBullet(); return(true); } } else if (!hasRicocheted) // explosive bullets that get stopped by armor will explode { if (hitPart.rb != null && hitPart.rb.mass > 0) { float forceAverageMagnitude = impactVelocity * impactVelocity * (1f / hit.distance) * (bulletMass - tntMass); float accelerationMagnitude = forceAverageMagnitude / (hitPart.vessel.GetTotalMass() * 1000); hitPart.rb.AddForceAtPosition(impactVector.normalized * accelerationMagnitude, hit.point, ForceMode.Acceleration); if (BDArmorySettings.DRAW_DEBUG_LABELS) { Debug.Log("[BDArmory.PooledBullet]: Force Applied " + Math.Round(accelerationMagnitude, 2) + "| Vessel mass in kgs=" + hitPart.vessel.GetTotalMass() * 1000 + "| bullet effective mass =" + (bulletMass - tntMass)); } } distanceTraveled += hit.distance; hasPenetrated = false; ProjectileUtils.ApplyDamage(hitPart, hit, 1, penetrationFactor, caliber, bulletMass, impactVelocity, bulletDmgMult, distanceTraveled, explosive, hasRicocheted, sourceVessel, bullet.name); ExplosiveDetonation(hitPart, hit, bulletRay); hasDetonated = true; KillBullet(); return(true); } ///////////////////////////////////////////////////////////////////////////////// // penetrated after a few ticks ///////////////////////////////////////////////////////////////////////////////// //penetrating explosive //richochets if ((penTicker >= 2 && explosive) || (hasRicocheted && explosive)) { //detonate ExplosiveDetonation(hitPart, hit, bulletRay, airDetonation); distanceTraveled += hit.distance; return(true); } //bullet should not go any further if moving too slowly after hit //smaller caliber rounds would be too deformed to do any further damage if (currentVelocity.magnitude <= 100 && hasPenetrated) { if (BDArmorySettings.DRAW_DEBUG_LABELS) { Debug.Log("[BDArmory.PooledBullet]: Bullet Velocity too low, stopping"); } KillBullet(); distanceTraveled += hit.distance; return(true); } } //end While } //end enumerator } //end of hits return(false); }
public static void AddLaunchClampReinforcementModule(Part p) { p.AddModule("KJRLaunchClampReinforcementModule"); (p.Modules["KJRLaunchClampReinforcementModule"] as KJRLaunchClampReinforcementModule).OnPartUnpack(); if (debug) Debug.Log("Added KJRLaunchClampReinforcementModule to part " + p.partInfo.title); }
public static void AddBasicDragModule(Part p) { //if (IsNonphysical(p)) // return; //MonoBehaviour.print(p + ": " + p.PhysicsSignificance + " " + p.physicalSignificance); if (p.Modules.Contains("KerbalEVA")) return; p.angularDrag = 0; if (!p.Modules.Contains("ModuleResourceIntake")) { p.minimum_drag = 0; p.maximum_drag = 0; p.dragModelType = "override"; } else return; p.AddModule("FARBasicDragModel"); SetBasicDragModuleProperties(p); }
public UIPartManager(Part p) { this.Part = p; IsActive = false; IsFolderVisible = false; IsActionGroupsVisible = false; IsSymmetryModeVisible = false; baseActionList = new List <UIBaseActionManager>(); actionGroupList = new List <UIActionGroupManager>(); if (Part.Modules.Contains("UIBaseActionManager") || Part.Modules.Contains("UIActionGroupManager")) { //if the part already contains actionManager class, we clean them. List <PartModule> toRemove = new List <PartModule>(); foreach (PartModule item in Part.Modules) { if (item is UIBaseActionManager || item is UIActionGroupManager) { toRemove.Add(item); } } foreach (PartModule mod in toRemove) { Part.Modules.Remove(mod); } } //We create our base action list foreach (BaseAction ba in BaseActionManager.FromParts(p)) { //We create the module through AddModule to get the initialization done UIBaseActionManager man = Part.AddModule("UIBaseActionManager") as UIBaseActionManager; // and we remove it to avoid bloating an eventual save. Part.Modules.Remove(man); man.Action = ba; man.Origin = this; man.Clicked += BaseAction_Clicked; man.Initialize(); baseActionList.Add(man); } // and our action group list //First two specific uiactionmanager as folder. UIActionGroupManager agm = Part.AddModule("UIActionGroupManager") as UIActionGroupManager; Part.Modules.Remove(agm); agm.Events[UIActionGroupManager.EVENTNAME].guiName = " AGM : General"; agm.Origin = this; agm.Isfolder = true; agm.Type = UIActionGroupManager.FolderType.General; agm.Clicked += Folder_Clicked; actionGroupList.Add(agm); agm = Part.AddModule("UIActionGroupManager") as UIActionGroupManager; Part.Modules.Remove(agm); agm.Events[UIActionGroupManager.EVENTNAME].guiName = " AGM : Custom"; agm.Origin = this; agm.Isfolder = true; agm.Type = UIActionGroupManager.FolderType.Custom; agm.Clicked += Folder_Clicked; actionGroupList.Add(agm); //and the rest of action groups foreach (KSPActionGroup ag in Enum.GetValues(typeof(KSPActionGroup))) { if (ag == KSPActionGroup.None) { continue; } agm = Part.AddModule("UIActionGroupManager") as UIActionGroupManager; Part.Modules.Remove(agm); agm.Origin = this; agm.ActionGroup = ag; agm.Clicked += ActionGroup_Clicked; agm.Initialize(); actionGroupList.Add(agm); } agm = Part.AddModule("UIActionGroupManager") as UIActionGroupManager; Part.Modules.Remove(agm); agm.Events[UIActionGroupManager.EVENTNAME].guiName = " Only this part"; agm.Origin = this; agm.IsSymmetrySelector = true; agm.SymmetryMode = UIActionGroupManager.SymmetryType.One; agm.Clicked += SymmetryMode_Clicked; actionGroupList.Add(agm); agm = Part.AddModule("UIActionGroupManager") as UIActionGroupManager; Part.Modules.Remove(agm); agm.Events[UIActionGroupManager.EVENTNAME].guiName = " This part and all symmetry counterparts"; agm.Origin = this; agm.IsSymmetrySelector = true; agm.SymmetryMode = UIActionGroupManager.SymmetryType.All; agm.Clicked += SymmetryMode_Clicked; actionGroupList.Add(agm); }
private void addPartModule(Part p, string module) { try { ConfigNode node = new ConfigNode("MODULE"); node.AddValue("name", module); p.AddModule(node); } catch(Exception e) { Debug.Log("PartDamage: Failed to add PartModule" + module + "--> " + e.Message + "\n" + e.StackTrace); } }
private void EvaAddPartModule(Part part) { try { ConfigNode node = new ConfigNode("MODULE"); node.AddValue("name", "LifeSupportModule"); part.AddModule(node); this.LogWarning("The expected exception did not happen when adding the Life Support part module to the EVA!"); } catch (Exception ex) { if (ex.Message.Contains("Object reference not set")) { this.Log("Adding life support to the EVA part succeeded as expected."); } else { this.LogError("Unexpected error while adding the Life Support part module to the EVA: " + ex.Message + "\n" + ex.StackTrace); } } }
private static bool InstantiateHandler(ConfigNode node, Part ourPart, out Func<string, object> handlerFunction) { handlerFunction = null; var handlerConfiguration = new ConfigNode("MODULE"); node.CopyTo(handlerConfiguration); string moduleName = node.GetValue("name"); string methodName = node.GetValue("method"); // Since we're working with part modules here, and starting in a pod config, // we'll keep one instance per pod, which will let them instantiate with their own config if needed. MonoBehaviour thatModule = null; foreach (PartModule potentialModule in ourPart.Modules) { if (potentialModule.ClassName == moduleName) { thatModule = potentialModule; break; } } if (thatModule == null) { try { thatModule = ourPart.AddModule(handlerConfiguration); } catch { JUtil.LogErrorMessage(null, "Caught exception when trying to instantiate module '{0}'. Something's fishy here", moduleName); } } if (thatModule == null) { JUtil.LogMessage(null, "Warning, variable handler module \"{0}\" could not be loaded. This could be perfectly normal.", moduleName); return false; } foreach (MethodInfo m in thatModule.GetType().GetMethods()) { if (m.Name == node.GetValue("method")) { try { handlerFunction = (Func<string, object>)Delegate.CreateDelegate(typeof(Func<string, object>), thatModule, m); } catch { JUtil.LogErrorMessage(null, "Error, incorrect variable handler configuration for module {0}", moduleName); return false; } break; } } return true; }
private bool FindPartsWithoutFARModel(List <Part> editorShip) { bool returnValue = false; for (int i = 0; i < editorShip.Count; i++) { Part p = editorShip[i]; if (p == null) { continue; } if (p != null && FARAeroUtil.IsNonphysical(p) && p.physicalSignificance != Part.PhysicalSignificance.NONE) { MonoBehaviour.print(p + ": FAR correcting physical significance to fix CoM in editor"); p.physicalSignificance = Part.PhysicalSignificance.NONE; } string title = p.partInfo.title.ToLowerInvariant(); if (p.Modules.Contains("FARBasicDragModel")) { List <PartModule> modulesToRemove = new List <PartModule>(); for (int j = 0; j < p.Modules.Count; j++) { PartModule m = p.Modules[j]; if (!(m is FARBasicDragModel)) { continue; } FARBasicDragModel d = m as FARBasicDragModel; if (d.CdCurve == null || d.ClPotentialCurve == null || d.ClViscousCurve == null || d.CmCurve == null) { modulesToRemove.Add(m); } } if (modulesToRemove.Count > 0) { for (int j = 0; j < modulesToRemove.Count; j++) { PartModule m = modulesToRemove[j]; p.RemoveModule(m); Debug.Log("Removing Incomplete FAR Drag Module"); } if (p.Modules.Contains("FARPayloadFairingModule")) { p.RemoveModule(p.Modules["FARPayloadFairingModule"]); } if (p.Modules.Contains("FARCargoBayModule")) { p.RemoveModule(p.Modules["FARCargoBayModule"]); } if (p.Modules.Contains("FARControlSys")) { p.RemoveModule(p.Modules["FARControlSys"]); } } } if (p is StrutConnector || p is FuelLine || p is ControlSurface || p is Winglet || FARPartClassification.ExemptPartFromGettingDragModel(p, title)) { continue; } FARPartModule q = p.GetComponent <FARPartModule>(); if (q != null && !(q is FARControlSys)) { continue; } bool updatedModules = false; if (FARPartClassification.PartIsCargoBay(p, title)) { if (!p.Modules.Contains("FARCargoBayModule")) { p.AddModule("FARCargoBayModule"); p.Modules["FARCargoBayModule"].OnStart(PartModule.StartState.Editor); FARAeroUtil.AddBasicDragModule(p); p.Modules["FARBasicDragModel"].OnStart(PartModule.StartState.Editor); updatedModules = true; } } if (!updatedModules) { if (FARPartClassification.PartIsPayloadFairing(p, title)) { if (!p.Modules.Contains("FARPayloadFairingModule")) { p.AddModule("FARPayloadFairingModule"); p.Modules["FARPayloadFairingModule"].OnStart(PartModule.StartState.Editor); FARAeroUtil.AddBasicDragModule(p); p.Modules["FARBasicDragModel"].OnStart(PartModule.StartState.Editor); updatedModules = true; } } if (!updatedModules && !p.Modules.Contains("FARBasicDragModel")) { FARAeroUtil.AddBasicDragModule(p); p.Modules["FARBasicDragModel"].OnStart(PartModule.StartState.Editor); updatedModules = true; } } returnValue |= updatedModules; FARPartModule b = p.GetComponent <FARPartModule>(); if (b != null) { b.VesselPartList = editorShip; //This prevents every single part in the ship running this due to VesselPartsList not being initialized } } return(returnValue); }
private void AddPartModule(Part part) { try { if (!part.Modules.Contains("LifeSupportModule")) { this.Log("The LifeSupportModule is missing!"); ConfigNode node = new ConfigNode("MODULE"); node.AddValue("name", "LifeSupportModule"); part.AddModule(node); } else { this.Log("The LifeSupportModule is already there."); } } catch (Exception ex) { this.LogError("Error adding the Part Module (expected?): " + ex.Message + "\n" + ex.StackTrace); } }
protected override void OnStart() { FARLogger.Info("FARVesselAero on " + vessel.name + " reporting startup"); base.OnStart(); if (!CompatibilityChecker.IsAllCompatible()) { this.enabled = false; return; } if (!HighLogic.LoadedSceneIsFlight) { this.enabled = false; return; } _currentGeoModules = new List <GeometryPartModule>(); /*if (!vessel.rootPart) * { * this.enabled = false; * return; * }*/ for (int i = 0; i < vessel.parts.Count; i++) { Part p = vessel.parts[i]; p.maximum_drag = 0; p.minimum_drag = 0; p.angularDrag = 0; /*p.dragModel = Part.DragModel.NONE; * p.dragReferenceVector = Vector3.zero; * p.dragScalar = 0; * p.dragVector = Vector3.zero; * p.dragVectorDir = Vector3.zero; * p.dragVectorDirLocal = Vector3.zero; * p.dragVectorMag = 0; * p.dragVectorSqrMag = 0; * * p.bodyLiftMultiplier = 0; * p.bodyLiftScalar = 0;*/ GeometryPartModule g = p.GetComponent <GeometryPartModule>(); if ((object)g != null) { _currentGeoModules.Add(g); if (g.Ready) { geoModulesReady++; } } if (p.Modules.Contains <KerbalEVA>() || p.Modules.Contains <FlagSite>()) { FARLogger.Info("Handling Stuff for KerbalEVA / Flag"); g = (GeometryPartModule)p.AddModule("GeometryPartModule"); g.OnStart(StartState()); p.AddModule("FARAeroPartModule").OnStart(StartState()); _currentGeoModules.Add(g); } } RequestUpdateVoxel(false); this.enabled = true; //GameEvents.onVesselLoaded.Add(VesselUpdateEvent); //GameEvents.onVesselChange.Add(VesselUpdateEvent); //GameEvents.onVesselLoaded.Add(VesselUpdate); //GameEvents.onVesselCreate.Add(VesselUpdateEvent); //FARLogger.Info("Starting " + _vessel.vesselName + " aero properties"); }
private bool canDamage(Part p) { if(hasModule(p, "ModuleGimbal")) { // engine gimbal damage p.AddModule("DamageTestModule"); return true; } if(hasModule(p, "ModuleEngines")) { // engine damage p.AddModule("DamageTestModule"); return true; } if(hasModule(p, "ModuleParachute")) { // parachute damage p.AddModule("DamageTestModule"); return true; } if(hasModule(p, "ModuleDecouple") || hasModule(p, "ModuleAnchoredDecoupler")) { // decoupler damage p.AddModule("DamageTestModule"); return true; } if(hasModule(p, "ModuleDockingNode")) { // docking port damage p.AddModule("DamageTestModule"); return true; } if(p.Resources.Count > 0) { // fuel tank damage Debug.Log("Found a fuel tank"); addPartModule(p, "DamageTestModule"); return true; } if(hasModule(p, "ModuleResourceIntake")) { // intake damage p.AddModule("DamageTestModule"); return true; } if(hasModule(p, "ModuleWheel")) { // wheel damage p.AddModule("DamageTestModule"); return true; } if(hasModule(p, "ModuleEnviroSensor")) { // sensor damage p.AddModule("DamageTestModule"); return true; } if(hasModule(p, "ModuleDeployableSolarPanel")) { // solar panel damage p.AddModule("DamageTestModule"); return true; } if(hasModule(p, "ModuleGenerator")) { // generator damage p.AddModule("DamageTestModule"); return true; } return false; }
private void FindPartsWithoutFARModel(Vessel v) { for (int i = 0; i < v.Parts.Count; i++) { Part p = v.Parts[i]; if (p == null) { continue; } string title = p.partInfo.title.ToLowerInvariant(); if (p.Modules.Contains("FARBasicDragModel")) { List <PartModule> modulesToRemove = new List <PartModule>(); for (int j = 0; j < p.Modules.Count; j++) { PartModule m = p.Modules[j]; if (!(m is FARBasicDragModel)) { continue; } FARBasicDragModel d = m as FARBasicDragModel; if (d.CdCurve == null || d.ClPotentialCurve == null || d.ClViscousCurve == null || d.CmCurve == null) { modulesToRemove.Add(m); } } if (modulesToRemove.Count > 0) { for (int j = 0; j < modulesToRemove.Count; j++) { PartModule m = modulesToRemove[j]; p.RemoveModule(m); Debug.Log("Removing Incomplete FAR Drag Module"); } if (p.Modules.Contains("FARPayloadFairingModule")) { p.RemoveModule(p.Modules["FARPayloadFairingModule"]); } if (p.Modules.Contains("FARCargoBayModule")) { p.RemoveModule(p.Modules["FARCargoBayModule"]); } if (p.Modules.Contains("FARControlSys")) { p.RemoveModule(p.Modules["FARControlSys"]); } } } if (p is StrutConnector || p is FuelLine || p is ControlSurface || p is Winglet || FARPartClassification.ExemptPartFromGettingDragModel(p, title)) { continue; } if (p.Modules.Contains("ModuleCommand") && !p.Modules.Contains("FARControlSys")) { p.AddModule("FARControlSys"); PartModule m = p.Modules["FARControlSys"]; m.OnStart(PartModule.StartState.Flying); //Debug.Log("Added FARControlSys to " + p.partInfo.title); } FARPartModule q = p.GetComponent <FARPartModule>(); if (q != null && !(q is FARControlSys)) { continue; } bool updatedModules = false; if (FARPartClassification.PartIsCargoBay(p, title)) { if (!p.Modules.Contains("FARCargoBayModule")) { p.AddModule("FARCargoBayModule"); PartModule m = p.Modules["FARCargoBayModule"]; m.OnStart(PartModule.StartState.Flying); FARAeroUtil.AddBasicDragModule(p); m = p.Modules["FARBasicDragModel"]; m.OnStart(PartModule.StartState.Flying); updatedModules = true; } } if (!updatedModules) { if (FARPartClassification.PartIsPayloadFairing(p, title)) { if (!p.Modules.Contains("FARPayloadFairingModule")) { p.AddModule("FARPayloadFairingModule"); PartModule m = p.Modules["FARPayloadFairingModule"]; m.OnStart(PartModule.StartState.Flying); FARAeroUtil.AddBasicDragModule(p); m = p.Modules["FARBasicDragModel"]; m.OnStart(PartModule.StartState.Flying); updatedModules = true; } } if (!updatedModules && !p.Modules.Contains("FARBasicDragModel")) { FARAeroUtil.AddBasicDragModule(p); PartModule m = p.Modules["FARBasicDragModel"]; m.OnStart(PartModule.StartState.Flying); updatedModules = true; } } //returnValue |= updatedModules; FARPartModule b = p.GetComponent <FARPartModule>(); if (b != null) { b.VesselPartList = p.vessel.Parts; //This prevents every single part in the ship running this due to VesselPartsList not being initialized } } UpdateFARPartModules(v); }
private void EvaAddPartModule(Part part) { try { ConfigNode node = new ConfigNode("MODULE"); node.AddValue("name", "LifeSupportModule"); part.AddModule(node); } catch (Exception ex) { Debug.LogError("TAC Life Support (AddLifeSupport) [" + this.GetInstanceID().ToString("X") + "][" + Time.time + "]: Failed to add the part module to EVA: " + ex.Message + "\n" + ex.StackTrace); } }